D3.js adds on () listening events to the element with an error. On () is not a function

problem description

when using d3.js to do a bar chart demo, you want to add mouse interactive event listening to the bar chart. The direct listening event is added to the growth animation of the element in the form of a chain call to report an error:

clipboard.png

the code is as follows:

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")
    })

but if you put it before the growth animation, there will be no problem, and the event listener function will work properly:

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);
  })

the confusion lies

I don"t quite understand why listening events work before the growth function. What"s the mechanism behind this? I hope one or two will be instructed by a great god.

Oct.12,2021

because the object returned after duration is no longer the element found in D3 at the beginning, but an animated object. Chained calls are no longer supported.

Menu