d3 平移和缩放时更新旧比例

zha*_*hou 3 javascript d3.js

我是 d3 的新手。当使用 进行平移和缩放时d3v4,我注意到我们总是必须基于 来创建新比例并将d3.event.transform新比例应用于所有内容,而不是用新比例替换旧比例并再次应用旧比例。例如,这个缩放功能就可以完美运行:

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)
};
Run Code Online (Sandbox Code Playgroud)

这个缩放功能搞砸了一切:

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)
};
Run Code Online (Sandbox Code Playgroud)

完整的示例在这里:https://bl.ocks.org/rutgerhofste/5bd5b06f7817f0ff3ba1daa64dee629d

我想使用新比例代替旧比例的原因是,就我而言,svg 的很多部分都与比例相关。如果我只是改变旧的比例,那些绑定的事件将完美地工作。我不想回收 ZoomFunction 中的所有内容。

Cyr*_*ian 5

所以你想改变

xAxisScale = new_xScale; yAxisScale = new_yScale;

由于某种原因在缩放功能内。

如果您这样做,重新缩放将无法按预期进行。

  var new_xScale = d3.event.transform.rescaleX(xAxisScale)
  var new_yScale = d3.event.transform.rescaleY(yAxisScale)
Run Code Online (Sandbox Code Playgroud)

原因: xAxisScale和yAxisScale应该是原始的,因为重新缩放是基于/相对于原始缩放值计算的。

解决这个问题的一种方法是复制原始的 x 和 y 比例。

// 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
Run Code Online (Sandbox Code Playgroud)

接下来在您的 ZoomFunction 中执行以下操作:

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)
};
Run Code Online (Sandbox Code Playgroud)

工作代码在这里