This is an example of adding simple interface for single axis zoom and pan capability using the mouse. When the mouse is over the x
or y
axes, the panning and zooming with the mouse will execute on only those axes. When the mouse is over the main plotting canvas, pan and zoom with the mouse works on both axes. Feel free to comment on the gist.
xxxxxxxxxx
<meta charset="utf-8">
<title>Simpe Single Axis Zoom</title>
<script src="https://d3js.org/d3.v3.min.js"></script>
<style>
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
<body>
<div id="chart"></div>
<script>
var ex_chart = example().zoom(true);
var data = [];
for (var i = 0; i < 100; i++) {
data.push([Math.random(), Math.random()]);
}
d3.select('#chart')
.append("svg").attr("width", window.innerWidth).attr("height",window.innerHeight)
.datum(data).call(ex_chart);
function example() {
var svg;
var margin = {
top: 60,
bottom: 80,
left: 60,
right: 0
};
var width = 500;
var height = 400;
var xaxis = d3.svg.axis();
var yaxis = d3.svg.axis();
var xscale = d3.scale.linear();
var yscale = d3.scale.linear();
var zoomable = true;
var xyzoom = d3.behavior.zoom()
.x(xscale)
.y(yscale)
.on("zoom", zoomable ? draw : null);
var xzoom = d3.behavior.zoom()
.x(xscale)
.on("zoom", zoomable ? draw : null);
var yzoom = d3.behavior.zoom()
.y(yscale)
.on("zoom", zoomable ? draw : null);
function chart(selection) {
selection.each(function(data) {
svg = d3.select(this).selectAll('svg').data([data]);
svg.enter().append('svg');
var g = svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom);
g.append("svg:rect")
.attr("class", "border")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom)
.style("stroke", "black")
.style("fill", "none");
g.append("g").attr("class", "x axis")
.attr("transform", "translate(" + 0 + "," + (height - margin.top - margin.bottom) + ")");
g.append("g").attr("class", "y axis");
g.append("g")
.attr("class", "scatter")
.attr("clip-path", "url(#clip)");
g
.append("svg:rect")
.attr("class", "zoom xy box")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom)
.style("visibility", "hidden")
.attr("pointer-events", "all")
.call(xyzoom);
g
.append("svg:rect")
.attr("class", "zoom x box")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom)
.attr("transform", "translate(" + 0 + "," + (height - margin.top - margin.bottom) + ")")
.style("visibility", "hidden")
.attr("pointer-events", "all")
.call(xzoom);
g
.append("svg:rect")
.attr("class", "zoom y box")
.attr("width", margin.left)
.attr("height", height - margin.top - margin.bottom)
.attr("transform", "translate(" + -margin.left + "," + 0 + ")")
.style("visibility", "hidden")
.attr("pointer-events", "all")
.call(yzoom);
// Update the x-axis
xscale.domain(d3.extent(data, function(d) {
return d[0];
}))
.range([0, width - margin.left - margin.right]);
xaxis.scale(xscale)
.orient('bottom')
.tickPadding(10);
svg.select('g.x.axis').call(xaxis);
// Update the y-scale.
yscale.domain(d3.extent(data, function(d) {
return d[1];
}))
.range([height - margin.top - margin.bottom, 0]);
yaxis.scale(yscale)
.orient('left')
.tickPadding(10);
svg.select('g.y.axis').call(yaxis);
draw();
});
return chart;
}
function update() {
var gs = svg.select("g.scatter");
var circle = gs.selectAll("circle")
.data(function(d) {
return d;
});
circle.enter().append("svg:circle")
.attr("class", "points")
.style("fill", "steelblue")
.attr("cx", function(d) {
return X(d);
})
.attr("cy", function(d) {
return Y(d);
})
.attr("r", 4);
circle.attr("cx", function(d) {
return X(d);
})
.attr("cy", function(d) {
return Y(d);
});
circle.exit().remove();
}
function zoom_update() {
xyzoom = d3.behavior.zoom()
.x(xscale)
.y(yscale)
.on("zoom", zoomable ? draw : null);
xzoom = d3.behavior.zoom()
.x(xscale)
.on("zoom", zoomable ? draw : null);
yzoom = d3.behavior.zoom()
.y(yscale)
.on("zoom", zoomable ? draw : null);
svg.select('rect.zoom.xy.box').call(xyzoom);
svg.select('rect.zoom.x.box').call(xzoom);
svg.select('rect.zoom.y.box').call(yzoom);
}
function draw() {
svg.select('g.x.axis').call(xaxis);
svg.select('g.y.axis').call(yaxis);
update();
zoom_update();
};
// X value to scale
function X(d) {
return xscale(d[0]);
}
// Y value to scale
function Y(d) {
return yscale(d[1]);
}
chart.zoom = function (_){
if (!arguments.length) return zoomable;
zoomable = _;
return chart;
}
return chart;
}
</script>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js