Home > Software engineering >  When using a d3 Reusable Chart pattern how do you implement on drag when Dispatching Events (d3v5 )
When using a d3 Reusable Chart pattern how do you implement on drag when Dispatching Events (d3v5 )

Time:10-06

I am developing a set of d3 Reusable Charts - vanilla and in one page. (I know this is not great practice but as this is a learning exercise for me I find it easier to follow the code this way.) Using the pattern from ProD3 Book by Marcos Iglesias https://www.apress.com/gp/book/9781484252024.

I can implement on.click events (ish).

But I am trying to do so with Drag events using this "d3 minimal drag example" https://bl.ocks.org/codetricity/7ced6f3b3c95d64e7d7467e430716a63.

I have the Dispatcher object to broadcast the 'customHover' event:

const dispatcher = d3.dispatch('customDrag');

Then I have the ".on" event nested in the "draghandler" function with the "d3.drag()" called from the "enter selection". But I am not sure if this is correct way to do this - it is only configuration I tried that didn't cause errors.

        discs.enter()
            .append('circle')
            .attr('class', 'Discs')
            .attr('cx', 50)
            .attr('cy', 50)
            .attr('r', 20)
            .attr('stroke', 'black')
            .attr('fill', '#69a3b2');
    
        let dragHandler = d3.drag()
            .on('drag', function(d) {
                dispatcher.call('customDrag', this, d);
            });    
      
        discs.call(dragHandler);

Then the accessor function is here:

    exports.on = function() {
        let value = dispatcher.on.apply(dispatcher, arguments);

        return value === dispatcher ? exports : value;
    };

Then I have called this in this way:

    let position = [50]

    let myChart = d3.reusable.chart()
       .on('customDrag', function(d){
            d3.select(this).classed("dragging", true).attr('cx', d3.event.x).attr('cy', d3.event.y);
    });
 
    d3.select("#chart")
        .datum(position) 
        .call(myChart);

JSFiddle here: https://jsfiddle.net/Maltbyjim/y1mpuh4c/1/

I can't figure out where I am going wrong.

The only thing I think I may have missed is the possible translation of the x and y coord positions, but I don;t know how I would do that with drag coords.

Sorry if this seems daft, I don't understand d3 or js particularly well. And couldn't see a previous question that addressed this issue.

CodePudding user response:

I think the issue is related to this line:

discs.call(dragHandler);

You will need instead to select the discs again to apply the drag:

svg.select('.Discs').call(dragHandler);

See it working here: https://jsfiddle.net/mku50xyh/1/

  • Related