简体   繁体   English

如何在 D3 的 Angular 中使用“this”?

[英]How to use 'this' in Angular with D3?


Tldr;网址; How do I deal with this in reference to a D3 object when Angular binds this to the class (component/service)?当 Angular 将this绑定到类(组件/服务)时,我this如何处理引用 D3 对象的this


I am looking to use D3.js (v.4) in an Angular (v.4) app.我希望在 Angular (v.4) 应用程序中使用 D3.js (v.4)。

My code works in standalone JavaScript but I now need to integrate it into an Angular app.我的代码在独立的 JavaScript 中工作,但我现在需要将它集成到一个 Angular 应用程序中。

The use of this is tripping me up.使用this让我绊倒。

I have an SVG group that I wish to drag and so I use .call(drag)我有一个想要拖动的 SVG 组,所以我使用.call(drag)

someFunction() {
    this.unitGroup = this.svg.append('g')
            .attr('id', 'unitGroup');
            .call(drag)

}

My problem comes about when I try to reference the svg element that is being dragged.当我尝试引用被拖动的 svg 元素时,我的问题就出现了。 In my original code, I could refer to this eg let matrix = this.getCTM() .在我的原始代码中,我可以参考this例如let matrix = this.getCTM() Using this is now not working when using this code within a service.使用this是在服务中使用此代码的时候,现在不工作。

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})`);
    });

Any pointers on how to implement this or clarification of what I am doing wrong would be appreciated.任何关于如何实现这一点或澄清我做错了什么的指示将不胜感激。


I don't think this is simply an error associated with the arrow function this binding as .on('drag', function(d){...} results in the same error.我不认为这是简单地用箭头功能相关联的错误this结合作为.on('drag', function(d){...}导致同样的错误。


Here is Plunker illustrating my issue: https://embed.plnkr.co/p1hdhMBnaebVPB6EuDdj/这是 Plunker 说明我的问题: https ://embed.plnkr.co/p1hdhMBnaebVPB6EuDdj/

In most of D3 methods, this refers to the DOM element, and it is the most simple way to get the element.在大多数 D3 方法中, this指的是 DOM 元素,是获取元素最简单的方式。 However, you're facing some problems using this in your angular code.但是,在 angular 代码中使用this会遇到一些问题。

The good news is that there is an idiomatic way to get the current DOM element without relying on this (and without relying on d3.event as well): using the second and the third arguments combined.好消息是,有一种惯用的方式来获取当前的 DOM 元素,而不依赖this (也不依赖于d3.event ):结合使用第二个第三个参数。 This is quite useful in situations where you cannot use this , like your situation right now or when using an arrow function, for instance.这在您无法使用this情况下非常有用,例如您现在的情况或使用箭头函数时。

That alternative to this is extensively documented on the API.这替代this被广泛证明的API。 For most D3 methods, you can read that the method is...对于大多数 D3 方法,您可以阅读该方法是...

... being passed the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element ( nodes[i] ). ... 传递当前数据 (d)、当前索引 (i) 和当前组(节点),并将作为当前 DOM 元素(节点 [i] )。 (both emphases mine) (两者都强调我的)

So, in a common D3 code, you can get the DOM element using:因此,在常见的 D3 代码中,您可以使用以下方法获取 DOM 元素:

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

Or:或者:

.on("whatever", function(d,i,n){
//                         ^-^--- second and third arguments
    d3.select(n[i]).etc...
//              ^--- here, 'n[i]' is also the DOM element

Therefore, in your case, just use:因此,在您的情况下,只需使用:

.on('drag', (d,i,n) => {
    const m = d3.select(n[i]).node().getCTM();
//the same of 'this'-----^
...
}

Since d3.select(n[i]) is a selection , you'll have to use node() to get the actual DOM element.由于d3.select(n[i])是一个selection ,您必须使用node()来获取实际的DOM元素。

Here is your updated plunker: https://plnkr.co/edit/tjQ6lV411vAUcEKPh0ru?p=preview这是您更新的 plunker: https ://plnkr.co/edit/tjQ6lV411vAUcEKPh0ru ? p = preview

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

.on('drag', () => {
  const target = d3.event.sourceEvent.target;
  const m = target.getCTM();
  const x = d3.event.x - this.clickOrigin.x;
  const y = d3.event.y - this.clickOrigin.y;
  this.setClickOrigin(d3.event);
  d3.select(target)

Forked Plunker Example分叉的Plunker示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM