javascript - 如何完全停止 d3.zoom?

标签 javascript d3.js

给定这个运行片段:

var svgWidth = 800;
var svgHeight = 300;

var margin = {
  top: 30,
  right: 40,
  bottom: 50,
  left: 60
};

var width = svgWidth - margin.left - margin.right;
var height = svgHeight - margin.top - margin.bottom;

var originalCircle = {
  "cx": -150,
  "cy": -15,
  "r": 20
};

var svgViewport = d3.select("body")
  .append('svg')
  .attr('width', svgWidth)
  .attr('height', svgHeight);


// create scale objects
var xAxisScale = d3.scaleLinear()
  .domain([-200, -100])
  .range([0, width]);

var yAxisScale = d3.scaleLinear()
  .domain([-10, -20])
  .range([height, 0]);

// create axis objects
var xAxis = d3.axisBottom(xAxisScale);
var yAxis = d3.axisLeft(yAxisScale);

// Zoom Function
var zoom = d3.zoom()
  .on("zoom", zoomFunction);

// Inner Drawing Space
var innerSpace = svgViewport.append("g")
  .attr("class", "inner_space")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")").call(zoom);

// append some dummy data
var circles = innerSpace.append('circle')
  .attr("id", "circles")
  .attr("cx", xAxisScale(originalCircle.cx))
  .attr("cy", yAxisScale(originalCircle.cy))
  .attr('r', originalCircle.r);

// Draw Axis
var gX = innerSpace.append("g")
  .attr("class", "axis axis--x")
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis);

var gY = innerSpace.append("g")
  .attr("class", "axis axis--y")
  .call(yAxis);

// append zoom area
var view = innerSpace.append("rect")
  .attr("class", "zoom")
  .attr("width", width)
  .attr("height", height);

function zoomFunction() {
  gX.call(xAxis.scale(xAxisScale));
  gY.call(yAxis.scale(yAxisScale));
  circles.attr("transform", d3.event.transform)
};

function stop_zoom() {
  zoom = d3.zoom()
    .on("zoom", null);

  d3.select(".inner_space").call(zoom);
  console.log(d3.select(".inner_space"));
}

function start() {
  zoom = d3.zoom()
    .on("zoom", zoomFunction);

  d3.select(".inner_space").call(zoom);
  console.log(d3.select(".inner_space"));
}
.zoom {
  cursor: move;
  fill: none;
  pointer-events: all;
}
<!DOCTYPE html>
<meta charset="utf-8">

<body></body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<button onclick="stop_zoom()">stop zoom</button>
<button onclick="start()">do again</button>

  1. 停止缩放
  2. 将圆圈拖到不同的地方(在屏幕上,圆圈应该还在同一个地方)
  3. 再做一次并拖动圆圈
  4. 它仍然应用步骤 2 中的转换

这是显示问题的 gif:

Click here to see a gif demo of how to reproduce the problem

我的问题是:在我按下 stop zoom 后,如何阻止 d3 跟踪平移和缩放?

最佳答案

使用 selection.on 而不是更改缩放监听器。根据API :

Internally, the zoom behavior uses selection.on to bind the necessary event listeners for zooming.

所以,你的函数可以是:

function stop_zoom(){
    d3.select(".inner_space").on(".zoom", null);
}
function start(){
    d3.select(".inner_space").call(zoom);
}

下面是修改后的代码:

var svgWidth = 800;
var svgHeight = 300;

var margin = {
  top: 30,
  right: 40,
  bottom: 50,
  left: 60
};

var width = svgWidth - margin.left - margin.right;
var height = svgHeight - margin.top - margin.bottom;

var originalCircle = {
  "cx": -150,
  "cy": -15,
  "r": 20
};

var svgViewport = d3.select("body")
  .append('svg')
  .attr('width', svgWidth)
  .attr('height', svgHeight);


// create scale objects
var xAxisScale = d3.scaleLinear()
  .domain([-200, -100])
  .range([0, width]);

var yAxisScale = d3.scaleLinear()
  .domain([-10, -20])
  .range([height, 0]);

// create axis objects
var xAxis = d3.axisBottom(xAxisScale);
var yAxis = d3.axisLeft(yAxisScale);

// Zoom Function
var zoom = d3.zoom()
  .on("zoom", zoomFunction);

// Inner Drawing Space
var innerSpace = svgViewport.append("g")
  .attr("class", "inner_space")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")").call(zoom);

// append some dummy data
var circles = innerSpace.append('circle')
  .attr("id", "circles")
  .attr("cx", xAxisScale(originalCircle.cx))
  .attr("cy", yAxisScale(originalCircle.cy))
  .attr('r', originalCircle.r);

// Draw Axis
var gX = innerSpace.append("g")
  .attr("class", "axis axis--x")
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis);

var gY = innerSpace.append("g")
  .attr("class", "axis axis--y")
  .call(yAxis);

// append zoom area
var view = innerSpace.append("rect")
  .attr("class", "zoom")
  .attr("width", width)
  .attr("height", height);

function zoomFunction() {
  gX.call(xAxis.scale(xAxisScale));
  gY.call(yAxis.scale(yAxisScale));
  circles.attr("transform", d3.event.transform)
};

function stop_zoom() {
  d3.select(".inner_space").on(".zoom", null);
}

function start() {
  d3.select(".inner_space").call(zoom);
}
.zoom {
  cursor: move;
  fill: none;
  pointer-events: all;
}
<!DOCTYPE html>
<meta charset="utf-8">

<body></body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<button onclick="stop_zoom()">stop zoom</button>
<button onclick="start()">do again</button>

关于javascript - 如何完全停止 d3.zoom?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50463710/

相关文章:

javascript - `this` 在全局上下文和内部函数中

javascript - qt webengine 将 javascript 输出重定向到 GUI

javascript - d3 缩放/平移行为以毫秒为间隔变化

javascript - d3.queue 从不触发 .await 函数

javascript - 在ReactJS中超过api限制时的错误处理

javascript - AngularJS:将菜单作为部分内容包含在index.html中

javascript - 消除矩形中间的边界半径

d3.js - 交叉过滤查询

javascript - 将 d3.js SVG 移植到 HTML5 Canvas?

javascript - 使用相同 View 的 React-Native 2 按钮