【问题标题】:Select and Style Objects via Data id通过数据 ID 选择对象并设置样式
【发布时间】:2017-01-10 08:21:02
【问题描述】:

我正在尝试在圆半径变大的情况下进行鼠标悬停事件,并且相应的数据标签会增加字体大小。数据标签位于图表本身的圆圈上。所以我的想法是有两个函数,一个是通过过渡设置圆的漂亮和平滑的样式,并使用一个单独的函数和补间来设置文本的样式。 我想同时调用这两个函数,并且只让它们的样式对象具有与其“id”匹配的数据绑定。id 只是我从 .tsv 解析的索引。这个想法是文本和圆圈都有相同的“id”。

!boring circle svg code above
.on('mouseenter', function(d) {circle_event(this); text_event(this);})

function circle_event(id) {
    if (d3.select(this).data==id) {
        d3.select(this)
        .transition()
        .attr('r', radius*1.5)
        .duration(500);
    }
}

function text_event(id) {
    if (d3.select(this).data==id) {
        d3.select(this)
        .transition()
        .styleTween('font', function() {return d3.interpolate('12px Calibri', '20px Calibri' )
        .duration(500);
    }
}

由于某种原因,当我将鼠标悬停在圆圈上时,什么也没有发生。开发工具没有任何错误。如果我不得不猜测,我误解了如何使用 d3 的 select 函数。

谢谢

编辑

请注意,我需要同时调用圆形和文本样式函数我将接受显示如何设置圆形样式及其相应 data_label 文本的答案只需将鼠标悬停在 CIRCLE 上。似乎this 不能同时用作圆形和文本对象。欢迎使用基于this 的其他解决方案。

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    看起来你编辑了你的问题,这大大改变了事情。以下是一种可行的方法,或者可以对其进行修改以使其发挥作用:

    // Assumes circle & text objects have the same .x, .y and .id data bound to them and that 
    // when created, they each have classes "circle-class" and "text-class" respectively
    
    !boring circle svg code above
    .on('mouseenter', function(d) {circle_event(d.x, d.y, d.id); text_event(d.x, d.y, d.id);})
    
    function circle_event(x, y, id) {
        d3.selectAll(".circle-class")
        .filter(function (d) {
          return (d.x === x) && (d.y == y) && (d.id == id);
        })
          .transition()
          .attr('r', radius * 1.5)
          .duration(500);
    }
    
    function text_event(x, y, id) {
      d3.selectAll(".text-class")
        .filter(function (d) {
          return (d.x === x) && (d.y == y) && (d.id == id);
        })
          .transition()
          .styleTween('font', function() {return d3.interpolate('12px Calibri', '20px Calibri' )
          .duration(500);
    }
    

    或者,如果您将圆和文本 DOM 元素的创建构造成具有兄弟关系,您可以使用 d3.select(this.previousElementSibling) 获取对文本选择的引用,其中 this 是被鼠标移动的圆节点结束(见这里 - How to access "previous sibling" of `this` when iterating over a selection?)。这样的做法可以使用我上面回复中的代码。

    【讨论】:

    • 其实它仍然是完全相同的问题。在最初的帖子中,我说我不知道​​如何同时为两个对象设置样式。不过,这只是一句话,大多数人可能都忽略了它——因此造成了混乱。那是我的错,我对帖子的编辑是为了让关键问题更清楚。
    • 我也尝试了你的解决方案,一旦我将.attr('class',...) 更改为匹配,它就可以完美运行。我实际上只需要通过d.id 就可以了。也非常感谢您的精彩解释。
    • 很高兴它成功了。我最初是在凌晨 4 点回答的,所以我很可能误读/误解了你原来的问题!干杯。
    【解决方案2】:

    您的主要问题是 this 不是您想要的嵌套函数。它不再绑定到悬停在您的圆形 DOM 节点上,而是引用全局 window

    更多关于 this 作用域的信息可以在这里找到:

    Javascript "this" pointer within nested function

    http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/

    尝试改成这样:

    !boring circle svg code above
    .on('mouseenter', function(d) {circle_event(this, d.id)})
    
    function circle_event(selection, id) {
        if (d3.select(selection).data==id) {
            d3.select(selection)
            .transition()
            .attr('r', radius*1.5)
            .duration(500);
        }
    }
    
    function text_event(selection, id) {
        if (d3.select(selection).data==id) {
            d3.select(selection)
            .transition()
            .styleTween('font', function() {return d3.interpolate('12px Calibri', '20px Calibri' )
            .duration(500);
        }
    }
    

    【讨论】:

    • 你不需要d.id 因为this 已经是选中的圈子
    • @Tim B - 虽然这是真的,但在方便时传递它似乎更简单,而不是依赖函数中的 d3.select(this).datum().id 之类的东西。
    【解决方案3】:

    你应该在函数中传递this

    .on('mouseenter', function(d) {circle_event(this)})
    
    function circle_event(item) {
            d3.select(item)
            .transition()
            .attr('r', radius*1.5)
            .duration(500);
    }
    
    function text_event(item) {
            d3.select(item)
            .transition()
            .styleTween('font', function() {return d3.interpolate('12px Calibri', '20px Calibri' )
            .duration(500);
    }
    

    您不需要d.id,因为this 已经是选定的圈子

    【讨论】:

    • 所以我不需要任何 if 语句,因为 this 已经识别出哪个项目。这很有趣。
    • 当我尝试同时调用两个函数时,我的悬停事件-.on('mouseenter', function(d) {circle_event(this); text_event(this);}) 停止工作,我该怎么办?我认为添加分号可以让你调用多个函数。错误抛出 d3.js 未定义的计算样式。
    • this是一个圆圈,你不能在上面使用.styleTween('font', ...)
    • 我想这是有道理的,我应该在我的问题中说得更清楚。我实际上是在尝试用一个鼠标事件同时为圆圈和圆圈的标签设置样式,这就是我最初尝试使用 d.id 技术的原因,因为这是文本和圆圈的共同点。有没有办法在不同的对象类中使用this?如果不是,如果不是太麻烦,您能否以其他方式调整您的答案,使其对多个对象类具有鲁棒性?
    • 我很乐意接受您的回答,一旦我们解决了这个问题。我将承担责任,因为没有使重要信息足够清楚。为了清楚起见,我在帖子中添加了一些粗体和大写字母。感谢您一直以来的耐心和提示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 2016-05-01
    • 1970-01-01
    • 2021-04-07
    • 2016-05-10
    相关资源
    最近更新 更多