I would like to know how can I deal with Zoom and Brush behaviours at the same time.
Imagine you have an application that controls whether a "Select Area" option is activated or not. If activated, then when an user starts selecting visually it's expected to brush a set of SVG elements. If deactivated, then the user would be moving some SVG container (pan).
How can I declare both native d3 behaviours without overriding between each other and working properly using an state? Or, is it the only solution I have to go destroying events and declaring new ones and viceversa when the user wants a different behaviour?
Or, is there another different way of doing it?
A piece of code I have is the following one:
var zoomer, brush;
zoomer = self.get('zoomer');
if (zoomer === undefined){
    self.set({zoomer: d3.behavior.zoom().translate([0,0]).scale(1)});
} else{
    self.zoomCurrent();
}
brush = self.get('brush');
if (brush === undefined) {
    self.set({brush: d3.svg.brush().x(d3.scale.identity().domain([0, self.get('config').width]))
        .y(d3.scale.identity().domain([0, self.get('config').height]))});
}
svgObject = d3.select(self.get('target')).append('svg')
    .attr('xmlns', 'http://www.w3.org/2000/svg')
    .attr('xlink', 'http://www.w3.org/1999/xlink')
    .attr('id', self.get('targetNoChar')+'SVG')
    .attr('width',self.get('config').width)
    .attr('height',self.get('config').height)
    .attr("pointer-events", "all")
    .call(self.get('zoomer').on("zoom", function (d) { self.zoomFunction(d3.event, this,d) }))
    .append('g')
        .attr('class', 'zoomer')
        .attr("pointer-events", "all")
    .append('g')
    .attr("pointer-events", "all");
d3.select('svg').append('g')
        .attr('class', 'brush')
        .attr("pointer-events", "all")
        .datum(function() { return { selected: false, previouslySelected: false};})
        .call(self.get('brush').on('brushstart', function (d) { self.brushStart(d3.event, this,d) })
            .on('brush', function (d) { self.brush(d3.event, this,d) })
            .on('brushend', function (d) { self.brushEnd(d3.event, this,d) }));
How can I deal with d3.behaviour.zoom and also brush without they override each other?
Thanks a lot in advance.
FIRST SOLUTION FOUND:
Finally, my decision has been re-declaring events definition when the state changes, ending up with the following code:
setAreaMode: function () {
        var self = this;
        if (self.get('selectAreaMode')===true) {
            self.setCursorToCrosshair();
            /* Deactivating zoom tool */
            self.get('zoomer').on('zoom', null);
            /* Adding brush to DOM */
            d3.select('svg').append('g')
                .attr('class', 'brush')
                .attr("pointer-events", "all")
                .datum(function() { return { selected: false, previouslySelected: false};});
            /* Attaching listeners to brush */
            d3.select('.brush').call(self.get('brush').on('brushstart', function (d) { self.brushStart(d3.event, this,d) })
                .on('brush', function (d) { self.brush(d3.event, this,d) })
                .on('brushend', function (d) { self.brushEnd(d3.event, this,d) })
            );
        } else if (self.get('selectAreaMode')===false) {
            self.setCursorToDefault();
            /* Activating zoomer */
            self.get('zoomer').on('zoom', function (d) { self.zoomFunction(d3.event, this,d) });
            /* Deactivating listeners brush tool */
            d3.select('.brush').call(self.get('brush').on('brushstart', null)
                .on('brush', null)
                .on('brushend', null));
            /* Removing brush from DOM */
            d3.select('.brush').remove();
        }
    }
Any other ideas?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With