我用我的问题创建了一个
gist.
我从this example开始.
所以我的问题是我需要一些放大和缩小按钮以及鼠标控件.
鼠标控件(通过拖动缩放轮子和平移)用zoom() behaviour实现.它工作得很好.
然后我添加了两个用于放大和缩小的按钮:
var _zoom = d3.zoom() .scaleExtent([1 / 2,8]) .on("zoom",zoomed); var gui = d3.select("#gui") gui.append("span") .classed("zoom in",true) .text("+") .on("click",function() { _zoom.scaleBy(container,2); }) gui.append("span") .classed("zoom out",true) .text("-") .on("click",function(){ _zoom.scaleBy(container,0.5); })
它们与鼠标行为发生冲突.要重现您必须缩放和拖动的错误(使用鼠标控件),然后单击跨度:当前转换将被覆盖.
怎么解决?
解决方法
要记住的关键是缩放变换存储在节点上,而不是存储在_zoom对象中.
在您的情况下,您在svg节点上设置鼠标侦听器,
svg.call(_zoom);
当在svg元素上触发缩放事件时,您可以获取svg节点的更新缩放变换并将其应用于g节点,
g.attr("transform",d3.event.transform);
在按钮单击时更新g元素的缩放时,您需要做的就是获取正确的变换,在您的情况下,获取svg节点的变换,
_zoom.scaleBy(svg,0.5);
这将正确触发svg节点上的缩放事件,下面全部更新,
var svg = d3.select("svg"),width = +svg.attr("width"),height = +svg.attr("height"); svg.style("border","solid 1px black"); var points = d3.range(2000).map(phyllotaxis(10)); var g = svg.append("g"); var _zoom = d3.zoom() .scaleExtent([1 / 2,8]) .on("zoom",function() { g.attr("transform",d3.event.transform); }); svg.call(_zoom); var container = g.selectAll("circle") .data(points) .enter().append("circle") .attr("cx",function(d) { return d.x; }) .attr("cy",function(d) { return d.y; }) .attr("r",2.5) function phyllotaxis(radius) { var theta = Math.PI * (3 - Math.sqrt(5)); return function(i) { var r = radius * Math.sqrt(i),a = theta * i; return { x: width / 2 + r * Math.cos(a),y: height / 2 + r * Math.sin(a) }; }; } var gui = d3.select("#gui"); gui.append("span") .classed("zoom in",function() { _zoom.scaleBy(svg,2); }); gui.append("span") .classed("zoom out",0.5); })
<svg width="960" height="500"></svg> <div id="gui"></div> <script src="https://d3js.org/d3.v4.min.js"></script>