d3.js:使用缩放时禁用拖动

时间:2015-07-29 06:08:41

标签: jquery d3.js svg

我正在使用此示例http://bl.ocks.org/mbostock/6123708

在这里我想在其中附加带有矩形(或任何形状)的g(组)标签,它应该是可拖动的,并且不希望松散svg的缩放和平移功能。

这是我的jsfiddle

拖动矩形时

。由于缩放行为,整个svg正在平移。 所以如何拖动rect。用g标签。

var margin = {top: -5, right: -5, bottom: -5, left: -5},
        width = 1260 - margin.left - margin.right,
        height = 700 - margin.top - margin.bottom;

    var zoom = d3.behavior.zoom()
        .scaleExtent([1, 10])
        .on("zoom", zoomed);

    var drag = d3.behavior.drag()
        .origin(function(d) { return d; })
        //.inertia(true)
        .on("dragstart", dragstarted)
        .on("drag", dragged)
        .on("dragend", dragended);

    var svg = d3.select("body").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .attr("id","my_svg")
      .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.right + ")")
        .call(zoom);

    var rect = svg.append("rect")
        .attr("width", width)
        .attr("height", height)
        .style("fill", "none")
        .style("pointer-events", "all");

    var x = d3.scale.linear()
        .domain([-width / 2, width / 2])
        .range([0, width]);

    var y = d3.scale.linear()
        .domain([-height / 2, height / 2])
        .range([height, 0]);

    var container = svg.append("g");



    container.append("g")
        .attr("class", "x axis")
      .selectAll("line")
        .data(d3.range(-1000, width, 10))
      .enter().append("line")
        .attr("x1", function(d) { return d; })
        .attr("y1", -1000)
        .attr("x2", function(d) { return d; })
        .attr("y2", height);

    container.append("g")
        .attr("class", "y axis")
      .selectAll("line")
        .data(d3.range(-1000, height, 10))
      .enter().append("line")
        .attr("x1", -1000)
        .attr("y1", function(d) { return d; })
        .attr("x2", width)
        .attr("y2", function(d) { return d; });

    d3.tsv("https://dl.dropboxusercontent.com/u/14652161/dots.tsv", dottype, function(error, dots) {
      dot = container.append("g")
          .attr("transform", "translate(" + margin.left + "," + margin.right + ")")
          .attr("class", "dot")
        .selectAll("circle")
          .data(dots)
        .enter().append("circle")
          .attr("r", 5)
          .attr("cx", function(d) { return d.x; })
          .attr("cy", function(d) { return d.y; })
          .call(drag);
    });



    // Add a new group to the canvas
    var newGroup = container.append("svg:g")
        .attr("transform", "translate(10, 10)")
        .attr("id", "mygroup");

    //add rect to the new group
    var rect1 = newGroup.append("svg:rect")
        .attr("rx", 6)
        .attr("ry", 6)
        .attr("x", 5/2)
        .attr("y", 5/2)
        .attr("id", "rect")
        .attr("width", 250)
        .attr("height", 125)
        .style("fill", 'white')
        .style("stroke", d3.scale.category20c())
        .style('stroke-width', 5);

    //drag the new group
    var drag1 = d3.behavior.drag()
            .origin(function() {
                var t = d3.select(this);
                console.log(this);
                return {x: t.attr("x") + d3.transform(t.attr("transform")).translate[0],
                        y: t.attr("y") + d3.transform(t.attr("transform")).translate[1]};
            })
            .on("drag", function(d,i) {
              //d3.event.sourceEvent.stopPropagation();
                d3.select(this).attr("transform", function(d,i){
                    return "translate(" + [ d3.event.x,d3.event.y ] + ")"
                })
            });

    newGroup.call(drag1);

    d3.select("#zoomin").on("click", zoomIn);
    d3.select("#zoomout").on("click", zoomOut);

    function dottype(d) {
      d.x = +d.x;
      d.y = +d.y;
      return d;
    }

    function zoomed() {
      //console.log(d3.event.translate);
      container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
      //container.attr("transform", "scale(" + d3.event.scale + ")");
    }

    function dragstarted(d) {
      d3.event.sourceEvent.stopPropagation();
      d3.select(this).classed("dragging", true);
    }

    function dragged(d) {
      //console.log(d);
      //console.log(this);
      d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
    }

    function dragended(d) {
      d3.select(this).classed("dragging", false);
    }

    var scale = 1;

    function zoomIn() {
            var svg = d3.select("body").select("svg");
            var container = svg.select("g");
            var h = svg.attr("height"), w = svg.attr("width");

            // Note: works only on the <g> element and not on the <svg> element
      // which is a common mistake
      scale = scale + 0.1;
            container.attr("transform",
                    "translate(" + w/2 + ", " + h/2 + ") " +
                    "scale(" + scale + ") " +
                    "translate(" + (-w/2) + ", " + (-h/2) + ")");
    }

    function zoomOut() {
            var svg = d3.select("body").select("svg");
            var container = svg.select("g");
            var h = svg.attr("height"), w = svg.attr("width");

            // Note: works only on the <g> element and not on the <svg> element
      // which is a common mistake
      scale = scale - 0.1;
            container.attr("transform",
                    "translate(" + w/2 + ", " + h/2 + ") " +
                    "scale(" + scale + ") " +
                    "translate(" + (-w/2) + ", " + (-h/2) + ")");
    }

1 个答案:

答案 0 :(得分:0)

您必须stopPropagation sourceEvent dragstart拖动行为事件才能使其正常工作。

