1
我使用Interactjs在SVG视口周围拖动SVG元素,主要是因为它支持手势,我最终将在手机上使用它进行轮换。但是我的简单拖动有问题。与SVG的交互
<div class="container">
<!--?xml version="1.0" encoding="UTF-8"?-->
<svg viewBox="0 0 100 100">
<g class="shape" transform="scale(0.1) translate(-300, 0) rotate(10)">
<polygon xmlns="http://www.w3.org/2000/svg" points="350,75 379,161 469,161 397,215 423,301 350,250 277,301 303,215 231,161 321,161" />
</g>
</svg>
</div>
Interactjs不给当前光标的x,y,所以它是从一个增量X计算,Y,(event.dx,event.dy)积累的事件,从起始位置偏移(事件.x0,event.y0)。然后,在将其应用为元素当前变换的平移变换之前,将其转换为目标元素的局部坐标(以防旋转,偏斜等)(按照SO answer)。
interact('.shape').draggable({
onstart: dragStartListener,
onmove: dragMoveListener,
onend: dragEndListener
});
var svg = document.getElementsByTagName('svg')[0];
var pt = svg.createSVGPoint();
function dragStartListener(event) {
event.target.transform.baseVal.consolidate();
console.clear();
}
function dragMoveListener(event) {
var target = event.target;
var currentCursor = getCurrentCursor(event);
var translationMatrix = getMatrixForTranslation(target, currentCursor.x, currentCursor.y);
target.transform.baseVal.getItem(0).setMatrix(target.transform.baseVal.getItem(0).matrix.multiply(translationMatrix));
}
function dragEndListener(event) {
var target = event.target;
target.removeAttribute('data-x');
target.removeAttribute('data-y');
}
function getMatrixForTranslation(target, x, y) {
return target.ownerSVGElement.createSVGMatrix().translate(x, y);
}
function getCurrentCursor(event) {
var target = event.target;
// keep the change in cursor on page in the data-x/data-y attributes
var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
pt.x = event.x0 + x; // calculate the new whole page coordinates
pt.y = event.y0 + y;
// convert to object space coordinates ... https://stackoverflow.com/a/5223921/5610106
var globalPoint = pt.matrixTransform(svg.getScreenCTM().inverse());
var globalToLocal = target.getTransformToElement(svg).inverse();
var inObjectSpace = globalPoint.matrixTransform(globalToLocal);
console.log('cursor: x: ' + inObjectSpace.x + '; y: ' + inObjectSpace.y);
return {x: inObjectSpace.x, y: inObjectSpace.y};
}
JSFiddle here。我通过target.transform.baseVal.getItem(0).setMatrix()操纵元素的“transform”属性,而不是通过CSS转换,因为我需要的单位与SVG空间的单位相同。此外,我可以轻松地将它们合并()成单个矩阵,然后我可以将其发送回服务器,以便可以在其他视图上轻松渲染这些形状。
但是,简单的拖动会导致第一个事件发生大的跳转,然后目标元素在跟随光标时不在光标之下。
任何想法,我应该如何做到这一点?
您的解决方案不会考虑变换对矩形拖动之前。尝试在设置时添加“rect.setAttribute('transform','translate(50 0)rotate(45)')”,您将看到矩形不再跟随鼠标,因为没有鼠标的帐户在对象空间坐标中的位置。此外,我无法操纵x&y属性,因为标签没有它们,因此我试图操作transform属性。 –
marlboroman