在D3v6文档之后,我无法在使用d3绘制的路径SVG元素上实现简单的拖动行为。util象征。typescript类在这里显示为上下文。事件在正确的元素上触发,但回调函数似乎没有接收到(event, datum)参数。如有任何帮助,我将不胜感激。
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);
}
}
问题的可能原因是第一个示例中使用的d3
版本不是v6.0。与v5相比有很大的变化。从X到v6.0,事件不再是全局变量,而是在回调中作为参数传递。
您的代码是v6.0风格的,因此它在第二个示例中工作,其中它显式地从https://d3js.org/
导入v6.0。您可以确认您的原始代码是否运行d3 v6.0,其中一个回调中包含console.log(d3.event)
:
.on("drag", () => {
console.log(d3.event);
})
如果上面的代码记录事件,这意味着您的d3版本是v5.x。如果它工作,但typescript也给出了一个类型错误,这意味着你的类型(@types/d3
)是v6.0的,所以它们不与d3的安装版本对齐。
在任何情况下,如果d3.event
工作,那么最简单的解决方案是更新你的d3到v6.0,因为你已经有代码与最新版本兼容。
回调函数的第二个参数是绑定到元素的数据。在您的示例中,它预计是undefined
,因为没有与圆相关的基准(即,在.append()
之前没有.selectAll(...).data(...)
)。如果感兴趣,您可以查看v.6.0中使用数据绑定的3d -drag示例,以便更好地理解它。
.on("drag", function() {
d3.select(this).attr("cx", d3.event.x).attr("cy", d3.event.y);
})
而在v6.0中:
.on("drag", function(event) {
d3.select(this).attr("cx", event.x).attr("cy", event.y);
})
节点:如果您希望访问其中正确的this
对象,请记住使用function
关键字而不是箭头函数(() => ...
)
自己回答一些细节。剥离任何webpack/typescript业务,在单个html文件中,定义了拖动事件回调参数
<!DOCTYPE html>
<meta charset="utf-8">
<div id="data"> </div>
<script src="https://d3js.org/d3.v6.min.js"></script>
<script>
const svg = d3.select('#data').append('svg').attr('width', 500).attr('height', 500);
console.log(svg);
const circle = svg.append('circle').attr('r', 5).attr('cy', 25).attr('cx', 25);
// `event` parameter is defined
const D = d3.drag()
.on("start", (event, d) => circle.attr("stroke", "lime"))
.on("drag", (event, d) => {
console.log(event);
})
.on("end", (event, d) => circle.attr("stroke", "black"));
circle.call(D);
</script>
并不能解决我最初的问题。