草庐IT

html - SVG坐标与变换矩阵

coder 2023-07-31 原文

我想在矩形元素上实现svg-edit等功能

  1. 旋转矩形
  2. 调整大小
  3. 拖动

旋转 SVG 矩形效果很好,但当我想调整矩形大小时出现问题。坐标不正确;我使用变换矩阵来旋转 targetelement.setAttribute(变换,旋转(45,cx,cy)) 但是当元素旋转时,坐标会移动。我还使用 inverse 函数来反转变换矩阵,它解决了问题,但它不适用于拖动功能。

最佳答案

我已经创建了一个工作示例,我认为您在我的网站上描述的内容如下:
http://phrogz.net/svg/drag_under_transformation.xhtml

通常,您可以通过以下方式将鼠标光标转换到对象的局部空间:

  1. 创建一个 mousemove 事件处理程序:

    var svg = document.getElementsByTagName('svg')[0];
    document.documentElement.addEventListener('mousemove',function(evt){
      ...
    },false);
    
  2. 在该事件处理程序中,将鼠标坐标(以像素为单位)转换为 SVG 文档的全局空间:

    var pt = svg.createSVGPoint();
    pt.x = evt.clientX;
    pt.y = evt.clientY;
    var globalPoint = pt.matrixTransform(svg.getScreenCTM().inverse());
    
  3. 将全局点转换为您拖动的对象的空间:

    var globalToLocal = dragObject.getTransformToElement(svg).inverse();
    var inObjectSpace = globalPoint.matrixTransform( globalToLocal );
    

为了 Stack Overflow 的后代,这里是我的 SVG+XHTML 演示的完整源代码(以防我的网站出现故障):

