如何用d3js拖动完整的svg?

时间:2015-06-02 14:13:35

标签: javascript svg d3.js drag

我想点击svg上的任何地方时有​​拖拽行为。

这是我尝试过的一个JSFiddle:https://jsfiddle.net/d2fx196n/2/

我尝试的直观之处是:

svg = d3.select("body")
  .append("svg:svg")
  .attr("width", 200)
  .attr("height", 200)
  .style("border", "solid")
  .call(drag);

是否有一种简单的方法将拖拽行为应用于整个svg,使每个对象都以相同的方式移动?

编辑:我更想要的是通过单击svg中的任何位置来拖动svg内的所有内容(即使是"背景")。当我拖动时,svg内的所有东西都应该一起移动。

EDIT2:基本上,我希望在这里可以看到相同的行为:http://jsfiddle.net/superboggly/2hfx3/,但也有线条

1 个答案:

答案 0 :(得分:1)

策略

您可以将svg的内容包装在g中并对其进行转换,然后在拖动时更新转换转换。

策略

  1. d3.event公开了dxdy,因此您可以将这些内容添加到拖动变换中。
  2. 在d3 Math模块中有一个方便的转换API,您可以使用它来节省解析g元素的transform属性的麻烦。
  3. 代码

        var drag = d3.behavior.drag()
              //.origin(function (d) { return d; })
              .on("dragstart", dragstarted)
              .on("drag", dragged)
              .on("dragend", dragended),
    
            data = {
              "nodes": [
                  { "id": "0", "x": 50, "y": 50 },
                  { "id": "1", "x": 100, "y": 50 },
                  { "id": "2", "x": 50, "y": 100 },
                  { "id": "3", "x": 100, "y": 100 }
              ],
              "edges": [
                  { "id": "0", "source": "0", "target": "1" },
                  { "id": "1", "source": "2", "target": "3" }
              ]
            },
    
            log = d3.select("body").append("div")
              .style({ "background-color": "1px solid #ccc" })
              .text("waiting..."),
    
            svg = d3.select("body")
              .append("svg:svg")
              .attr("width", 200)
              .attr("height", 200)
              .style("border", "solid")
              .call(drag)
              .append("g"),
    
            nodes = data.nodes,
    
            links = data.edges;
    
        for (var i in data.edges) {
          for (var j in nodes) {
            if (nodes[j].id == data.edges[i].source) {
              data.edges[i].source = nodes[j];
            } else if (nodes[j].id == data.edges[i].target) {
              data.edges[i].target = nodes[j];
            }
          }
        }
    
        var lines = svg.selectAll(".line")
            .data(links)
            .enter()
            .append("line")
            .attr("x1", function (d) { return d.source.x })
            .attr("y1", function (d) { return d.source.y })
            .attr("x2", function (d) { return d.target.x })
            .attr("y2", function (d) { return d.target.y })
            .attr("stroke-width", "4")
            .style("stroke", "#000000");
    
        var circles = svg.selectAll("circle.nodes")
            .data(nodes)
            .enter()
            .append("svg:circle")
            .attr("cx", function (d) { return d.x; })
            .attr("cy", function (d) { return d.y; })
            .attr("r", "8px")
            .attr("fill", "#FF0000");
    
    
        function dragstarted(d) {
          d3.event.sourceEvent.stopPropagation();
          d3.event.sourceEvent.preventDefault;
          console.log("start")
          log.text("start")
        }
    
        function dragged(e) {
          var t = d3.transform(svg.attr("transform")).translate;
          svg.attr("transform", "translate(" + [t[0] + d3.event.dx, t[1] + d3.event.dy] + ")")
          console.log("drag: " + d3.transform(svg.attr("transform")).translate);
          log.text("drag: " + d3.transform(svg.attr("transform")).translate)
        }
    
        function dragended(d) {
          console.log("end")
          log.text("end")
        }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>