Skip to content

Instantly share code, notes, and snippets.

@aleereza
Last active May 31, 2023 11:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aleereza/d2be3d62a09360a770b79f4e5527eea8 to your computer and use it in GitHub Desktop.
Save aleereza/d2be3d62a09360a770b79f4e5527eea8 to your computer and use it in GitHub Desktop.
D3 v4 - Scatter Plot - Semantic Zooming

This code shows how to use zoom in d3.js v4, for a scatter plot, without changing in points size.

<!DOCTYPE html>
<meta charset="utf-8">
<svg width="500" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var n = 50; // number of points
var max = 100; // maximum of x and y
// dimensions and margins
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
width = 0.8*width;
height = 0.8*height;
var margin = {top: (0.1*width), right: (0.1*width), bottom: (0.1*width), left: (0.1*width)};
// create a clipping region
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
// create scale objects
var xScale = d3.scaleLinear()
.domain([0, max])
.range([0, width]);
var yScale = d3.scaleLinear()
.domain([0, max])
.range([height, 0]);
// create axis objects
var xAxis = d3.axisBottom(xScale)
.ticks(20, "s");
var yAxis = d3.axisLeft(yScale)
.ticks(20, "s");
// Draw Axis
var gX = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + (margin.top + height) + ')')
.call(xAxis);
var gY = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
.call(yAxis);
// Draw Datapoints
var points_g = svg.append("g")
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
.attr("clip-path", "url(#clip)")
.classed("points_g", true);
data = genRandomData (n, max);
var points = points_g.selectAll("circle").data(data);
points = points.enter().append("circle")
.attr('cx', function(d) {return xScale(d.x)})
.attr('cy', function(d) {return yScale(d.y)})
.attr('r', 5);
// Pan and zoom
var zoom = d3.zoom()
.scaleExtent([.5, 20])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all")
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
.call(zoom);
function genRandomData (n, max){
var data = [];
var datapoint = {};
for (i = 0; i < n; i++){
datapoint = {};
datapoint["x"] = Math.random() * max;
datapoint["y"] = Math.random() * max;
data.push(datapoint);
}
return data
}
function zoomed() {
// create new scale ojects based on event
var new_xScale = d3.event.transform.rescaleX(xScale);
var new_yScale = d3.event.transform.rescaleY(yScale);
// update axes
gX.call(xAxis.scale(new_xScale));
gY.call(yAxis.scale(new_yScale));
points.data(data)
.attr('cx', function(d) {return new_xScale(d.x)})
.attr('cy', function(d) {return new_yScale(d.y)});
}
</script>
@Ram0987
Copy link

Ram0987 commented May 19, 2019

Thank you very much @aleereza for sharing your work. It is really great!!. I have a question. Is it possible to add tool tips on the above graph?
Thank you.

@aleereza
Copy link
Author

Hi @Ram0987, It's been a long time since I used d3, actually I am not sure if it is possible. I found this example which has both zoom and tool tip.

@Ram0987
Copy link

Ram0987 commented May 20, 2019

@aleereza, Thank you very much for your help

@cgq18
Copy link

cgq18 commented May 31, 2023

Hi @aleereza Great work, may I ask what to do if I want to zoom more than one scatterplot simultaneously?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment