在D3JS中拖动时平移

时间:2016-03-13 14:17:08

标签: d3.js svg drag pan

我想要实现的是在拖动操作期间平移整个SVG“图像”的能力。

现在我正在玩这个例子:https://bl.ocks.org/mbostock/6123708因为我发现它最适合我(大多数是因为它正确处理拖动“,大多数其他例子只是在拖动操作中居中点我会拖动更复杂的对象所以对我这个功能,我增加位置不改变它更合适)但是我真的不知道如何在拖动过程中处理这个平移功能

  1. 用户开始使用LeftMouseButton
  2. 拖动圆圈
  3. 按住此按钮按下RightMouseButton(然后魔法开始发生)
  4. 整个SVG开始移动(平移),因此拖动的元素(拖动仍在工作并更新位置,因此拖动元素上的鼠标位置不会改变)
  5. 用户释放RightMouseButton,SVG停止平移,只有拖动仍在工作
  6. 用户释放LeftMouseButton,拖动元素更新它的位置
  7. 据我所知,我必须:

    • 仅为RightMouseButton处理平底锅 - 已解决
    • 仅为LeftMouseButton处理Drag - 在开发中:)
    • 当我处于拖动“模式”时允许平移启动 - 这是最常见的问题
    • 在释放RightMenuButton - SOLVED
    • 时不允许触发上下文菜单

    对不起英语错误,这不是我原来的错误,可以随意提出任何可以解决这个问题的问题:)

    更新

    至于现在,我最终会找到一个拖动代码:

      var drag = d3.behavior.drag()
      .on("dragstart", function () {
    
        //d3.event.sourceEvent.stopPropagation();
        d3.select(this).classed("dragging", true);
    
      }).on("drag", function () {
    
        var $this = d3.select(this);
        var t = d3.transform($this.attr("transform"));
        t.translate[0] += d3.event.dx;
        t.translate[1] += d3.event.dy;
    
        $this.attr("transform", "translate(" + t.translate + ")");
    
      }).on("dragend", function () {
    
        console.log("dragend");
        d3.select(this).classed("dragging", false);
    
      });
    

    为了放大而购买:

    var zoom = d3.behavior.zoom()
                .scaleExtent([0.1, 2])
                .on("zoomstart", function() {
    
                    if (d3.event.sourceEvent.buttons != 2) {
                        savedTranslation = zoom.translate();
                    } else {
                        savedTranslation = null;
                    }
    
                }).on("zoom", function() {
    
                    var translate = d3.event.translate;
    
                    if (d3.event.sourceEvent.buttons != 2) {
                        zoom.translate(savedTranslation);
                        translate = savedTranslation;
                    }
    
                    svgContainer.attr("transform", "translate(" + translate + ")scale(" + d3.event.scale + ")");
    
                }).on("zoomend", function() {
    
                    if (savedTranslation) {
                        zoom.translate(savedTranslation);
                        savedTranslation = null;
                    }
    
                });
    

    使用缩放+防止上下文菜单弹出(也阻止双击缩放,因为它将用于弹出编辑弹出模式)

    var svg = d3.select("#svg-workspace")
                .call(zoom)
                .on("dblclick.zoom", null)
                .on('contextmenu',function () {
                    d3.event.preventDefault();
                    return false;
                });
    

    附上od D3.JS

    d3.select($foreignObject.get(0))
        .call(drag);
    

    $ foreignObject是jQuery抓取对象

    而且问题是在拖动时开始平移。

1 个答案:

答案 0 :(得分:0)

这可能很难在D3JS中实现,所以我最终编写了一些JS代码。真有帮助的是这个页面:http://www.petercollingridge.co.uk/interactive-svg-components/pan-and-zoom-control

    var transMatrix = [1,0,0,1,0,0];

var $svg = $("#svg-workspace");

mapMatrix = $("#svg-workspace-group")[0];

function pan(dx, dy)
{
  transMatrix[4] += dx;
  transMatrix[5] += dy;

  newMatrix = "matrix(" +  transMatrix.join(' ') + ")";
  mapMatrix.setAttributeNS(null, "transform", newMatrix);
}

    function zoom(scale, mousex, mousey)
    {
        for (var i=0; i < transMatrix.length; i++)
        {
            transMatrix[i] *= scale;
        }

        transMatrix[4] += (1-scale) * mousex;
        transMatrix[5] += (1-scale) * mousey;

        newMatrix = "matrix(" +  transMatrix.join(' ') + ")";
        mapMatrix.setAttributeNS(null, "transform", newMatrix);
}

$svg.contextmenu(function () {return false;});

var drag = false;
var distanceX = 0;
var distanceY = 0;

var initX = 0;
var initY = 0;

$svg.on("mousedown", function(evt) {
  if(evt.originalEvent.which == 1) {
    drag = true;
    distanceX = 0;
    distanceY = 0;
  }
});

$svg.on("mouseup", function(evt) {
  if (evt.originalEvent.which == 1) {
    drag = false;
    initX = parseInt($("#dragtest").attr("cx"));
    initY = parseInt($("#dragtest").attr("cy"));
  }
});

$svg.on("mousemove", function(evt) {
  if( (evt.originalEvent.buttons & 2) == 2) {
    pan(evt.originalEvent.movementX, evt.originalEvent.movementY);
  } else if(drag) {
    distanceX += evt.originalEvent.movementX;
    distanceY += evt.originalEvent.movementY;

    $("#dragtest").attr("cx", initX + distanceX / transMatrix[0]);
    $("#dragtest").attr("cy", initY + distanceY / transMatrix[0]);
  }
});

$svg.on("mousewheel", function(evt) {
  if(evt.originalEvent.deltaY > 0) {
    zoom(0.9, evt.originalEvent.offsetX, evt.originalEvent.offsetY);
  } else if (evt.originalEvent.deltaY < 0) {
    zoom(1.1, evt.originalEvent.offsetX, evt.originalEvent.offsetY);
  }
});

相应的HTML代码:

<svg id="svg-workspace" xmlns="http://www.w3.org/2000/svg" width="900" height="600" viewBox="0 0 900 600" style="display: block; margin: 0 auto; border: 1px solid #ddd;">
  <g id="svg-workspace-group" transform="translate(0,0)scale(1)">
    <circle cx="0" cy="0" r="5" stroke="black" stroke-width="1" fill="red" />
    <circle cx="100" cy="-100" r="5" stroke="black" stroke-width="1" fill="red" />
    <circle cx="100" cy="100" r="5" stroke="black" stroke-width="1" fill="red" />
    <circle cx="-100" cy="100" r="5" stroke="black" stroke-width="1" fill="red" />
    <circle id="dragtest" cx="-100" cy="-100" r="5" stroke="black" stroke-width="1" fill="red" />
  </g>
</svg>

我发现此代码只有一个问题拖动无法正常进行缩放,但是我可以忍受它;)