Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shared tooltips do not work with Irregular Timeseries #420

Open
jhuckaby opened this issue Mar 21, 2019 · 20 comments
Open

Shared tooltips do not work with Irregular Timeseries #420

jhuckaby opened this issue Mar 21, 2019 · 20 comments
Labels
bug Something isn't working tooltip

Comments

@jhuckaby
Copy link

First of all, thank you for an awesome chart library. I absolutely love ApexCharts!

Codepen

This issue is actually illustrated perfectly on your Irregular Timeseries demo page, so no codepen is required:

https://apexcharts.com/javascript-chart-demos/area-charts/irregular-timeseries/

This demo has the following configuration for the tooltip:

tooltip: {
	shared: true
},

However, as you can see in the demo, the tooltips are not showing as shared, even if you hover over a point intersecting multiple series. Instead, it only shows a single series in the tooltip.
Screenshot:

Screenshot 2019-03-20 17 27 25

Explanation

What is the behavior you expect?

I expect that when tooltip.shared is set to true, that all intersecting series will show in the tooltip hover. This is indeed the case when all series start at the same timestamp (i.e. a "regular" timeseries).

What is happening instead?

The tooltip hover is only showing one single series (the nearest one), even though multiple series intersect the X position of the mouse.

What error message are you getting?

There is no error message. This is just a visual issue.

I've noticed that when all my series data starts at the same timestamp (i.e. regular, not irregular) the shared tooltip works just fine. This issue only occurs when one or more of the series starts at a different timestamp, as shown in your Irregular Timeseries demo.

@jhuckaby
Copy link
Author

Here is codepen created from your Irregular Timeseries demo code, but I adjusted all three series to start at the same timestamp, and have the same array length:

https://codepen.io/anon/pen/EMdpmN

As you can see, the shared tooltip works just fine in this case.

@junedchhipa
Copy link
Contributor

By default, a shared tooltip is turned off in an irregular time-series.
Until now, I haven't found a solution that would work elegantly in this case, hence I turned it off programmatically.

I will visit that part of code once again to see how it goes, thanks!

@junedchhipa junedchhipa added the feature-request New feature or request label Mar 23, 2019
@petericebear
Copy link

Any updates on this? We have a similar issue in our graphs with 'missing' keys, but the days at the x-axes are equal.

@junedchhipa
Copy link
Contributor

If the days at the x-axes are equal, you should create series with null values so that all series length stays equal.

series: [
  {
    data: [
      {
        x: new Date('17 Jul').getTime(),
        y: 20
      },
      {
        x: new Date('18 Jul').getTime(),
        y: 30
      },
      {
        x: new Date('19 Jul').getTime(),
        y: null
      }
    ]
  },
  {
    data: [
      {
        x: new Date('17 Jul').getTime(),
        y: null
      },
      {
        x: new Date('18 Jul').getTime(),
        y: 23
      },
      {
        x: new Date('19 Jul').getTime(),
        y: 98
      }
    ]
  }
],

@onli
Copy link

onli commented Jan 20, 2020

Wouldn't it maybe be possible to optionally show the y value at the line position, instead of the datapoint?

For context, in my example I only have data point when values are about to change or just changed. So the correct behaviour for a shared tooltip in those cases of an irregular timeseries would be to either show the y value of all series lines at the date, or to show the y value of the closest data point of each series.

@niklashaug
Copy link

@junedchhipa can we expect an official fix for this sometime?

@betaanish
Copy link

i am stuck with this from past few days.....any update on this

@betaanish
Copy link

@junedchhipa ....please suggest any workaround

@matthew-williamson-sd
Copy link

@betaanish He's already suggested a workaround, just add the missing dates with null values

@alfonsrv
Copy link

alfonsrv commented Nov 2, 2020

The suggested fix doesn't work.

Chart

