在 D3JS 中拖动期间平移

Pan during dragging in D3JS

我想要实现的是能够在拖动操作期间平移整个 SVG "image"。

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

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

据我所知我必须:

抱歉英文错误,这不是我的母语,请随意提出任何可以解决此问题的问题:)

更新

至于现在我以这样的拖动代码结束:

  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抓取的对象

问题仍然是拖动时开始平移。

这在 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>

我发现这段代码只有一个问题,拖动在缩放时无法正常工作,但是是的,我可以接受 ;)