2

我想在 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);
            }

在此处输入图像描述

在此处输入图像描述

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

编辑:-(更新)

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

在此处输入图像描述

4

1 回答 1

1

This is one way, I've just done it with the Y/vertical for the moment...

You may want to adjust it, so that if the cursor is off the screen it adjusts the viewBox automatically as well, depends how you want it to drag (otherwise you will need to keep wiggling it to kick the drag func in).

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

于 2014-02-21T09:33:07.560 回答