我正在寻找暂时禁用d3库提供的缩放功能的可能性。我尝试在停用缩放时保存洞穴当前缩放/平移值,并在再次激活缩放时设置缩放/平移值。不幸的是,这不起作用。
这是我创建的代码示例:
var savedTranslation = null;
var savedScale = null;
var body = d3.select("body");
var svg = body.append("svg");
var svgContainer = svg.append("svg:g");
var circle = svgContainer.append("svg:circle")
.attr('cx', 100)
.attr('cy', 100)
.attr('r',30)
.attr('fill', 'red');
circle.on('click', clickFn);
function clickFn(){
if (circle.attr('fill') === 'red'){
circle.attr('fill','blue')
}
else if (circle.attr('fill') === 'blue'){
circle.attr('fill','red')
}
};
svg.call(zoom = d3.behavior.zoom().on('zoom', redrawOnZoom)).on('dblclick.zoom', null);
function redrawOnZoom(){
if (circle.attr('fill') === 'red'){
if (savedScale !== null){
zoom.scale(savedScale)
savedScale = null
}
if (savedTranslation !== null){
zoom.translate(savedTranslation)
savedTranslation = null
}
// the actual "zooming"
svgContainer.attr('transform', 'translate(' + d3.event.translate + ')' + ' scale(' + d3.event.scale + ')');
}
else {
// save the current scales
savedScale = zoom.scale()
savedTranslation = zoom.translate()
}
};
编辑:
可以通过以下步骤复制虚假行为:
答案 0 :(得分:8)
我发现的最简单方法是简单地禁用所选的.zoom
个事件。您必须重新调用zoom
才能再次启用该行为。
if (zoomEnabled) {
svg.call(zoom);
} else {
svg.on('.zoom', null);
}
答案 1 :(得分:4)
我一直在努力解决同样的问题。而且,我找到了一种解决方案,可以保存缩放和平移,而不会出现您在当前解决方案中看到的跳跃。
主要更改是执行缩放的保存/更新并在“单击”功能中进行翻译。因此,可以使用缩放功能的参考,必须在缩放行为之后设置单击。解决方案看起来像这样。您问题中的相同样板:
var savedTranslation = null;
var savedScale = null;
var body = d3.select("body");
var svg = body.append("svg");
var svgContainer = svg.append("svg:g");
var circle = svgContainer.append("svg:circle")
.attr('cx', 100)
.attr('cy', 100)
.attr('r',30)
.attr('fill', 'red');
然后是缩放功能,无需管理已保存的比例并翻译:
svg.call(zoom = d3.behavior.zoom().on('zoom', redrawOnZoom)).on('dblclick.zoom', null);
function redrawOnZoom(){
if (circle.attr('fill') === 'red'){
// the actual "zooming"
svgContainer.attr('transform', 'translate(' + zoom.translate() + ')' + ' scale(' + zoom.scale() + ')');
}
};
最后,附上下面的点击行为,并保存并设置比例和翻译:
circle.on('click', clickFn);
function clickFn(){
if (circle.attr('fill') === 'red'){
circle.attr('fill','blue')
if (savedScale === null){
savedScale = zoom.scale();
}
if (savedTranslation === null){
savedTranslation = zoom.translate();
}
}
else if (circle.attr('fill') === 'blue'){
circle.attr('fill','red')
if (savedScale !== null){
zoom.scale(savedScale);
savedScale = null;
}
if (savedTranslation !== null){
zoom.translate(savedTranslation);
savedTranslation = null;
}
}
};
这是一个有效的版本:http://jsfiddle.net/cb3Zm/1/。
然而,当发生拖动时仍然会发生点击事件,这看起来并不理想,但我还没能解决它。
答案 2 :(得分:2)
请参阅更新的小提琴:http://jsfiddle.net/prayerslayer/La8PR/1/
我在点击处理程序中重新分配了一个空缩放行为。
function clickFn(){
if (circle.attr('fill') === 'red'){
circle.attr('fill','blue');
svg.call( fake );
}
else if (circle.attr('fill') === 'blue'){
circle.attr('fill','red');
svg.call( zoom );
}
};
我认为有一个更好的解决方案,因为我可能会引入内存泄漏。
优于全局doZoom
标记的优点是您不必保存和检查缩放和转换值,因为缩放行为继续有效(例如设置d3.event.scale
)即使您是不改变观点。
答案 3 :(得分:2)
Yabba Dabba Doo!
好的,问题在于
else {
// save the current scales
savedScale = zoom.scale()
savedTranslation = zoom.translate()
}
一部分。每个事件都会调用这些值,而不仅仅是在圆圈改变颜色后调用一次。所以解决方案是:
else {
// save the current scales
if (savedScale === null){
savedScale = zoom.scale();
}
if (savedTranslation === null){
savedTranslation = zoom.translate();
}
现在它的工作原理! Updated jsFiddle here.
答案 4 :(得分:2)
当我找到解决方案时,我想赶上这个! 诀窍是重置比例并在zoomstart和zoomend事件中进行转换。
var zoom = d3.behavior.zoom()
.scaleExtent([1, 10])
.on("zoomstart", zoomstart)
.on("zoomend", zoomend)
.on("zoom", zoomed);
function zoomed() {
if (circle.attr('fill') === 'red') {
if (savedScale !== null){
zoom.scale(savedScale);
}
if (savedTranslation !== null){
zoom.translate(savedTranslation);
}
svgContainer.attr('transform', 'translate(' + d3.event.translate + ')' + ' scale(' + d3.event.scale + ')');
}
}
function zoomend () {
if (circle.attr('fill') === 'red') {
if (savedScale !== null){
zoom.scale(savedScale);
savedScale = null;
}
if (savedTranslation !== null){
zoom.translate(savedTranslation);
savedTranslation = null;
}
}
}
function zoomstart (d) {
if (circle.attr('fill') === 'red'){
if (savedScale !== null){
zoom.scale(savedScale)
}
if (savedTranslation !== null){
zoom.translate(savedTranslation)
}
} else {
if (savedScale === null) {
savedScale = zoom.scale();
}
if (savedTranslation === null) {
savedTranslation = zoom.translate();
}
}
}
答案 5 :(得分:1)
我实现此方法的方法是使用全局标志来告诉您是否启用了缩放。然后,您只需要检查是否在处理缩放的函数中设置了此标志。如果是,则该功能不执行任何操作。
答案 6 :(得分:0)
我觉得以这种方式做得更漂亮。
function clickFn(){
if (circle.attr('fill') === 'red'){
circle.attr('fill','blue');
savedScale = zoom.scale();
savedTranslation = zoom.translate();
}
else if (circle.attr('fill') === 'blue'){
circle.attr('fill','red');
zoom.scale(savedScale);
zoom.translate(savedTranslation);
}
};
svg.call(zoom = d3.behavior.zoom().on('zoom', redrawOnZoom)).on('dblclick.zoom', null);
function redrawOnZoom(){
if (circle.attr('fill') === 'red'){
// the actual "zooming"
svgContainer.attr('transform', 'translate(' + d3.event.translate + ')' + ' scale(' + d3.event.scale + ')');
}
};
答案 7 :(得分:0)
https://github.com/d3/d3-zoom/issues/156
const svg = d3.select(svgElement);
const zoom = d3.zoom();
function startZoomPan() {
svg.call(zoom); // attach the zoom listeners
}
function stopZoomPan() {
svg.on('.zoom', null); // remove the zoom listeners
}
mousemove 处理程序是热代码,所以在那里分支很慢