Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to temporarily disable the zooming in d3.js

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
like image 561
karlitos Avatar asked Sep 13 '13 13:09

karlitos


People also ask

How to use zoom () function in D3 JS?

The d3.zoom () Function in D3.js is used to create a new zoom behaviour. It is used to apply the zoom transformation on a selected element. Parameters: This function does not accept any parameter. Return Value: This function returns the zoom behaviour. Below programs illustrate the d3.zoom () function in D3.js

How do i Zoom in on a circle?

Click on the circle, the color changes to blue,zooming is not working Use mouse wheel IN ONE DIRECTION several times as if you would be zooming (e.g. zoom in) Click again on the circle, the color chnages to red, zoom is re-enabled The easiest way I've found is to simply disable all the .zoom events on the selection.

Is there a way to change the zoom behavior of click?

The main change is to perform the saving/updating of zoom and translate in the "click" function. And so that a reference to the zoom function is available, the click must be set after the zoom behavior. The solution looks like this.

How do i Zoom in/out of a brush zone?

Select a zone to zoom on it (X axis only). Double click to unzoom. A clipPath is used to avoid displaying the circle outside the chart area. all (brush.move, null) is used to dismiss the grey brushing area once the selection has been done.


2 Answers

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

like image 54
hughes Avatar answered Nov 15 '22 15:11

hughes


See the updated fiddle: http://jsfiddle.net/prayerslayer/La8PR/1/

There I reassign an empty zoom behavior in the click handler.

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

I suppose there is a better solution as mine probably introduces memory leaks.

The advantage over a global doZoom flag is that you don't have to save and check scale and translation values because the zoom behavior continues to work (e.g. setting d3.event.scale) even though you're not altering the view.

like image 39
prayerslayer Avatar answered Nov 15 '22 15:11

prayerslayer