当`this`不可用时,d3 v4从拖动回调中检索拖动DOM目标

时间:2017-07-23 06:23:45

标签: d3.js

d3.drag的文档说明了拖拽事件的DOM元素目标将在this中提供给回调:

  

当调度指定的事件时,将使用与selection.on侦听器相同的上下文和参数调用每个侦听器:当前数据d和索引i,并将此上下文作为当前DOM元素。

但我的回调是一个对象实例,this指向该对象。所以我需要另一种方法来访问通常在this中传递的当前DOM元素。我该怎么办?

1 个答案:

答案 0 :(得分:4)

this不可用时,同时使用第二个和第三个参数获取this

d3.drag().on(typename, function(d, i, n) {
  //here, 'this' is simply n[i]
})

有关详细说明,请查看我在箭头函数中编写的用于处理this的文章。这个问题与你的不同,但解释是一样的。

这是一个基本演示,尝试拖动一个圆圈并查看控制台:

var data = d3.range(5)
var svg = d3.select("body")
  .append("svg")
  .attr("width", 400)
  .attr("height", 100);
var circle = svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .attr("cy", 50)
  .attr("cx", function(d) {
    return 50 + 50 * d
  })
  .attr("r", 10)
  .attr("fill", "tan")
  .attr("stroke", "black")
  .call(d3.drag()
    .on("start", function(d, i, n) {
      console.log(JSON.stringify(n[i]))
    }))
<script src="https://d3js.org/d3.v4.min.js"></script>

PS:我在D3选择中使用JSON.stringify,因为如果您尝试console.log选择D3,则堆栈片段会冻结。

使用带箭头功能的“this”

D3.js中的大多数函数都接受匿名函数作为参数。常见示例包括.attr.style.text.on.data,但列表大于此。

在这种情况下,将按顺序评估每个选定元素的匿名函数:

  1. 当前数据(d
  2. 当前索引(i
  3. 当前组(nodes
  4. this作为当前的DOM元素。
  5. 数据,索引和当前组作为参数传递,D3.js中的着名的第一,第二和第三个参数(其参数传统上被命名为di和{{1在D3 v3.x中)。但是,对于使用p,不需要使用任何参数:

    this

    当鼠标悬停在元素上方时,上面的代码将选择.on("mouseover", function(){ d3.select(this); }); 。检查它是否在这个小提琴中工作:https://jsfiddle.net/y5fwgopx/

    箭头功能

    作为一种新的ES6语法,与函数表达式相比,箭头函数的语法更短。但是,对于经常使用this的D3程序员来说,存在一个缺陷:箭头函数不会创建自己的this上下文。这意味着,在箭头函数中,this在封闭的上下文中具有其原始含义。

    这在几种情况下都很有用,但对于习惯在D3中使用this的编码器来说这是一个问题。例如,在上面的小提琴中使用相同的例子,这将不起作用:

    this

    如果你对此表示怀疑,这就是小提琴:https://jsfiddle.net/tfxLsv9u/

    嗯,这不是一个大问题:人们可以在需要时简单地使用常规的旧式函数表达式。但是,如果您想使用箭头函数编写所有代码,该怎么办?是否可以使用箭头函数的代码在D3中正确使用.on("mouseover", ()=>{ d3.select(this); });

    第二个和第三个参数合并

    答案是,因为thisthis相同。当它描述这个时,提示实际上存在于整个D3 API中:

      

    ...将nodes[i]作为当前DOM元素(this

    解释很简单:因为nodes[i]是DOM中当前的元素组,nodes是每个元素的索引,i引用当前的DOM元素本身。也就是nodes[i]

    因此,可以使用:

    this

    这是相应的小提琴:https://jsfiddle.net/2p2ux38s/