reference: https://github.com/mbostock/d3/wiki/Zoom-Behavior
//make zoom
var zoomFirst = d3.behavior.zoom()
.x(x)
.y(y1)
.scaleExtent([0, 3])
.size([w, h])
//.center([w/2+200, h/2-200])
.on("zoom", zoomedFirst);
function zoomedFirst() {
svgContainer.select(".x.axis").call(xAxis);
svgContainer.selectAll(".y.axis.axisLeft").call(yAxisLeft);
//set y2's scale manually
svgContainer.select(".price")
.attr("d", line1(priceData))
.attr("class", "price");
svgContainer.select(".difficulty")
.attr("d", line2(difficultyData))
.attr("class", "difficulty");
}
d3.behavior.zoom()
supports autoscaling of x and y axes. However, I have to scale two y axes at the same time. When zoom() is triggered, I can get the current scale
and translate
info from d3.event.scale
and d3.event.translate
, but I cant figure out how to make appropriate scale for the second y axis(y2
) with them.
I am also looking at https://github.com/mbostock/d3/wiki/Quantitative-Scales.
Since y1
's range is automatically adjusted by zoom
, if there is a way to get y1
's current range, I can get its min and max and set y2
's range based on them. However, the document doesn't specify a way to get range
given a scale
object.
Calling y1.range()
(without any arguments) will return you the [min, max]
of the scale.
From the docs:
If values is not specified, returns the scale's current output range.
Most accessor functions in D3 work like this, they return you (get) the value if you call them without any arguments and set the value if you call them with arguments and return the this
object for easy chaining:
d3Object.propertyName = function (_) {
if (!arguments.length) return propertyName;
propertyName = _;
return this;
}
However, the zoom
behaviour alters the domain
and not the range
of the scales.
From the docs:
Specifies an x-scale whose domain should be automatically adjusted when zooming.
Hence, you do do not need to get/set the range
, but instead the domain
of the scales y1
and y2
: y2.domain(y1.domain())
.
Since the zoom function already manages all the ratios, a more abbreviated answer would be:
var zoomFirst = d3.behavior.zoom()
.x(x)
.y(y1)
.scaleExtent([0, 3])
.size([w, h])
.on("zoom", function() {
zoomSecond.scale(zoom.scale());
zoomSecond.translate(zoom.translate());
// Update visual. Both y domains will now be updated
});
// Create copy for y2 scale
var zoomSecond = d3.behavior.zoom()
.x(x)
.y(y2) // <-- second scale
.scaleExtent([0, 3]) // <-- extent
This assumes you have called only zoomFirst to your visual.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With