zooming and panning - upgrading d3 code to d3.v4

2019-07-14 00:49发布

问题:

I have been trying to upgrade this code to v4 of d3 with no luck.

function xnr(selector) {
var coordinates = [
                        {"id": 1, "x": 120.16353869437225, "y": 160.974180892502466},
            {"id": 2, "x": 190.285414932883366, "y": 259.116836781737214},
            {"id": 3, "x": 310.218762385111142, "y": 170.033297729284202}
            ];

var x = d3.scale.linear()
    .domain([0, 100])
    .range([0, 100]);

var y = d3.scale.linear()
    .domain([0, 100])
    .range([0, 100]);

var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom");

var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left");

var svg = d3.select(selector).append("svg:svg")
    .attr("width", 400)
    .attr("height", 400)
    .call(d3.behavior.zoom().x(x).y(y).scaleExtent([1, 100]).on("zoom", zoom));

var groups = svg.selectAll("g.leaf")
    .data(coordinates)
    .enter()
    .append("svg:g")
    .attr("class", "leaf")
    .attr("transform", transform)
    .append("svg:circle")
    .attr("r", 5)
    .attr('stroke', '#aaaaaa')
    .attr('stroke-width', '2px');

function zoom() {
    svg.selectAll("g.leaf").attr("transform", transform);
}

function transform(d) {
    return "translate(" + x(d.x) + "," + y(d.y) + ")";
}
}

Old code jsfiddle - works as i need it (semantic zoom). New code jsfiddle - only works as geometic zoom.

Mike Bostock's examples for SVG geometric and semantic zooming worked for me in d3 v3, but since the zoom.x() and zoom.y() functions had been removed, i am lost.

回答1:

Mike Bostock's Pan & Zoom III example can be modified to use semantic zooming as per this jsfiddle. The important bits are:

var radius = 3;
var circles = g.selectAll("circle")
    .data(points)
  .enter().append("circle")
    .attr("cx", function(d) { return d[0]; })
    .attr("cy", function(d) { return d[1]; })
    .attr("r", radius);

svg.append("rect")
    .attr("width", width)
    .attr("height", height)
    .style("fill", "none")
    .style("pointer-events", "all")
    .call(d3.zoom()
        .scaleExtent([1 / 2, 4])
        .on("zoom", zoomed));

function zoomed() {
    var transform = d3.zoomTransform(this);
    circles.attr("transform", transform);
    circles.attr("r", radius/transform.k)
}

zoomTransform is a linear transformation of the plane which increases area as it increases distances. If we want the circles to have the same area after zooming, we need to rescale their radii by the scale factor of the transformation, transform.k.



回答2:

    I have an example fiddle for semantic zoom for d3 version 4 with click controls. also displaying scale for the reference. you can use this scale to add any semantic information for the same.

var svg = d3.select("svg"),
  width = +svg.attr("width"),
  height = +svg.attr("height");

var randomX = d3.randomNormal(width / 2, 80),
  randomY = d3.randomNormal(height / 2, 80),
  data = d3.range(200).map(function() {
    return [randomX(), randomY()];
  });
var scale;

var circle;


var _zoom = d3.zoom()
  .scaleExtent([1, 8])
  .on("zoom", zoom);


circle = svg.selectAll("circle")
  .data(data)
  .enter().append("circle")
  .attr("r", 5)
  .attr("transform", transform(d3.zoomIdentity));


svg.append("rect")
  .attr("fill", "none")
  .attr("pointer-events", "all")
  .attr("width", width)
  .attr("height", height)
  .call(_zoom);

function zoom() {
  circle.attr("transform", transform(d3.event.transform));
  scale = d3.event.transform.k;
  console.log(scale);
  document.getElementById('scale').value = scale;
}


// semantic zoom

function semanticZoom() {
  circle.attr("transform", transform(d3.event.transform));
}

function transform(t) {
  return function(d) {
    return "translate(" + t.apply(d) + ")";
  }
}



var gui = d3.select("#gui");
gui.append("span")
  .classed("zoom-in", true)
  .text("+")
  .on("click", function() {
    _zoom.scaleBy(circle, 1.2);
  });
gui.append("span")
  .classed("zoom-out", true)
  .text("-")
  .on("click", function() {
    _zoom.scaleBy(circle, 0.8);
  });

    below is the js fiddle link:

    https://jsfiddle.net/sagarbhanu/5jLbLpac/36/