This examples demonstrates using transform.applyX and transform.applyY to apply the zoom behavior’s transform to data, rather than using an SVG transform. This is typically slower because it requires modifying all two thousand elements on each zoom, but it lets you customize the display on zoom, such as rendering circles that are the same size regardless of scale; consider using Canvas.
<!DOCTYPE html>
<meta charset="utf-8">
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var points = d3.range(2000).map(phyllotaxis(10));
var circle = svg.selectAll("circle")
.data(points)
.enter().append("circle")
.attr("transform", function(d) { return "translate(" + d[0] + "," + d[1] + ")"; })
.attr("r", 2.5);
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.event.transform;
circle.attr("transform", function(d) {
return "translate(" + transform.applyX(d[0]) + "," + transform.applyY(d[1]) + ")";
});
}
function phyllotaxis(radius) {
var theta = Math.PI * (3 - Math.sqrt(5));
return function(i) {
var r = radius * Math.sqrt(i), a = theta * i;
return [
width / 2 + r * Math.cos(a),
height / 2 + r * Math.sin(a)
];
};
}
</script>