<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head> 
<meta http-equiv="content-type" content="application/xhtml+xml;charset=utf-8"/>
<title>Dragging Transformed SVG Elements</title>
<style type="text/css" media="screen">
  html, body {
    background:#eee; margin:0;
    user-select:none; -moz-user-select:none; -webkit-user-select:none;
  }
  p { margin:0.5em; text-align:center }
  svg {
    position:absolute; top:5%; left:5%; width:90%; height:90%;
    background:#fff; border:1px solid #ccc
  }
  svg rect { stroke:#333 }
  svg .drag { cursor:move }
  svg .sizer { opacity:0.3; fill:#ff0; stroke:#630;}
  #footer {
    position:absolute; bottom:0.5em; margin-bottom:0;
    width:40em; margin-left:-20em; left:50%; color:#666;
    font-style:italic; font-size:85%
  }
  #dragcatch { position:absolute; left:0; right:0; top:0; bottom:0; z-index:-1}
</style>
</head><body>
<p>Showing how to drag points inside a transformation hierarchy.</p>
<svg viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg"
 xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full">
  <g transform="scale(1.2,0.8)">
    <rect transform="translate(50,20) rotate(30)"
     class="drag resize" x="50" y="30" width="50" height="30" fill="#69c" />
    <rect class="drag resize" x="5" y="5" width="90" height="50" fill="#c66" />
  </g>
</svg>
<p id="footer">
  Copyright © 2011 <a href="mailto:!@phrogz.net">Gavin Kistner</a>. 
  Comments/criticisms welcome.
</p>
<script type="text/javascript"><![CDATA[
  var svg   = document.getElementsByTagName('svg')[0];
  var svgNS = svg.getAttribute('xmlns');
  var pt    = svg.createSVGPoint();

  function createOn(root,name,prop){
    var el = document.createElementNS(svgNS,name);
    for (var a in prop) if (prop.hasOwnProperty(a)) el.setAttribute(a,prop[a]);
    return root.appendChild(el);
  }

  function rectCorner(rect){
    pt.x = rect.x.animVal.value + rect.width.animVal.value;
    pt.y = rect.y.animVal.value + rect.height.animVal.value;
    return pt.matrixTransform(rect.getTransformToElement(svg));
  }

  function pointIn(el,x,y){
    pt.x = x; pt.y = y;
    return pt.matrixTransform(el.getTransformToElement(svg).inverse());
  }

  function cursorPoint(evt){
    pt.x = evt.clientX; pt.y = evt.clientY;
    return pt.matrixTransform(svg.getScreenCTM().inverse());
  }

  // Make all rects resizable before drag, so the drag handles become drag
  for (var a=svg.querySelectorAll('rect.resize'),i=0,len=a.length;i<len;++i){
    (function(rect){
      var dot = createOn(svg,'circle',{'class':'drag sizer',cx:0,cy:0,r:5});
      var moveDotToRect = function(){
        var corner = rectCorner(rect);
        dot.setAttribute('cx',corner.x);
        dot.setAttribute('cy',corner.y);
      }
      moveDotToRect();
      rect.addEventListener('dragged',moveDotToRect,false);
      dot.addEventListener('dragged',function(){
        var rectXY = pointIn(rect,dot.cx.animVal.value,dot.cy.animVal.value);
        var w = Math.max( rectXY.x-rect.x.animVal.value, 1 );
        var h = Math.max( rectXY.y-rect.y.animVal.value, 1 );
        rect.setAttribute('width', w);
        rect.setAttribute('height',h);
      },false);
    })(a[i]);
  }

  for (var a=svg.querySelectorAll('.drag'),i=0,len=a.length;i<len;++i){
    (function(el){
      var onmove; // make inner closure available for unregistration
      el.addEventListener('mousedown',function(e){
        el.parentNode.appendChild(el); // move to top
        var x = el.tagName=='circle' ? 'cx' : 'x';
        var y = el.tagName=='circle' ? 'cy' : 'y';
        var mouseStart   = cursorPoint(e);
        var elementStart = { x:el[x].animVal.value, y:el[y].animVal.value };
        onmove = function(e){
          var current = cursorPoint(e);
          pt.x = current.x - mouseStart.x;
          pt.y = current.y - mouseStart.y;
          var m = el.getTransformToElement(svg).inverse();
          m.e = m.f = 0;
          pt = pt.matrixTransform(m);
          el.setAttribute(x,elementStart.x+pt.x);
          el.setAttribute(y,elementStart.y+pt.y);
          var dragEvent = document.createEvent("Event");
          dragEvent.initEvent("dragged", true, true);
          el.dispatchEvent(dragEvent);
        };
        document.body.addEventListener('mousemove',onmove,false);
      },false);
      document.body.addEventListener('mouseup',function(){
        document.body.removeEventListener('mousemove',onmove,false);
      },false);
    })(a[i]);
  }
]]></script>
<div id="dragcatch"></div>
</body></html>

关于html - SVG坐标与变换矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4850821/

有关html - SVG坐标与变换矩阵的更多相关文章

  1. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  2. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  3. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  4. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  5. ruby-on-rails - capybara ::ElementNotFound:无法找到 xpath "/html" - 2

    我正在学习http://ruby.railstutorial.org/chapters/static-pages上的RubyonRails教程并遇到以下错误StaticPagesHomepageshouldhavethecontent'SampleApp'Failure/Error:page.shouldhave_content('SampleApp')Capybara::ElementNotFound:Unabletofindxpath"/html"#(eval):2:in`text'#./spec/requests/static_pages_spec.rb:7:in`(root)'

  6. 旋转矩阵的几何意义 - 2

    点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度;     在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。

  7. ruby - 如何使用 Ruby 将 CSV 文件读入 HTML 表格? - 2

    我正在尝试将一个简单的CSV文件读入HTML表格以在浏览器中显示,但我遇到了麻烦。这就是我正在尝试的:Controller:defshow@csv=CSV.open("file.csv",:headers=>true)end查看:输出:NameStartDateEndDateQuantityPostalCode基本上我只获取标题,而不会读取和呈现CSV正文。 最佳答案 这最终成为最终解决方案:Controller:defshow#OpenaCSVfile,andthenreaditintoaCSV::Tableobjectforda

  8. ruby - 如何使用 Nokogiri 解析纯 HTML 表格? - 2

    我想用Nokogiri解析HTML页面。页面的一部分有一个表,它没有使用任何特定的ID。是否可以提取如下内容:Today,3,455,34Today,1,1300,3664Today,10,100000,3444,Yesterday,3454,5656,3Yesterday,3545,1000,10Yesterday,3411,36223,15来自这个HTML:TodayYesterdayQntySizeLengthLengthSizeQnty345534345456563113003664354510001010100000344434113622315

  9. ruby-on-rails - 连接字符串时如何在 <%=%> block 内输出 html_safe? - 2

    考虑一下:现在这些情况:#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2我需要用其他字符串输出URL。我如何保证&符号不会被转义?由于我无法控制的原因,我无法发送&。求助!把我的头发拉到这里:\编辑:为了澄清,我实际上有一个像这样的数组:@images=[{:id=>"fooid",:url=>"http://

  10. ruby-on-rails - 我需要从 HTML 转到 markdown,有什么建议吗? - 2

    我正在使用Maruku,将Markdown(超集)转换为HTML,你知道我该怎么做才能从HTML转换为Markdown吗? 最佳答案 Google发现了一个名为reverse_markdown的ruby​​脚本.它似乎可以满足您的需求。 关于ruby-on-rails-我需要从HTML转到markdown,有什么建议吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/175162

随机推荐