Javascript 如何在D3中使用“this”?

Javascript 如何在D3中使用“this”?,javascript,angular,d3.js,svg,Javascript,Angular,D3.js,Svg,Tldr;当Angular将D3对象绑定到类组件/服务时,如何在引用D3对象时处理此问题 我希望在Angular v.4应用程序中使用D3.js v.4 我的代码在独立的JavaScript中工作,但我现在需要将其集成到Angular应用程序中 使用这个让我很困惑 我有一个想要拖动的SVG组,因此我使用.calldrag 当我尝试引用正在拖动的svg元素时,问题就出现了。在我的原始代码中,我可以引用它,例如让matrix=this.getCTM。在服务中使用此代码时,现在无法使用此代码 drag

Tldr;当Angular将D3对象绑定到类组件/服务时,如何在引用D3对象时处理此问题

我希望在Angular v.4应用程序中使用D3.js v.4

我的代码在独立的JavaScript中工作,但我现在需要将其集成到Angular应用程序中

使用这个让我很困惑

我有一个想要拖动的SVG组,因此我使用.calldrag

当我尝试引用正在拖动的svg元素时,问题就出现了。在我的原始代码中,我可以引用它,例如让matrix=this.getCTM。在服务中使用此代码时,现在无法使用此代码

drag = d3.drag()
    .on('start', () => {
        this.setClickOrigin(d3.event);
    })
    .on('drag', (d) => {
        const m = this.getCTM(); // <--- PROBLEM HERE
        const x = d3.event.x - this.clickOrigin.x;
        const y = d3.event.y - this.clickOrigin.y;
        this.setClickOrigin(d3.event);
        d3.select(this) // <--- PROBLEM HERE
            .attr('transform', `matrix(${m.a},${m.b},${m.c},${m.d},${m.e + x},${m.f + y})`);
    });
任何关于如何实现这一点或澄清我做错了什么的建议都将不胜感激

我不认为这只是一个与此绑定的箭头函数相关联的错误,因为在“拖动”时,函数d{…}会导致相同的错误

以下是Plunker对我的问题的说明:

尝试使用d3.event.sourceEvent.target:

在大多数D3方法中,这是指DOM元素,这是获取元素的最简单方法。但是,在angular代码中使用它会遇到一些问题

好消息是,有一种惯用方法可以获取当前DOM元素,而不依赖于此,也不依赖于d3.event:将第二个和第三个参数组合使用。这在您无法使用它的情况下非常有用,例如您现在的情况或使用箭头函数时

API中广泛记录了这一替代方案。对于大多数D3方法,您可以看到该方法是

。。。传递当前数据d、当前索引i和当前组节点,并将其作为当前DOM元素节点[i]。两者都强调我的观点

因此,在常见的D3代码中,可以使用以下方法获取DOM元素:

.on("whatever", function(){
    d3.select(this).etc...
//              ^--- 'this' is the DOM element
或:

因此,在您的情况下,只需使用:

.on('drag', (d,i,n) => {
    const m = d3.select(n[i]).node().getCTM();
//the same of 'this'-----^
...
}
由于d3.selectn[i]是一个选择,因此必须使用node来获取实际的DOM元素


这是您更新的plunker:

可能重复更改为“拖动”,函数d{…}无法解决此问题。您可以在plunker中复制它吗?您可以尝试将其更改为像d3.selectdrag一样拖动,或者您正在查找d3.event.currentTarget,而不是此。我将看看如何执行此操作。一开始,由于需要的代码太多,我很犹豫是否要这么做,我希望有人能识别我的错误。我想在plunker中看到它。这里是我的d3示例,感谢您的解决方案!我已经将@GerardoFurtado的答案标记为已被接受,因为它看起来更可靠。当移动解决方案中的深灰色方框时,事件有时会切换到较大的方框,然后将其移动。它解决了其中一个问题!我很感谢你的帮助。下一个问题中的奖励积分:太好了!非常感谢。Plunker按预期工作。为了在我的代码中实现这一点,我必须做一些小的调整,以获得一个要传递的键入错误-类型“Element”上不存在属性“getCTM”。const m=d3。选择n[i]作为any.node.getCTM;有趣的当d3在我的AppComponent中声明时,您如何引用d3而不声明它。d3?在我的例子中,我在AppComponent的ngOnInit上创建了画布,如果不说明这一点,我似乎无法引用d3。d3@MichaelArdan很抱歉,我不是angular用户。非常感谢您的帮助-以编程方式同时使用angular和d3对于这样的东西来说真的很痛苦。非常感谢!对于面积图,我也面临同样的问题,但这种方法解决了我的问题。
.on("whatever", function(){
    d3.select(this).etc...
//              ^--- 'this' is the DOM element
.on("whatever", function(d,i,n){
//                         ^-^--- second and third arguments
    d3.select(n[i]).etc...
//              ^--- here, 'n[i]' is also the DOM element
.on('drag', (d,i,n) => {
    const m = d3.select(n[i]).node().getCTM();
//the same of 'this'-----^
...
}