JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.6/d3.js"></script>
<button id="zoom_in">+</button>
<button id="zoom_out">-</button>
<button id="zoom_init">Init</button>
CSS
.overlay {
fill: none;
pointer-events: all;
}
button {
padding: 10px 20px;
}
JavaScript
var width = 960,
height = 500;
var randomX = d3.randomUniform(width / 2, 80),
randomY = d3.randomUniform(height / 2, 80);
var data = d3.range(2000).map(function() {
return [randomX(), randomY() ];
});
var svg = d3.select("body")
.append("svg")
.attr('id', 'svg')
.attr("width", width)
.attr("height", height)
.append("g")
.append("g")
.attr('id', 'g');
svg.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height);
svg.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("r", 2.5)
.attr("transform", function(d) { return "translate(" + d + ")"; });
//****************** ZOOM IMPLEMENTATION ********************
var g = d3.select("#g");
var svg = d3.select('#svg');
var zoom = d3.zoom()
.scaleExtent([1/2, 4])
.on("zoom", zoom);
svg.call(transform);
function zoomed() {
g.attr('transform', `translate(${d3.event.transform.x}, ${d3.event.transform.y}) scale(${d3.event.transform.k})`);
};
// this function need to be called if we need zoom to center of the picture
function transform() {
return d3.zoomIdentity
.translate(width / 2.75, height / 2.75)
.scale(zoomLevel)
.translate(-width/2.75, -height/2.75);
}
function transition(zoomLevel) {
svg.transition()
.delay(100)
.duration(700)
.call(zoom.scaleBy, zoomLevel)
.call(zoom.transform, transform);
//.on("end", function() { canvas.call(transition); });
}
d3.selectAll('button').on('click', function() {
if (this.id === 'zoom_in') {
transition(1.2); // increase on 0.2 each time
}
if (this.id === 'zoom_out') {
transition(0.8); // deacrease on 0.2 each time
}
if (this.id === 'zoom_init') {
svg.transition()
.delay(100)
.duration(700)
.call(zoom.scaleTo, 1); // return to initial state
}
});