//drag the new group
var drag1 = d3.behavior.drag()
    .origin(function() {
        var t = d3.select(this);
        return {
            x: t.attr("x") + d3.transform(t.attr("transform")).translate[0],
            y: t.attr("y") + d3.transform(t.attr("transform")).translate[1]
        };
    })
    .on("dragstart", function() { //Newly added code
        d3.event.sourceEvent.stopPropagation();
    })
    .on("drag", function(d, i) {        
        d3.select(this).attr("transform", function(d, i) {
            return "translate(" + [d3.event.x, d3.event.y] + ")"
        })
    });

以下是工作代码段。

var margin = {
        top: -5,
        right: -5,
        bottom: -5,
        left: -5
    },
    width = 1260 - margin.left - margin.right,
    height = 700 - margin.top - margin.bottom;

var zoom = d3.behavior.zoom()
    .scaleExtent([1, 10])
    .on("zoom", zoomed);

var drag = d3.behavior.drag()
    .origin(function(d) {
        return d;
    })
    //.inertia(true)
    .on("dragstart", dragstarted)
    .on("drag", dragged)
    .on("dragend", dragended);

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .attr("id", "my_svg")
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.right + ")")
    .call(zoom);

var rect = svg.append("rect")
    .attr("width", width)
    .attr("height", height)
    .style("fill", "none")
    .style("pointer-events", "all");

var x = d3.scale.linear()
    .domain([-width / 2, width / 2])
    .range([0, width]);

var y = d3.scale.linear()
    .domain([-height / 2, height / 2])
    .range([height, 0]);

var container = svg.append("g");



container.append("g")
    .attr("class", "x axis")
    .selectAll("line")
    .data(d3.range(-1000, width, 10))
    .enter().append("line")
    .attr("x1", function(d) {
        return d;
    })
    .attr("y1", -1000)
    .attr("x2", function(d) {
        return d;
    })
    .attr("y2", height);

container.append("g")
    .attr("class", "y axis")
    .selectAll("line")
    .data(d3.range(-1000, height, 10))
    .enter().append("line")
    .attr("x1", -1000)
    .attr("y1", function(d) {
        return d;
    })
    .attr("x2", width)
    .attr("y2", function(d) {
        return d;
    });

d3.tsv("https://dl.dropboxusercontent.com/u/14652161/dots.tsv", dottype, function(error, dots) {
    dot = container.append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.right + ")")
        .attr("class", "dot")
        .selectAll("circle")
        .data(dots)
        .enter().append("circle")
        .attr("r", 5)
        .attr("cx", function(d) {
            return d.x;
        })
        .attr("cy", function(d) {
            return d.y;
        })
        .call(drag);
});



// Add a new group to the canvas
var group = container.append("svg:g")
    .attr("transform", "translate(10, 10)")
    .attr("id", "mygroup");

//add rect to the new group
var rect1 = group.append("svg:rect")
    .attr("rx", 6)
    .attr("ry", 6)
    .attr("x", 5 / 2)
    .attr("y", 5 / 2)
    .attr("id", "rect")
    .attr("width", 250)
    .attr("height", 125)
    .style("fill", 'white')
    .style("stroke", d3.scale.category20c())
    .style('stroke-width', 5);

//drag the new group
var drag1 = d3.behavior.drag()
    .origin(function() {
        var t = d3.select(this);
        console.log(this);
        return {
            x: t.attr("x") + d3.transform(t.attr("transform")).translate[0],
            y: t.attr("y") + d3.transform(t.attr("transform")).translate[1]
        };
    })
    .on("dragstart", function() {
        d3.event.sourceEvent.stopPropagation();
    })
    .on("drag", function(d, i) {        
        d3.select(this).attr("transform", function(d, i) {
            return "translate(" + [d3.event.x, d3.event.y] + ")"
        })
    });

group.call(drag1);

d3.select("#zoomin").on("click", zoomIn);
d3.select("#zoomout").on("click", zoomOut);

function dottype(d) {
    d.x = +d.x;
    d.y = +d.y;
    return d;
}

function zoomed() {
    //console.log(d3.event.translate);
    container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
    //container.attr("transform", "scale(" + d3.event.scale + ")");
}

function dragstarted(d) {
    d3.event.sourceEvent.stopPropagation();
    d3.select(this).classed("dragging", true);
}

function dragged(d) {
    //console.log(d);
    //console.log(this);
    d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
}

function dragended(d) {
    d3.select(this).classed("dragging", false);
}

var scale = 1;

function zoomIn() {
    var svg = d3.select("body").select("svg");
    var container = svg.select("g");
    var h = svg.attr("height"),
        w = svg.attr("width");

    // Note: works only on the <g> element and not on the <svg> element
    // which is a common mistake
    scale = scale + 0.1;
    container.attr("transform",
        "translate(" + w / 2 + ", " + h / 2 + ") " +
        "scale(" + scale + ") " +
        "translate(" + (-w / 2) + ", " + (-h / 2) + ")");
}

function zoomOut() {
    var svg = d3.select("body").select("svg");
    var container = svg.select("g");
    var h = svg.attr("height"),
        w = svg.attr("width");

    // Note: works only on the <g> element and not on the <svg> element
    // which is a common mistake
    scale = scale - 0.1;
    container.attr("transform",
        "translate(" + w / 2 + ", " + h / 2 + ") " +
        "scale(" + scale + ") " +
        "translate(" + (-w / 2) + ", " + (-h / 2) + ")");
}
.dot circle {
  fill: lightsteelblue;
  stroke: steelblue;
  stroke-width: 1.5px;
}

.dot circle.dragging {
  fill: red;
  stroke: brown;
}

.axis line {
  fill: none;
  stroke: #ddd;
  shape-rendering: crispEdges;
  vector-effect: non-scaling-stroke;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<body>
  <button id="zoomin">Zoom In</button>
  <button id="zoomout">Zoom Out</button>
</body>