QuadTree.percent-range.html.svelte component
Creates an interaction layer (in HTML) using d3-quadtree to find the nearest datapoint to the mouse. This component creates a slot that exposes variables x
, y
, found
(the found datapoint), visible
(a Boolean whether any data was found) and e
(the event object). This component works with a percent range so the x
and y
values coming back will be percentages.
The quadtree searches across both the x and y dimensions at the same time. But if you want to only search across one, set the x
and y
props to the same value. For example, the shared tooltip component sets y='x'
since it's nicer behavior to only pick up on the nearest x-value.
Param | Default | Required | Description |
---|---|---|---|
x String |
'x' |
The dimension to search across when moving the mouse left and right. | |
y String |
'y' |
The dimension to search across when moving the mouse up and down. | |
searchRadius String |
None | The number of pixels to search around the mouse's location. This is the third argument passed to quadtree.find and by default a value of undefined means an unlimited range. |
|
dataset Array |
None | The dataset to work off of—defaults to $data if left unset. You can pass something custom in here in case you don't want to use the main data or it's in a strange format. |
<!--
@component
Creates an interaction layer (in HTML) using [d3-quadtree](https://github.com/d3/d3-quadtree) to find the nearest datapoint to the mouse. This component creates a slot that exposes variables `x`, `y`, `found` (the found datapoint), `visible` (a Boolean whether any data was found) and `e` (the event object). This component works with a percent range so the `x` and `y` values coming back will be percentages.
The quadtree searches across both the x and y dimensions at the same time. But if you want to only search across one, set the `x` and `y` props to the same value. For example, the [shared tooltip component](https://layercake.graphics/components/SharedTooltip.html.svelte) sets `y='x'` since it's nicer behavior to only pick up on the nearest x-value.
-->
<script>
import { getContext } from 'svelte';
import { quadtree } from 'd3-quadtree';
const { data, xGet, yGet, width, height } = getContext('LayerCake');
let visible = false;
let found = {};
let e = {};
/** @type {String} [x='x'] - The dimension to search across when moving the mouse left and right. */
export let x = 'x';
/** @type {String} [y='y'] - The dimension to search across when moving the mouse up and down. */
export let y = 'y';
/** @type {String} [searchRadius] - The number of pixels to search around the mouse's location. This is the third argument passed to [`quadtree.find`](https://github.com/d3/d3-quadtree#quadtree_find) and by default a value of `undefined` means an unlimited range. */
export let searchRadius = undefined;
/** @type {Array} [dataset] - The dataset to work off of—defaults to $data if left unset. You can pass something custom in here in case you don't want to use the main data or it's in a strange format. */
export let dataset = undefined;
$: xGetter = x === 'x' ? $xGet : $yGet;
$: yGetter = y === 'y' ? $yGet : $xGet;
function findItem (evt) {
e = evt;
const xLayerKey = `layer${x.toUpperCase()}`;
const yLayerKey = `layer${y.toUpperCase()}`;
const xLayerVal = (evt[xLayerKey] / (x === 'x' ? $width : $height)) * 100;
const yLayerVal = (evt[yLayerKey] / (y === 'y' ? $height : $width)) * 100;
found = finder.find(xLayerVal, yLayerVal, searchRadius) || {};
visible = Object.keys(found).length > 0;
}
$: finder = quadtree()
.extent([[-1, -1], [$width + 1, $height + 1]])
.x(xGetter)
.y(yGetter)
.addAll(dataset || $data);
</script>
<style>
.bg {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
</style>
<div
class="bg"
on:mousemove="{findItem}"
on:mouseout="{() => visible = false}"
on:blur="{() => visible = false}"
></div>
<slot
x={xGetter(found) || 0}
y={yGetter(found) || 0}
{found}
{visible}
{e}
></slot>