Interact JS,在viewboxed svg中拖动svg元素?

时间:2016-07-17 11:38:10

标签: javascript svg interact.js

我的问题是,当我拖动元素时,元素远远落后于光标,所以看起来这可能是一个比例问题?

screen grab of the weird movement

代码:

    interact('.element', {
        context: '.lipstick__plane'
    })
        .draggable({
            snap: {
                targets: [
                    interact.createSnapGrid({x: 10, y: 10})
                ],
                range: Infinity
            },
            inertia: true,
            restrict: {
                restriction: '#lipstick__plane__main',
                elementRect: {top: 0, left: 0, bottom: 1, right: 1},
                endOnly: true
            }
        })
        .on('dragmove', function (event) {
            $scope.$apply(function () {
                var target = event.target,
                    x = (parseFloat(target.getAttribute('x')) || 0) + ((1020 / window.outerWidth) * event.dx),
                    y = (parseFloat(target.getAttribute('y')) || 0) + ((1020 / window.outerHeight) * event.dy);

                var indx = event.target.getAttribute('data-index');

                _.set($scope.stage.elements[indx], 'meta.XCord', x);
                _.set($scope.stage.elements[indx], 'meta.YCord', y);
            });
        });

我在那里潜水,让它更接近光标,但我可以整天尝试数字......

我的svg init块:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1024 1024" width="1024px" height="1024px" xml:space="preserve" id="lipstick__plane__main">

我认为有一件事可能是一个问题,但我怀疑,是否在重新查询后获得新的xy属性时会发生Angular摘要?

2 个答案:

答案 0 :(得分:3)

由于SVG的内部设置设置为1024像素的宽度和高度,但是在这种情况下以较小的尺寸显示,因此应用于拖动的应用平移缩小了元素,因此会出现此问题。看起来比光标慢。

要解决此问题,您需要相应地缩放翻译向量。获得缩放因子sxsy的一种方法可能是:

  1. 通过bb
  2. 查询svg生成的边界框getClientBoudingRect
  3. sx = bb.width / 1024 // (original size), same for sy
  4. 或者,如果您可以访问svg元素,则可以使用.getScreenCTM()来获取转换矩阵。这应该是这样的:

    | a  c  e |
    | b  d  f |
    | 0  0  1 |
    

    a应代表sxd sy

    修改

    我设置了一个小小提示here,显示了基本方法。总而言之,解决方案是向量的矩阵变换,要解决的难题是找到正确的矩阵。由于任何svg元素可能有自己的变换,或者作为组的子节点,可能从其父节点获得变换,因此仅使用根<svg> C urrent T 变形 M atrix。这就是每个SVGElement实现SVGLocatable接口的原因,使您能够从根<svg>SVGElement(getCTM)获得转换,或者将文档转换为SVGElement(getScreenCTM())。通过这些矩阵的逆来描述相反的方向。 (explanation on SO

    let svg   = document.querySelector('svg'),
        e     = svg.querySelector('.myelement'),
        ctm   = e.getScreenCTM(),
        point = svg.createSVGPoint(),
        point2;
    
    point.x = …;
    point.y = …;
    
    point2 = point.matrixTransform(ctm);
    

    总结:使用变换矩阵应该是首选方式,因为它(至少应该)考虑所有变换,可以通过css应用于svg,如旋转,3d变换等。你越具体,意味着你想要变换的元素越多,精度就越高。

答案 1 :(得分:1)

由于您的SVG已缩放,因此您的SVG坐标与鼠标坐标不是1:1。因此,您需要将鼠标/屏幕坐标转换为SVG坐标,以便为拖动的对象获取正确的位置。

请参阅此问题以了解如何进行转换。

How do you convert screen coordinates to document space in a scaled SVG?