Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm busy plotting a bar chart using D3 in Angular4.

// 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();

In my plotting method, when I call animate() I get an error: Error: unknown type: mouseover. Which makes sense, since I'm probably trying to call the on("<event>") on a the transition returned by D3, the transition effect is there, however, everything after the transition breaks, i.e: The animation works, but the plotting is broken ofc.

However when I attempt to do the following:

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

No errors occur, but nothing happens, there is no transition effect to the new data set.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
369 views
Welcome To Ask or Share your Answers For Others

1 Answer

The problem here is a confusion between two different methods that use the same name:

Since you have a transition selection, when you write...

.on(...

The method expects to see three things (or typenames):

  • "start"
  • "end"
  • "interrupt"

However, "mouseover", "mouseout" or "click" are none of them. And then you get your error...

> Uncaught Error: unknown type: mouseover

Solution:

Bind the event listeners to a regular selection. Then, after that, create your transition selection.

Therefore, in your case, bind all the on listeners to the "enter" selection (which, by the way, makes more sense), removing them from the update selection.

Have a look at this little demo. First, I create a regular, enter selection, to which I add the event listener:

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

Then, I add the transition:

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

Hover over the bars to see the "mouseover" working:

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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...