gpt4 book ai didi

javascript - SVG如何获取鼠标在内部矩阵上的位置

转载 作者:太空宇宙 更新时间:2023-11-04 14:37:55 27 4
gpt4 key购买 nike

jsFiddle:http://jsfiddle.net/az6Ug/

使用 Snap.svg 库,我想在 SVG 上拖动并获取鼠标位置。我需要内部矩阵上的鼠标位置,而不是浏览器鼠标位置。我有一个问题,那就是如果 SVG 所属的窗口上有任何滚动,则计算出的鼠标位置会偏移滚动条上的滚动量。

例如,没有滚动则它工作正常。或者滚动条垂直滚动10px,鼠标位置计算为:真实位置+10px。如果有任何水平滚动也是一样的:由滚动量偏移。

在 jsFiddle 中,我使用一个矩形来显示拖动时计算出的鼠标位置。如您所见,如果没有滚动,则矩形将停留在鼠标光标(左上角)。但是随着一些滚动,矩形从鼠标光标偏移。

虽然我用的是Snap.svg库,但我只是用它来获取拖动事件,鼠标计算是纯Javascript。一个可能的解决方案是用滚动量减去 X 和 Y,但我认为使用 SVG 的转换函数会有更好的方法。

var S;
var pt;
var svg
var box;

window.onload = function(){
svg = $('#mysvg')[0];
S = Snap(svg);

pt = pt = svg.createSVGPoint(); // create the point

// add the rectangle
box = S.rect(10, 10, 50, 50);
box.attr({ fill : 'red', stroke : 'none' });

S.drag(
function(dx, dy, posX, posY, e){
//onmove
pt.x = posX;
pt.y = posY;

// convert the mouse X and Y so that it's relative to the svg element
var transformed = pt.matrixTransform(svg.getScreenCTM().inverse());
box.attr({ x : transformed.x, y : transformed.y });
},
function(){
//onstart
},
function(){
//onend
}
);

}

最佳答案

