sgratzl/chartjs-chart-geo

Tooltip for multiple datasets doesn't work after page refresh

atadeuccislideworks opened this issue · 3 comments

When using multiple datasets, the tooltip after a page refresh will only show the information of the first dataset.

To Reproduce

Codesandbox: https://codesandbox.io/s/react-chartjs-2-map-forked-6hyh0g?file=/src/geo-map.tsx

  1. Go to the codesandbox above and the tooltip will only show for the first dataset.
    image

  2. Change the name of any dataset and after it hot-reloads, the tooltips for both datasets should show as expected
    image

  3. Refresh the codesandbox, now the tooltip will only show for the first dataset.
    image

Expected behavior

Tooltip should show for all datasets, even after page refresh.

An example of it working but in Angular
https://codesandbox.io/s/angular-brazil-map-forked-ue0h05?file=/src/app/app.component.ts

  • Version: 3.9.0
  • Browser: All

this plugin doesn't control how the tooltips are computed. That is chart.js. Not sure how it computes everything for two charts on top of each other.

This plugin only provides the required methods such that the tooltip position can be computed:

inRange(mouseX: number, mouseY: number): boolean {
const bb = this.getBounds();
const r =
(Number.isNaN(mouseX) || (mouseX >= bb.x && mouseX <= bb.x2)) &&
(Number.isNaN(mouseY) || (mouseY >= bb.y && mouseY <= bb.y2));
const projection = this.projectionScale.geoPath.projection() as unknown as GeoProjection;
if (r && !Number.isNaN(mouseX) && !Number.isNaN(mouseY) && typeof projection.invert === 'function') {
// test for real if within the bounds
const longLat = projection.invert([mouseX, mouseY]);
return longLat != null && geoContains(this.feature, longLat);
}
return r;
}
inXRange(mouseX: number): boolean {
return this.inRange(mouseX, Number.NaN);
}
inYRange(mouseY: number): boolean {
return this.inRange(Number.NaN, mouseY);
}
getCenterPoint(): { x: number; y: number } {
if (this.cache && this.cache.center) {
return this.cache.center;
}
let center: { x: number; y: number };
if (this.center) {
const p = this.projectionScale.projection([this.center.longitude, this.center.latitude])!;
center = {
x: p[0]!,
y: p[1]!,
};
} else {
const centroid = this.projectionScale.geoPath.centroid(this.feature);
center = {
x: centroid[0],
y: centroid[1],
};
}
this.cache = { ...(this.cache || {}), center };
return center;
}

Thanks for the reply!

Damn I guess then the issue is with chartjs-react since I got it working with vanilla js.

For anyone who might come into the same issue, my solution was to hack it a little.

I used only one dataset, and added the raw information for that state inside the data object

data: data.map((d: any) => ({
  feature: d,
  value: 60,
  raw: [50, 10],
}))

Then I eddited the tooltip to get that information

plugins: {
  tooltip: {
    callbacks: {
      label: (context: any) => {
        return [
                  context.element.feature.properties.name,
                  `Total ${context.formattedValue}`,
                  `Dataset 1 ${context.raw.raw[0]}`,
                  `Dataset 2 ${context.raw.raw[1]}`
          ];
      },
    },
  },
},

Codesandbox with example 'fix':
https://codesandbox.io/s/react-chartjs-2-map-fix-multiple-datasets-ek5hwc?file=/src/geo-map.tsx:1561-1805