d3.js 为元素添加on()监听事件,报错 .on() is not a function

新手上路,请多包涵

问题描述

在用d3.js做一个柱状图的demo的时候,希望为柱状图添加鼠标交互事件监听。直接监听事件用链式调用的形式添加在元素的生长动画后面,报出错误:

clipboard.png

代码如下:

var rects = svg.selectAll(".MyRect")
    .data(dataset)
    .enter()
    .append("rect")
    .attr("class", ".MyRect")
    .attr("transform", "translate(" + padding.left + "," + padding.top + ")")
    .attr("x", function (d, i) {
        return xScale(i) + rectPadding / 2
    })
    .attr("y", function (d) {
        return yScale(d);
    })
    .attr("width", xScale.rangeBand() - rectPadding)

    .attr("fill", "steelblue")
    // 监听事件要放在y的生长动画之前



    .attr("y", function (d) {
        var min = yScale.domain()[0];
        return yScale(min)
    })
    .attr("height", function (d) { return 0 })
    .transition()
    .delay(function (d, i) {
        return i * 200
    })
    .duration(2000)
    .ease("bounce")
    .attr("y", function (d) {
        return yScale(d)
    })
    .attr("height", function (d) {
        return height - padding.top - padding.bottom - yScale(d);
    })
    //直接将事件监听放在了生长动画之后
    .on("mouseover",function(d,i){
        d3.select(this)
            .attr("fill","yellow");
    })
    .on("mouseout",function(d,i){
        d3.select(this)
        .attr("fill","steelblue")
    })

但是如果放在生长动画之前,这样就没有问题,就事件监听函数就可以正常工作:

var rects = svg.selectAll(".MyRect")
  .data(dataset)
  .enter()
  .append("rect")
  .attr("class", ".MyRect")
  .attr("transform", "translate(" + padding.left + "," + padding.top + ")")
  .attr("x", function (d, i) {
      return xScale(i) + rectPadding / 2
  })
  .attr("y", function (d) {
      return yScale(d);
  })
  .attr("width", xScale.rangeBand() - rectPadding)

  .attr("fill", "steelblue")
  
  // 监听事件
  .on("mouseover",function(d,i){
      d3.select(this)
          .attr("fill","yellow");
  })
  .on("mouseout",function(d,i){
      d3.select(this)
      .attr("fill","steelblue")
  })

  //bar chart生长动画
  .attr("y", function (d) {
      var min = yScale.domain()[0];
      return yScale(min)
  })
  .attr("height", function (d) { return 0 })
  .transition()
  .delay(function (d, i) {
      return i * 200
  })
  .duration(2000)
  .ease("bounce")
  .attr("y", function (d) {
      return yScale(d)
  })
  .attr("height", function (d) {
      return height - padding.top - padding.bottom - yScale(d);
  })

困惑所在

不太明白为什么监听事件放在生长函数之前就可以正常工作了,这背后的机制是怎么一回事?希望有大神指点一二。

阅读 5.3k
1 个回答

因为duration之后返还的对象不在是一开始的d3查找的元素了吧,而是个动画对象,不再支持链式调用

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题