Pan Svg拖动元素

时间:2014-02-21 07:30:19

标签: javascript svg scroll viewbox panning

我希望在svg中实现'平移',同时在特定方向上“拖动”元素。

假设我选择一个元素并开始向上“拖动”它直到它到达屏幕顶部,现在我的svg应该自动向上平移,而不会导致任何拖动问题。我怎么能做到这一点。?

我做了一个小模型,用户可以选择并拖动元素。它还包含两个按钮,使svg向上和向下平移。我通过更改svg的'ViewBox'来实现'平移'。 (我必须使用这个逻辑,我不能使用任何其他解决方案);

这里是小提琴链接:http://jsfiddle.net/9J25r/

完整代码: -

addEventListener('mousedown', mousedown, false);
            var mx, my;
            var dx, dy;
            var mainsvg = document.getElementById('svg');
            var selectedElement;
            var eleTx, eleTy;

            function getSvgCordinates(event) {

                var m = mainsvg.getScreenCTM();
                var p = mainsvg.createSVGPoint();

                var x, y;

                x = event.pageX;
                y = event.pageY;

                p.x = x;
                p.y = y;
                p = p.matrixTransform(m.inverse());

                x = p.x;
                y = p.y;

                x = parseFloat(x.toFixed(3));
                y = parseFloat(y.toFixed(3));

                return {x: x, y: y};
            }

            function mousedown(event) {
                if (event.target.id === 'arrow_t') {
                    panning('up');
                }
                else if (event.target.id === 'arrow_b') {
                    panning('down');
                }
                else  if (event.target.id.split('_')[0] === 'rect') {

                    selectedElement = event.target;
                    var translatexy = selectedElement.getAttribute('transform');
                    translatexy = translatexy.split('(');
                    translatexy = translatexy[1].split(',');

                    eleTx = translatexy[0];
                    translatexy = translatexy[1].split(')');
                    eleTy = translatexy[0];

                    eleTx = parseFloat(eleTx);
                    eleTy = parseFloat(eleTy);

                    var xy = getSvgCordinates(event);

                    mx = xy.x;
                    my = xy.y;

                    mx = parseFloat(mx);
                    my = parseFloat(my);

                    addEventListener('mousemove', drag, false);
                    addEventListener('mouseup', mouseup, false);
                }
            }

            function drag(event) {
                var xy = getSvgCordinates(event);
                dx = xy.x - mx;
                dy = xy.y - my;

                selectedElement.setAttribute('transform', 'translate(' + (eleTx + dx) + ',' + (eleTy + dy) + ')');
            }
            function mouseup(event) {


                removeEventListener('mousemove', drag, false);
                removeEventListener('mouseup', mouseup, false);

            }

            function panning(direction) {
                var viewBox = svg.getAttribute('viewBox');
                viewBox = viewBox.split(' ');
                var y = parseFloat(viewBox[1]);
                if (direction === 'up')
                {
                    y+=5;
                }
                else if (direction === 'down')
                {
                    y-=5;
                }

                viewBox=viewBox[0]+' '+y+' '+viewBox[2]+' '+viewBox[3];
                svg.setAttribute('viewBox',viewBox);
            }

enter image description here

enter image description here

这里是小提琴链接:http://jsfiddle.net/9J25r/

编辑: - (更新)

我使用Ian的解决方案,它在样本上运行良好,但是当我将它应用到我的原始应用程序时,它不起作用。检查下面的gif。您可以看到鼠标指针和元素之间的“间隙”。我怎么能删除它? 。

enter image description here

1 个答案:

答案 0 :(得分:1)

这是一种方式,我刚刚用Y /垂直方式做到了......

你可能想要调整它,这样如果光标在屏幕外,它也会自动调整viewBox,取决于你想要它的拖动方式(否则你需要继续摆动它来踢动拖动功能)

var viewBox = svg.getAttribute('viewBox');
viewBoxSplit = viewBox.split(' ');

if( ely < viewBoxSplit[1] ) {
      panning('down');
} else if( ely + +event.target.getAttribute('height')> +viewBoxSplit[1] + 300 ) {
      panning('up');
}

jsfiddle here