$(document).ready(function() {
    primary = [{
        x: "2020-01-05",
        y: null
    }, {
        x: "2020-10-01",
        y: 30
    }, {
        x: "2019-11-01",
        y: 15
    }, {
        x: "2020-11-02",
        y: 30
    }, ]
    secondary = [{
        x: "2020-01-05",
        y: 15
    }, {
        x: "2020-10-01",
        y: null
    }, {
        x: "2019-11-01",
        y: null
    }, {
        x: "2020-11-02",
        y: 30
    }, ]
    
    var options = {
        series: [{
            name: 'Primary',
            data: primary
        }, {
            name: 'Secondary',
            data: secondary
        }],
        chart: {
            type: 'line',
            stacked: false,
            height: 350,
            zoom: {
                type: 'x',
                enabled: true,
                autoScaleYaxis: true
            },
            toolbar: {
                autoSelected: 'zoom'
            }
        },
        dataLabels: {
            enabled: true
        },
        markers: {
            size: 0,
        },
        title: {
            text: 'Sample Series',
            align: 'left'
        },
        yaxis: {
            labels: {
                formatter: function(val) {
                    return val;
                },
            },
            title: {
                text: 'Amount'
            },
        },
        xaxis: {
            type: 'datetime',
        },
        tooltip: {
            shared: true,
            y: {
                formatter: function(val) {
                    return val;
                }
            }
        }
    };
    var chart = new ApexCharts(document.querySelector("#chart"), options);
    chart.render();
});

@v360-eduardo-marques
Copy link

facing the same problem here.

any chances it'll be fixed anytime soon?

@Muqeet1
Copy link

Muqeet1 commented Apr 15, 2021

The same issue here, any fix so far?

@faizalami
Copy link

hey everyone, I think I got the solution, and perhaps this solution will works for any case

so the key is using the "w.globals" context, and I used this flow to generate a correct tooltip:

  1. store the hovered x-axis series value (in this case is date time in integer form)
  2. find and map the index of similar time from another x-axis series from w.globals.seriesX
  3. print series value based on all x-axis points found with similar time
  4. style the tooltip, you can format the hovered x-axis series value to readable date time format as tooltip title
custom: ({ series, seriesIndex, dataPointIndex, w }) => {
      const hoverXaxis = w.globals.seriesX[seriesIndex][dataPointIndex];
      const hoverIndexes = w.globals.seriesX.map(seriesX => {
        return seriesX.findIndex(xData => xData === hoverXaxis);
      });

      let hoverList = '';
      hoverIndexes.forEach((hoverIndex, seriesEachIndex) => {
        if (hoverIndex >= 0) {
          hoverList += `<span>${w.globals.seriesNames[seriesEachIndex]}: ${series[seriesEachIndex][hoverIndex]}</span><br />`;
        }
      });
      const formatHoverX = this.dateFormat(new Date(hoverXaxis), 'YYYY-MM-DD HH:mm:ss');

      return `<div class="card">
        <div class="card-header p-1">${formatHoverX}</div>
        <div class="card-body p-1">
          ${hoverList}
        </div>
      </div>`;
    },

@github-actions
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@Splinter0
Copy link

Splinter0 commented Feb 21, 2022

Hello everyone, follow up on the comment by @faizalami , this is my implementation to fix the issue. For context, I use the Vue wrapper.

        customSharedTooltip({ series, seriesIndex, dataPointIndex, w }) {
            const hoverXaxis = w.globals.seriesX[seriesIndex][dataPointIndex];
            const hoverIndexes = w.globals.seriesX.map((seriesX) => {
                return seriesX.findIndex((xData) => xData === hoverXaxis);
            });

            let hoverList = "";
            hoverIndexes.forEach((hoverIndex, seriesEachIndex) => {
                if (hoverIndex >= 0) {
                    hoverList += `
                        <div class="apexcharts-tooltip-series-group apexcharts-active" style="order: 1; display: flex;">
                            <span class="apexcharts-tooltip-marker" style="background-color: ${
                                w.globals.markers.colors[seriesEachIndex]
                            };"></span>
                            <div class="apexcharts-tooltip-text" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px;">
                                <div class="apexcharts-tooltip-y-group">
                                    <span class="apexcharts-tooltip-text-y-label">${
                                        w.globals.seriesNames[seriesEachIndex]
                                    }: </span>
                                    <span class="apexcharts-tooltip-text-y-value">${w.globals.yLabelFormatters[0](
                                        series[seriesEachIndex][hoverIndex]
                                    )}</span>
                                </div>
                            </div>
                        </div>`;
                }
            });
            const parsed = new Date(hoverXaxis)
                .toDateString()
                .split(" ")
                .slice(1);
            return `<div class="apexcharts-tooltip-title" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px;">${
                parsed[1] + " " + parsed[0] + " " + parsed[2]
            }</div>${hoverList}`;
        },

