leeoniya / uPlot

📈 A small, fast chart for time series, lines, areas, ohlc & bars
MIT License
8.51k stars 371 forks source link

a question with hooks setSeries? #866

Open dingjunweibjkanyun opened 9 months ago

dingjunweibjkanyun commented 9 months ago
image

Is there any way? When the mouse position is at a spacing position, such as the position marked in the screenshot, setSeries hook can return the closest seriesIdx instead of null

leeoniya commented 8 months ago

is this using the grouped bars plugin with the quadtree?

dingjunweibjkanyun commented 8 months ago

is this using the grouped bars plugin with the quadtree?

yes

dingjunweibjkanyun commented 8 months ago

is this using the grouped bars plugin with the quadtree?

https://leeoniya.github.io/uPlot/demos/bars-grouped-stacked.html

leeoniya commented 8 months ago

the quadtree can only find overlapping rectangles. right now the demo asks for all rectangles that overlap a 1x1 px rect at the cursor position:

https://github.com/leeoniya/uPlot/blob/e8a1e8d6b70ca72f6e70d1f14894bc4a98cb47f2/demos/grouped-bars.js#L165-L168

you can modify this logic to make the cursor query rect 20x20 px (or dimensions that adjust to data density or bar width) and then do some simple comparison math on the resulting rects to find which one is nearest and set the hRect to that.

dingjunweibjkanyun commented 8 months ago

the quadtree can only find overlapping rectangles. right now the demo asks for all rectangles that overlap a 1x1 px rect at the cursor position:

https://github.com/leeoniya/uPlot/blob/e8a1e8d6b70ca72f6e70d1f14894bc4a98cb47f2/demos/grouped-bars.js#L165-L168

you can modify this logic to make the cursor query rect 20x20 px (or dimensions that adjust to data density or bar width) and then do some simple comparison math on the resulting rects to find which one is nearest and set the hRect to that.

The logic here is too complex,I need some time to understand here

dingjunweibjkanyun commented 8 months ago

the quadtree can only find overlapping rectangles. right now the demo asks for all rectangles that overlap a 1x1 px rect at the cursor position:

https://github.com/leeoniya/uPlot/blob/e8a1e8d6b70ca72f6e70d1f14894bc4a98cb47f2/demos/grouped-bars.js#L165-L168

you can modify this logic to make the cursor query rect 20x20 px (or dimensions that adjust to data density or bar width) and then do some simple comparison math on the resulting rects to find which one is nearest and set the hRect to that.

can you give me a specific examples?I don't know how to modify it

dingjunweibjkanyun commented 8 months ago

[uPlot/demos/grouped-bars.js] https://github.com/leeoniya/uPlot/blob/e8a1e8d6b70ca72f6e70d1f14894bc4a98cb47f2/demos/grouped-bars.js#L69-L74

I didn't understand your plan. I solved this problem by modifying the rectangular dimensions of the first and last series. Is this a reasonable solution?

 each: (u, seriesIdx, dataIdx, left, top, width, height) => {
      // we get back raw canvas coords (included axes & padding). translate to the plotting area origin
      left -= u.bbox.left;
      top -= u.bbox.top;
      const dataLen = u.data[0].length;
      const gapPer = (1 - groupWidth) / (dataLen - 1);
      const gapPx = (u.bbox.width / 2) * gapPer;

      const o = {
        x: left,
        y: top,
        w: width,
        h: height,
        sidx: seriesIdx,
        didx: dataIdx,
      };
      const firstSeriesShowIdx = u.series.findIndex(
        (s, index) => index > 0 && s.show
      );
      const lastSeriesShowIdx = u.series.findLastIndex(
        (s, index) => index > 0 && s.show
      );

      if (seriesIdx === lastSeriesShowIdx) {
        o.w += gapPx;
      }

      if (seriesIdx === firstSeriesShowIdx) {
        o.x -= gapPx;
        o.w += gapPx;
      }

      qt?.add(o);