|
6 | 6 | const _TooltipContext = new Context<TooltipContextValue>('TooltipContext'); |
7 | 7 |
|
8 | 8 | type TooltipMode = |
9 | | - | 'bisect-x' |
10 | | - | 'bisect-y' |
| 9 | + | 'bisect-x' // requires values to be sorted |
| 10 | + | 'bisect-y' // requires values to be sorted |
11 | 11 | | 'band' |
12 | | - | 'bisect-band' |
| 12 | + | 'bisect-band' // requires values to be sorted |
13 | 13 | | 'bounds' |
14 | 14 | | 'voronoi' |
15 | 15 | | 'quadtree' |
| 16 | + | 'quadtree-x' // ignores y values (constant 0) |
| 17 | + | 'quadtree-y' // ignores x values (constant 0) |
16 | 18 | | 'manual'; |
17 | 19 |
|
18 | 20 | export type TooltipContextValue<T = any> = { |
|
298 | 300 | } |
299 | 301 |
|
300 | 302 | // If tooltipData not provided already (voronoi, etc), attempt to find it |
301 | | - // TODO: When using bisect-x/y/band, values should be sorted. Typically they are for `x`, but not `y` (and band depends on if x or y scale) |
302 | 303 | if (tooltipData == null) { |
303 | 304 | switch (mode) { |
304 | 305 | case 'bisect-x': { |
|
311 | 312 | xValueAtPoint = scaleInvert(ctx.xScale, point.x - ctx.padding.left); |
312 | 313 | } |
313 | 314 |
|
| 315 | + // Requires values to be sorted |
314 | 316 | const index = bisectX(ctx.flatData, xValueAtPoint, 1); |
315 | 317 | const previousValue = ctx.flatData[index - 1]; |
316 | 318 | const currentValue = ctx.flatData[index]; |
|
322 | 324 | // `y` value at pointer coordinate |
323 | 325 | const yValueAtPoint = scaleInvert(ctx.yScale, point.y - ctx.padding.top); |
324 | 326 |
|
| 327 | + // Requires values to be sorted |
325 | 328 | const index = bisectY(ctx.flatData, yValueAtPoint, 1); |
326 | 329 | const previousValue = ctx.flatData[index - 1]; |
327 | 330 | const currentValue = ctx.flatData[index]; |
|
339 | 342 | const bandData = ctx.flatData |
340 | 343 | .filter((d) => ctx.x(d) === xValueAtPoint) |
341 | 344 | .sort(sortFunc(ctx.y as () => any)); // sort for bisect |
| 345 | + // Requires values to be sorted |
342 | 346 | const index = bisectY(bandData, yValueAtPoint, 1); |
343 | 347 | const previousValue = bandData[index - 1]; |
344 | 348 | const currentValue = bandData[index]; |
|
348 | 352 | const bandData = ctx.flatData |
349 | 353 | .filter((d) => ctx.y(d) === yValueAtPoint) |
350 | 354 | .sort(sortFunc(ctx.x as () => any)); // sort for bisect |
| 355 | + // Requires values to be sorted |
351 | 356 | const index = bisectX(bandData, xValueAtPoint, 1); |
352 | 357 | const previousValue = bandData[index - 1]; |
353 | 358 | const currentValue = bandData[index]; |
|
358 | 363 | break; |
359 | 364 | } |
360 | 365 |
|
| 366 | + case 'quadtree-x': |
| 367 | + case 'quadtree-y': |
361 | 368 | case 'quadtree': { |
362 | 369 | tooltipData = quadtree?.find( |
363 | 370 | point.x - ctx.padding.left, |
|
406 | 413 | } |
407 | 414 |
|
408 | 415 | const quadtree: Quadtree<[number, number]> | undefined = $derived.by(() => { |
409 | | - if (mode === 'quadtree') { |
| 416 | + if (['quadtree', 'quadtree-x', 'quadtree-y'].includes(mode)) { |
410 | 417 | return d3Quadtree() |
411 | 418 | .x((d) => { |
| 419 | + if (mode === 'quadtree-y') { |
| 420 | + return 0; |
| 421 | + } |
| 422 | +
|
412 | 423 | if (geoCtx.projection) { |
413 | 424 | const lat = ctx.x(d); |
414 | 425 | const long = ctx.y(d); |
|
429 | 440 | } |
430 | 441 | }) |
431 | 442 | .y((d) => { |
| 443 | + if (mode === 'quadtree-x') { |
| 444 | + return 0; |
| 445 | + } |
| 446 | +
|
432 | 447 | if (geoCtx.projection) { |
433 | 448 | const lat = ctx.x(d); |
434 | 449 | const long = ctx.y(d); |
|
509 | 524 | }); |
510 | 525 |
|
511 | 526 | const triggerPointerEvents = $derived( |
512 | | - ['bisect-x', 'bisect-y', 'bisect-band', 'quadtree'].includes(mode) |
| 527 | + ['bisect-x', 'bisect-y', 'bisect-band', 'quadtree', 'quadtree-x', 'quadtree-y'].includes(mode) |
513 | 528 | ); |
514 | 529 |
|
515 | 530 | function onPointerEnter(e: PointerEvent | MouseEvent | TouchEvent) { |
|
646 | 661 | {/each} |
647 | 662 | </g> |
648 | 663 | </Svg> |
649 | | - {:else if mode === 'quadtree' && debug} |
| 664 | + {:else if ['quadtree', 'quadtree-x', 'quadtree-y'].includes(mode) && debug} |
650 | 665 | <Svg pointerEvents={false}> |
651 | 666 | <ChartClipPath> |
652 | 667 | <g class={layerClass('tooltip-quadtree-g')}> |
|
0 commit comments