D3:.transition() 不适用于事件

Posted

技术标签:

【中文标题】D3:.transition() 不适用于事件【英文标题】:D3: .transition() not working with events 【发布时间】:2017-11-13 16:46:20 【问题描述】:

我正忙着在 Angular4 中使用 D3 绘制条形图。

// Enter Phase
this.chart.selectAll('.bar')
  .data(this.barData)
  .enter()
  .append('rect')
  .attr('class', 'bar');

// Update Phase
let bars = this.chart.selectAll('.bar').transition()
  .attr('x', (d) => return this.x(this.parseTime(d.date.toUpperCase()));)
  .attr('y', (d) => return this.y(d.point))
  .attr('width', 15)
  .attr('height', (d) => return this.charDimensions.height - this.y(d.point);)
    .on("mouseover", function (d) D3.select(this).style('opacity', 0.5);)
    .on("mouseout", function (d) D3.select(this).style('opacity', 1);)
    .on("click", (d) => this.barClicked.emit(d););

// Exit phase
this.chart.selectAll('.bar')
  .data(this.barData)
  .exit().remove();

在我的绘图方法中,当我调用 animate() 时出现错误:Error: unknown type: mouseover。这是有道理的,因为我可能试图在 D3 返回的转换上调用on("<event>"),所以转换效果就在那里,但是,转换中断后的所有内容,即:动画有效,但绘图被破坏了.

但是当我尝试执行以下操作时:

// Update Phase
let bars = this.chart.selectAll('.bar');
bars.transition();
bars.attr('x', (d) => return this.x(this.parseTime(d.date.toUpperCase()));)
  .attr('y', (d) => return this.y(d.point))
  .attr('width', 15)
  .attr('height', (d) => return this.charDimensions.height - this.y(d.point);)
    .on("mouseover", function (d) D3.select(this).style('opacity', 0.5);)
    .on("mouseout", function (d) D3.select(this).style('opacity', 1);)
    .on("click", (d) => this.barClicked.emit(d););

没有发生错误,但什么也没发生,没有到新数据集的过渡效果。

【问题讨论】:

增加持续时间有帮助吗? let bars = this.chart.selectAll('.bar').transition().duration(3000).attr(.... 试过了,没有运气@wazz @wazz 你不需要设置持续时间:如果没有,D3 会创建一个默认的 250 毫秒持续时间。 【参考方案1】:

这里的问题是两个使用相同名称的不同方法之间的混淆:

selection.on(typenames[, listener]) transition.on(typenames[, listener])

既然你有一个过渡选择,当你写...

.on(...

该方法期望看到三个东西(或类型名):

“开始” “结束” “中断”

但是,“mouseover”、“mouseout”或“click”都不是。然后你得到你的错误......

> Uncaught Error: unknown type: mouseover

解决方案

将事件侦听器绑定到常规选择。然后,在此之后,创建您的过渡选择。

因此,在您的情况下,将所有 on 侦听器绑定到“输入”选择(顺便说一句,这更有意义),将它们从更新选择中删除。

看看这个小演示。首先,我创建一个常规的输入选择,并在其中添加事件侦听器:

var bars = svg.selectAll(null)
    .data(data)
    .enter()
    .append("rect")
    //some attr here
    .on("mouseover", function(d) 
        console.log(d)
    );

然后,我添加过渡:

bars.transition()
    .duration(1000)
    etc...

将鼠标悬停在栏上以查看“鼠标悬停”的工作情况:

var svg = d3.select("svg");
var data = [30, 280, 40, 140, 210, 110];
var bars = svg.selectAll(null)
  .data(data)
  .enter()
  .append("rect")
  .attr("x", 0)
  .attr("width", 0)
  .attr("y", function(d, i) 
    return i * 20
  )
  .attr("height", 18)
  .attr("fill", "teal")
  .on("mouseover", function(d) 
    console.log(d)
  );

bars.transition()
  .duration(1000)
  .attr("width", function(d) 
    return d
  )
.as-console-wrapper  max-height: 25% !important;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>

【讨论】:

以上是关于D3:.transition() 不适用于事件的主要内容,如果未能解决你的问题,请参考以下文章

map.get() 方法不适用于 D3 v6

d3剪辑路径不适用于填充折线图

Vue:使用 scoped 时 CSS 不适用于 D3 的 svg

d3交互

d3交互

v-leave-active 动画工作,但 v-enter-active 动画不适用于 <transition-group>