下面是我在所有浏览器和所有视口(viewport)上使用的 Javascript 示例。它使用 svg 矩阵变换。事件附加到每个要拖动的元素。在示例中,我包括了 html 和 svg 的鼠标位置读数。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>E - Universal Drag/Drop</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body style='padding:10px;font-family:arial'>
<center>
<h4>Universal Drag/Drop</h4>
<div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:6px;'>
This example uses matrix transforms, with object methods, not strings. It can seamlessly drag/drop elements that have previously been transformed and reside it different viewPorts. It employs <b>getScreenCTM</b>, <b>createSVGTransform</b> and binds the element to a <b>transform List</b>
</div>
<table>
<tr><td align=left>
Scenerio:<br />
A 400x400 DIV contains an SVG with viewBox=0 0 330 330.<br />
1.) The blue rect element is contained in a &lt;g&gt;.<br />
2.) The &lt;g&gt; element has been transformed.<br />
3.) The maroon rect resides in a different viewPort.<br />
4.) The orange circle has been transformed.<br />
5.) Drag/Drop the circles and rectangles.<br />
</td>
<td align=left>
<div id="svgDiv" style='background-color:lightgreen;width:400px;height:400px;'>
<svg id="mySVG" width="100%" height="100%" viewBox="0 0 300 300" onmousemove="svgCursor(evt)">
<circle onmousedown=startDrag(evt) onmousemove=drag(evt) onmouseup=endDrag() id="redCircle" cx="120" cy="180" r="40" fill="red" stroke="black" stroke-width="2" />
<circle onmousedown=startDrag(evt) onmousemove=drag(evt) onmouseup=endDrag() id="orangeCircle" cx="200" cy="200" r="40" fill="orange" stroke="black" stroke-width="2" />
<svg viewBox="0 100 800 800">
<rect onmousedown=startDrag(evt) onmousemove=drag(evt) onmouseup=endDrag() id="maroonRect" x="220" y="250" width="60" height="60" fill="maroon" stroke="black" stroke-width="2" />
</svg>
<g id="myG" >
<rect onmousedown=startDrag(evt) onmousemove=drag(evt) onmouseup=endDrag() id="blueRect" x="220" y="250" width="60" height="60" fill="blue" stroke="black" stroke-width="2" />
</g>
</svg>
</div>
</td>
<td align=left>
<b>HTML Page Values:</b><br />
<input type=text id=htmlMouseXValue size=1 />: mouse X<br />
<input type=text id=htmlMouseYValue size=1 />: mouse Y<br />
<br />
<b>SVG Image Values:</b><br />
<input type=text id=svgXValue size=1 />: svg X<br />
<input type=text id=svgYValue size=1 />: svg Y<br />
</td>
</tr></table>
<br />SVG Source:<br />
<textarea id=svgSourceValue style='font-size:110%;font-family:lucida console;width:90%;height:200px'></textarea>
<br />Javascript:<br />
<textarea id=jsValue style='border-radius:26px;font-size:110%;font-weight:bold;color:midnightblue;padding:16px;background-color:beige;border-width:0px;font-size:100%;font-family:lucida console;width:90%;height:400px'></textarea>
</center>
<div id='browserDiv' style='padding:3px;position:absolute;top:5px;left:5px;background-color:gainsboro;'></div>
<script id=myScript>
var TransformRequestObj
var TransList
var DragTarget=null;
var Dragging = false;
var OffsetX = 0;
var OffsetY = 0;
//---mouse down over element---
function startDrag(evt)
{
if(!Dragging) //---prevents dragging conflicts on other draggable elements---
{
DragTarget = evt.target;
//---reference point to its respective viewport--
var pnt = DragTarget.ownerSVGElement.createSVGPoint();
pnt.x = evt.clientX;
pnt.y = evt.clientY;
//---elements transformed and/or in different(svg) viewports---
var sCTM = DragTarget.getScreenCTM();
var Pnt = pnt.matrixTransform(sCTM.inverse());

TransformRequestObj = DragTarget.ownerSVGElement.createSVGTransform()
//---attach new or existing transform to element, init its transform list---
var myTransListAnim=DragTarget.transform
TransList=myTransListAnim.baseVal

OffsetX = Pnt.x
OffsetY = Pnt.y

Dragging=true;
}
}
//---mouse move---
function drag(evt)
{
if(Dragging)
{
var pnt = DragTarget.ownerSVGElement.createSVGPoint();
pnt.x = evt.clientX;
pnt.y = evt.clientY;
//---elements in different(svg) viewports, and/or transformed ---
var sCTM = DragTarget.getScreenCTM();
var Pnt = pnt.matrixTransform(sCTM.inverse());
Pnt.x -= OffsetX;
Pnt.y -= OffsetY;

TransformRequestObj.setTranslate(Pnt.x,Pnt.y)
TransList.appendItem(TransformRequestObj)
TransList.consolidate()
}
}
//--mouse up---
function endDrag()
{
Dragging = false;
svgSourceValue.value=svgDiv.innerHTML
}
//---onload---
function initTransforms()
{
//---place some transforms on the elements---

//--- transform orange circle---
var transformRequestObj=mySVG.createSVGTransform()
var animTransformList=orangeCircle.transform
var transformList=animTransformList.baseVal
//---translate---
transformRequestObj.setTranslate(130,-300)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//----scale---
transformRequestObj.setScale(.5,.9)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//----skewY---
transformRequestObj.setSkewY(52)
transformList.appendItem(transformRequestObj)
transformList.consolidate()

//--init Transform on myG---
var transformRequestObj=mySVG.createSVGTransform()
var animTransformList=myG.transform
var transformList=animTransformList.baseVal
//---translate---
transformRequestObj.setTranslate(-50,-120)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//----skewX---
transformRequestObj.setSkewX(15)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//----skewY---
transformRequestObj.setSkewY(20)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//---rotate---
transformRequestObj.setRotate(30,200,200)
transformList.appendItem(transformRequestObj)
transformList.consolidate()

}

document.onmousemove = htmCursor
//---event is the html event object---
function htmCursor(event)
{
var event = event || window.event;
myMouseX=event.clientX;
myMouseY=event.clientY;
myMouseX = myMouseX + document.documentElement.scrollLeft;
myMouseY = myMouseY + document.documentElement.scrollTop;

htmlMouseXValue.value=myMouseX
htmlMouseYValue.value=myMouseY
}
//---evt is the svg event object--
function svgCursor(evt)
{
var rect = svgDiv.getBoundingClientRect();
svgXValue.value=evt.clientX-rect.left
svgYValue.value=evt.clientY-rect.top
}
</script>
<script>
document.addEventListener("onload",init(),false)
function init()
{
initTransforms()
svgSourceValue.value=svgDiv.innerHTML
jsValue.value=myScript.text
}
</script>

</body>

</html>

关于javascript - SVG如何获取鼠标在内部矩阵上的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21852543/

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