Search code examples
javascriptamcharts

Amcharts 4: How to combine tooltips of LineSeries


I have a chart containing 3 LineSeries. Sometimes, the lines cross each other. At these points only the single tooltip of the last added series is displayed.

enter image description here

How can I combine those tooltips into one single single tooltip that contains the information on all three series, in case the points are at the same position?

I build the chart using LineSeries and place CircleBullets on them:

/* Create series */
var series1 = chart.series.push(new am4charts.LineSeries());
series1.dataFields.valueY = "cars";
series1.dataFields.categoryX = "year";
series1.name = "Cars";
series1.strokeWidth = 3;
series1.tensionX = 0.7;
bullet1 = series1.bullets.push(new am4charts.CircleBullet());
bullet1.tooltipText = `[bold]YEAR {categoryX}[/]
----
cars: {cars}`;

var series2 = chart.series.push(new am4charts.LineSeries());
series2.dataFields.valueY = "motorcycles";
series2.dataFields.categoryX = "year";
series2.name = "Motorcycles";
series2.strokeWidth = 3;
series2.tensionX = 0.7;
bullet2 = series2.bullets.push(new am4charts.CircleBullet());
bullet2.tooltipText = `[bold]YEAR {categoryX}[/]
----
motorcycles: {motorcycles}`;

var series3 = chart.series.push(new am4charts.LineSeries());
series3.dataFields.valueY = "bicycles";
series3.dataFields.categoryX = "year";
series3.name = "Bicycles";
series3.strokeWidth = 3;
series3.tensionX = 0.7;
bullet3 = series3.bullets.push(new am4charts.CircleBullet());
bullet3.tooltipText = `[bold]YEAR {categoryX}[/]
----
Bicycles: {bicycles}`;

full example: https://codepen.io/anon/pen/ommRPp


Solution

  • So like Albondi was saying, what you can start with is the chart cursor so we can have all the tooltips trigger all the time:

    chart.cursor = new am4charts.XYCursor();
    

    From there, if you want to filter which tooltips get shown and what gets shown in the remaining tooltip, I suggest setting an adapter on each bullet's tooltipText. What triggers a tooltip to begin with is if the object has a non-empty tooltipText property. So for the tooltips we want to hide, with an adapter we can just return "" to hide them at will.

    To determine if we're hovering over multiple bullets, in this case we can just check if they have the same exact value, we know the value keys are cars, motorcycles, and bicycles, so if they're exactly the same on hover, suppress two of the tooltips, and modify the text of the other to show data for all three. The second parameter of the adapter will be the object we're hovering over, its dataItem.dataContext will have references to the data/values we're looking to compare.

    bullet1.adapter.add("tooltipText", blankTooltipTextOnSameValues);
    bullet2.adapter.add("tooltipText", blankTooltipTextOnSameValues);
    bullet3.adapter.add("tooltipText", function(text, target) {
      var data = target.dataItem.dataContext;
      if (data.bicycles === data.motorcycles && data.bicycles === data.cars) {
        return `[bold]YEAR {categoryX}[/]
    ----
    Cars: {cars}
    Motorcycles: {motorcycles}
    Bicycles: {bicycles}`;
      }
      return text;
    });
    
    function blankTooltipTextOnSameValues(text, target) {
      var data = target.dataItem.dataContext;
      if (data.bicycles === data.motorcycles && data.bicycles === data.cars) {
        return "";
      }
      return text;
    }
    

    Here's a fork of your code sample with the above changes:

    https://codepen.io/team/amcharts/pen/a9c1d3eff9170c04f18e134bd6940daa

    You can omit the Chart Cursor if you want, then you'd have to hover over the bullets individually for the tooltip to show. Since series3 is the latest addition to the chart, it will have a higher stacking order and will cover the other bullets at the same point, so the adapter above will achieve the same effect with/without the Chart Cursor.