Javascript d3.select(此选项)适用于鼠标悬停,但不适用于鼠标悬停中调用的函数

Javascript d3.select(此选项)适用于鼠标悬停,但不适用于鼠标悬停中调用的函数,javascript,d3.js,this,Javascript,D3.js,This,我是javascript新手,目前正在努力选择这个对象,同时尝试进行d3选择。我使用正在调用的函数和on mousemove事件制作了以下示例: function changeFont() { d3.select(this) .attr('font-size', '2em') } ... .on('mousemove', function() { var mouse = d3.mouse(this); var xVal = mouse[0]; // this woul

我是javascript新手,目前正在努力选择这个对象,同时尝试进行d3选择。我使用正在调用的函数和on mousemove事件制作了以下示例:

function changeFont() {
  d3.select(this)
    .attr('font-size', '2em')
}

...
.on('mousemove', function() {
  var mouse = d3.mouse(this);
  var xVal = mouse[0];

  // this would work, but not when its called in a function
  // d3.select(this)
  //  .attr('font-size', '2em')

  // this works
  d3.select(this)
   .attr("opacity", 1)

  // this doesnt
  changeFont()
});
在这里没有显示的主脚本中,我通过编写处理mousemove、mouseover等效果的函数来组织代码。但是由于这些函数,我遇到了这个问题,我不能做d3。在鼠标悬停函数中选择(这个)。。。有没有想过我应该采取什么不同的做法

我应该将其作为参数传递给changeFont()函数吗?或者我应该以不同的方式访问它


谢谢

让我们看看您的每种方法都定义了什么:

// console.log(this) in inline function:
<svg width="960" height="960"> 

// console.log(this) in function called from inline function:
Window → file:///fileName.html
虽然如果你从字面上理解这个问题,安德鲁的可能是最合适的,但我想再加上我的两分钱。你真正的问题似乎不是抓住
这个
,而是反复访问该元素以应用你的操作。由于在JavaScript中摆弄
这个
可能是一件痛苦的事情,因此可能需要采取稍微不同的方法,直接传递选择。这也将提高性能,因为无需反复选择
This

首先,让我们稍微重构一下
changeFont()
函数,以接受一个选择对象

function changeFont(selection) {
  selection
    .attr('font-size', '2em');
}
请注意,这如何使函数更普遍适用,因为它不会对传入的选择进行任何假设。它可以是您的
d3。选择(此)
,一个包含多个元素的选择或任何其他d3选择对象。此外,您不需要保留以前的
范围

调用此函数基本上有两种方法

  • 调用函数时,最明显的一个选项将直接将选择作为参数传递:

    const d3This = d3.select(this);
    changeFont(d3This);
    
  • 幸运的是,有一种更优雅的方法可以使用D3自己的方法,如果需要对同一个选择执行多个调用,甚至可以使用方法链接

    function changeFont(selection) { selection.attr("font-size", "2em"); }
    function changeFill(selection) { selection.attr("fill", "limegreen"); }
    function changeOpacity(selection) { selection.attr("opacity", "0.1"); }
    
    // ...
    .on("mouseover", function() {
      // Call the functions for this element.
      d3.select(this)
        .call(changeFont)
        .call(changeFill)
        .call(changeOpacity);
    
      // Instead, you could also apply the same pattern to all texts.
      d3.selectAll("text")
        .call(changeFont)
        .call(changeFill)
        .call(changeOpacity);
    
    }
    

  • 为了完整起见,因为这个问题已经有了两个非常好的答案:如果您结合使用第三个和第二个参数,您可以避免与
    this
    混淆。甚至D3开发人员最终也会忘记这一点

    在一些D3方法中,当前DOM元素只是节点组的当前索引。所以,在匿名函数中

    .on("mouseover", function(_, i, n) {
    
    只是
    n[i]
    ,您可以将其传递给其他函数。这里的
    \uu
    对应于第一个参数,即数据:我使用
    \u
    只是为了遵循显示未使用此参数的约定

    这种方法的好处是,您甚至可以(出于任何原因)使用箭头函数:

    d3.选择(“主体”).选择全部(空)
    .数据([“foo”、“bar”、“baz”])
    .输入()
    .附加(“p”)
    .文本(字符串)
    .on(“mouseover”,(u,i,n)=>{
    changeFont(n[i])
    });
    函数changeFont(元素){
    d3.选择(元素).样式(“字体大小”,“2em”)
    }

    我不确定是否100%关注您的问题,但“this”仅在每个函数中具有作用域。要在嵌套函数中使用父函数中的“this”,请将其分配给变量并向下传递。这有意义吗?@Andrewerid为了完整性,值得一提的是,您可以使用
    函数。原型。调用
    而不是
    。应用
    。很好,这是一个有用的模式,我很惊讶我没有看到更多。Andrew的答案更确切地回答了我的问题,但我想我更喜欢这个解决方案。非常感谢你把事情弄清楚!第三个论点太少使用了,老实说,我之前甚至没有想到——回答得很好。这是一个非常有用的贡献,谢谢!我将d3与Vue结合使用,处理“this”可能会有点棘手,箭头函数和
    非常有用。我一直在使用箭头功能,但无法使其工作。我也在使用D3V6,因此回调中的参数是
    事件
    数据
    ,而不是
    数据
    索引
    ,以及
    元素
    。因此,将我的箭头函数代码更改为
    d3.select(event.target)
    效果很好。