Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.8k views
in Technique[技术] by (71.8m points)

d3.js - D3v6 drag event callback function fire with undefined parameters

Following the D3v6 documentation, i am unable to implement a simple dragging behaviour on a path SVG element drawn using the d3.symbol util. The typescript class is shown here as a context. The events trigger on the correct element but the callback functions do not seem to receive the (event, datum) parameters. Any help would be greatly appreciated.

import * as d3 from "d3";

export default class Sliders {
    svg: SVGSVGElement;

    constructor(svg: SVGSVGElement){
        this.svg = svg;
    }

    draw(){
        const g = d3.select(this.svg).append('g').attr('class', 'symbol');   
        const circle = g.append('circle').attr('r', 200);

        const D = d3.drag() // `event` and `d` are always undefined in 3 lines below
            .on("start", (event, d) => circle.attr("stroke", "lime"))
            .on("drag", (event, d: any) => (d.x = event.x, d.y = event.y))
            .on("end", (event, d) => circle.attr("stroke", "black")) as any; // Could not fathom the proper type
        circle.call(D); 
    }
}
question from:https://stackoverflow.com/questions/65830586/d3v6-drag-event-callback-function-fire-with-undefined-parameters

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A possible cause for the issue is that the d3 version used in the first example is not v6.0. There was a significant change from v5.x to v6.0 where the event is no longer a global variable but passed as a parameter in callbacks.

Your code is in v6.0 style, so it works in the second example, where it is explicitly importing v6.0 from https://d3js.org/

You can confirm if your original code is running d3 v6.0 with a console.log(d3.event) inside one of the callbacks:

  .on("drag", () => { 
    console.log(d3.event);
  })  

If the code above logs the event, it means your d3 is in version v5.x. If it works, but typescript also gives a type error anyway, it means that your typings (@types/d3) are for v6.0, so they are not aligned with the installed version of d3.

In any case, if d3.event works, then the easiest solution is to update your d3 to v6.0 since you already have the code compatible with the latest version.

The second parameter of the callback is the datum bound to the element. In your example, it is expected to be undefined because there is no datum associated with the circle (i.e., there is no .selectAll(...).data(...) before the .append()). If interested, you could check a d3-drag example in v.6.0 that uses data binding to understand it better.

So, a minimal drag behavior example in v5.0, without data binding, would be:

 .on("drag", function() { 
    d3.select(this).attr("cx", d3.event.x).attr("cy", d3.event.y);
  })  

And in v6.0:

 .on("drag", function(event) { 
    d3.select(this).attr("cx", event.x).attr("cy", event.y);
  })  

Node: Remember to use the function keyword instead of an arrow function (() => ...) if you want acess to the correct this object inside it


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...