Reputation: 2701
I am new to d3. When do pan and zoom with d3v4
, I noticed we always have to create new scale based on the d3.event.transform
and apply the new scale to everything rather than replace the old scale with new and apply the old scale again. For example, this zoom function works perfect:
function zoomFunction(){
// create new scale ojects based on event
var new_xScale = d3.event.transform.rescaleX(xAxisScale)
var new_yScale = d3.event.transform.rescaleY(yAxisScale)
console.log(d3.event.transform)
// update axes
gX.call(xAxis.scale(new_xScale));
gY.call(yAxis.scale(new_yScale));
// update circle
circles.attr("transform", d3.event.transform)
};
This zoom function screws everything:
function zoomFunction(){
// create new scale ojects based on event
var new_xScale = d3.event.transform.rescaleX(xAxisScale)
var new_yScale = d3.event.transform.rescaleY(yAxisScale)
xAxisScale = new_xScale;
yAxisScale = new_yScale;
console.log(d3.event.transform)
// update axes
gX.call(xAxis.scale(xAxisScale));
gY.call(yAxis.scale(yAxisScale));
// update circle
circles.attr("transform", d3.event.transform)
};
The full example is here: https://bl.ocks.org/rutgerhofste/5bd5b06f7817f0ff3ba1daa64dee629d
The reason I want to use the new scale to replace the old one is that in my case a lot of parts of svg are related to scale. If I simply change the old scale, those binded events will work perfectly. I don't want to reclaim everything in my zoomFunction.
Upvotes: 3
Views: 1032
Reputation: 32327
So you wish to change
xAxisScale = new_xScale;
yAxisScale = new_yScale;
inside the zoom function for some reason.
If you do it the rescale will not work as expected.
var new_xScale = d3.event.transform.rescaleX(xAxisScale)
var new_yScale = d3.event.transform.rescaleY(yAxisScale)
Reason: xAxisScale andyAxisScale should be the original, because the rescale is calculated based/relative to the original scale value.
One way to get around this would be to make a copy of the original x and y scale.
// create scale objects
var xAxisScale =d3.scaleLinear()
.domain([-200,-100])
.range([0,width]);
var yAxisScale = d3.scaleLinear()
.domain([-10,-20])
.range([height,0]);
//make a copy of the scales
var copyX = xAxisScale.copy();
var copyY = yAxisScale.copy();
// create axis objects
Next in your zoomFunction do :
function zoomFunction(){
// create new scale ojects based on event
var new_xScale = d3.event.transform.rescaleX(copyX)
var new_yScale = d3.event.transform.rescaleY(copyY)
//changing scale due to some reason.
xAxisScale = new_xScale;
yAxisScale = new_yScale;
// update axes
gX.call(xAxis.scale(xAxisScale));
gY.call(yAxis.scale(yAxisScale));
// update circle
circles.attr("transform", d3.event.transform)
};
working code here
Upvotes: 5