gpt4 book ai didi

html - SVG坐标与变换矩阵

转载 作者:技术小花猫 更新时间:2023-10-29 11:44:50 24 4
gpt4 key购买 nike

我想在矩形元素上实现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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com