This is the method I defined, this way the rendering for the tooltip is identical to the default tooltip used by Apex.
I really think this issue should be addressed in upstream.

@junedchhipa junedchhipa reopened this Feb 21, 2022
@junedchhipa junedchhipa added bug Something isn't working and removed feature-request New feature or request no-issue-activity labels Feb 21, 2022
@dmitrypasyutin
Copy link

@Splinter0 thanks a lot!
by the way, there should be

w.globals.yLabelFormatters[seriesEachIndex]

instead of

w.globals.yLabelFormatters[0]

@placid2000
Copy link

Thank you @Splinter0 and @dmitrypasyutin . This solution temporary solves the problem.
What I'm missing though, are the markers on each line when hovering. I think this might be related to the same issue.

Example: I would expect to have a marker on the green line as well:
image

Is there a way to improve this ?

@raoulspronck
Copy link

Hello everyone, follow up on the comment by @faizalami , this is my implementation to fix the issue. For context, I use the Vue wrapper.

        customSharedTooltip({ series, seriesIndex, dataPointIndex, w }) {
            const hoverXaxis = w.globals.seriesX[seriesIndex][dataPointIndex];
            const hoverIndexes = w.globals.seriesX.map((seriesX) => {
                return seriesX.findIndex((xData) => xData === hoverXaxis);
            });

            let hoverList = "";
            hoverIndexes.forEach((hoverIndex, seriesEachIndex) => {
                if (hoverIndex >= 0) {
                    hoverList += `
                        <div class="apexcharts-tooltip-series-group apexcharts-active" style="order: 1; display: flex;">
                            <span class="apexcharts-tooltip-marker" style="background-color: ${
                                w.globals.markers.colors[seriesEachIndex]
                            };"></span>
                            <div class="apexcharts-tooltip-text" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px;">
                                <div class="apexcharts-tooltip-y-group">
                                    <span class="apexcharts-tooltip-text-y-label">${
                                        w.globals.seriesNames[seriesEachIndex]
                                    }: </span>
                                    <span class="apexcharts-tooltip-text-y-value">${w.globals.yLabelFormatters[0](
                                        series[seriesEachIndex][hoverIndex]
                                    )}</span>
                                </div>
                            </div>
                        </div>`;
                }
            });
            const parsed = new Date(hoverXaxis)
                .toDateString()
                .split(" ")
                .slice(1);
            return `<div class="apexcharts-tooltip-title" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px;">${
                parsed[1] + " " + parsed[0] + " " + parsed[2]
            }</div>${hoverList}`;
        },

This is the method I defined, this way the rendering for the tooltip is identical to the default tooltip used by Apex. I really think this issue should be addressed in upstream.

Does anyone have this solution for React apexcharts?

@stalniy
Copy link

stalniy commented Mar 26, 2024

the code above still may not work if corresponding XValue is not found in other series. This fixed code finds not only equal but the most close value on X axis to the one which was hovered. Obviously this works only with numbers (e.g., timestamps) on X axis. For me this is more than enough:

function customTooltip({ series, seriesIndex, dataPointIndex, w }) {
    const hoverXaxis = w.globals.seriesX[seriesIndex][dataPointIndex];
    const hoverIndexes = w.globals.seriesX.map((seriesX) => {
      let min = Math.abs(seriesX[0] - hoverXaxis);
      let minIndex = 0;
      for (let i = 1; i < seriesX.length; i++) {
        const v = Math.abs(seriesX[i] - hoverXaxis);
        if (v < min) { 
          min = v;
          minIndex = i;
        }
       }
      return minIndex
    });

    let hoverList = "";
    hoverIndexes.forEach((hoverIndex, seriesEachIndex) => {
        if (hoverIndex >= 0) {
            hoverList += `
                <div class="apexcharts-tooltip-series-group apexcharts-active" style="order: 1; display: flex;">
                    <span class="apexcharts-tooltip-marker" style="background-color: ${
                        w.globals.markers.colors[seriesEachIndex]
                    };"></span>
                    <div class="apexcharts-tooltip-text" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px;">
                        <div class="apexcharts-tooltip-y-group">
                            <span class="apexcharts-tooltip-text-y-label">${
                                w.globals.seriesNames[seriesEachIndex]
                            }: </span>
                            <span class="apexcharts-tooltip-text-y-value">${w.globals.yLabelFormatters[0](
                                series[seriesEachIndex][hoverIndex]
                            )}</span>
                        </div>
                    </div>
                </div>`;
        }
    });
    const parsed = new Date(hoverXaxis)
        .toDateString()
        .split(" ")
        .slice(1);
    return `<div class="apexcharts-tooltip-title" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px;">${
        parsed[1] + " " + parsed[0] + " " + parsed[2]
    }</div>${hoverList}`;
}

@sebgutierrez
Copy link

Hello everyone, follow up on the comment by @faizalami , this is my implementation to fix the issue. For context, I use the Vue wrapper.

        customSharedTooltip({ series, seriesIndex, dataPointIndex, w }) {
            const hoverXaxis = w.globals.seriesX[seriesIndex][dataPointIndex];
            const hoverIndexes = w.globals.seriesX.map((seriesX) => {
                return seriesX.findIndex((xData) => xData === hoverXaxis);
            });

            let hoverList = "";
            hoverIndexes.forEach((hoverIndex, seriesEachIndex) => {
                if (hoverIndex >= 0) {
                    hoverList += `
                        <div class="apexcharts-tooltip-series-group apexcharts-active" style="order: 1; display: flex;">
                            <span class="apexcharts-tooltip-marker" style="background-color: ${
                                w.globals.markers.colors[seriesEachIndex]
                            };"></span>
                            <div class="apexcharts-tooltip-text" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px;">
                                <div class="apexcharts-tooltip-y-group">
                                    <span class="apexcharts-tooltip-text-y-label">${
                                        w.globals.seriesNames[seriesEachIndex]
                                    }: </span>
                                    <span class="apexcharts-tooltip-text-y-value">${w.globals.yLabelFormatters[0](
                                        series[seriesEachIndex][hoverIndex]
                                    )}</span>
                                </div>
                            </div>
                        </div>`;
                }
            });
            const parsed = new Date(hoverXaxis)
                .toDateString()
                .split(" ")
                .slice(1);
            return `<div class="apexcharts-tooltip-title" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px;">${
                parsed[1] + " " + parsed[0] + " " + parsed[2]
            }</div>${hoverList}`;
        },

This is the method I defined, this way the rendering for the tooltip is identical to the default tooltip used by Apex. I really think this issue should be addressed in upstream.

This worked really well for me! I had to modify this line so only the active series appear. Otherwise the hidden series value will show undefined.

hoverIndexes.forEach((hoverIndex, seriesEachIndex) => {
    if (hoverIndex >= 0 && w.globals.collapsedSeriesIndices.includes(seriesEachIndex) === false) { ... } 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working tooltip
Projects
None yet
Development

No branches or pull requests