如何完全停止d3.zoom?

时间:2018-05-22 09:00:54

标签: 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>
&#13;
&#13;
&#13;

  1. 停止缩放
  2. 将圆圈拖到不同的位置(在屏幕上,圆圈仍应在同一位置)
  3. 再次执行并拖动圆圈
  4. 它仍然适用于步骤2中的转换
  5. 这是一个显示问题的GIF:

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

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

1 个答案:

答案 0 :(得分:3)

使用selection.on而不是更改缩放侦听器。根据{{​​3}}:

  

在内部,缩放行为使用selection.on绑定必要的事件侦听器以进行缩放。

所以,你的功能可以只是:

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>