How to temporarily disable the zooming in d3.js

karlitos picture karlitos · Sep 13, 2013 · Viewed 11.5k times · Source

I am searching for a possibility to temporarily disable the zooming functionality provided by the d3 library. I tried to save the cave the current scale/translation values when the zooming is deactivated and set the zoom/translate-values when the zooming is active again. Unfortunately this will not work.

Here is a code example I created :

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()
     }
};

Here is a working jsfiddle example.

EDIT:

The false behavior can be reproduced by following steps :

  1. Click on the circle, the color changes to blue,zooming is not working
  2. Use mouse wheel IN ONE DIRECTION several times as if you would be zooming (e.g. zoom in)
  3. Click again on the circle, the color chnages to red, zoom is re-enabled
  4. Use mouse wheel, the circle will be huge/tiny

Answer

hughes picture hughes · Apr 21, 2015

The easiest way I've found is to simply disable all the .zoom events on the selection. You'll have to re-call zoom to enable the behavior again.

if (zoomEnabled) {
    svg.call(zoom);
} else {
    svg.on('.zoom', null);
}

jsfiddle