RBushWebv0.1.1

Usage guide.

A real example, a clear model, and an explicit lifetime.

Spatial query lens

This is the JavaScript used by the first playground preset. Edit and run it in the interactive playground, including its HTML and CSS.

JavaScript
import {RBush,Envelope} from '@wieslawsoltes/rbushweb';
const count=2000,tree=new RBush(9),canvas=document.querySelector('#spatial'),ctx=canvas.getContext('2d');
let seed=19;const random=()=>((seed=(seed*1664525+1013904223)>>>0)/4294967296);
const items=Array.from({length:count},(_,id)=>{const x=random()*900,y=random()*440;return{id,x,y,Envelope:new Envelope(x,y,x+3,y+3)};});
tree.BulkLoad(items);let x=450,y=220;
function draw(){
 const r=Number(document.querySelector('#radius').value),near=document.querySelector('#mode').value==='nearest';
 const start=performance.now(),found=near?tree.Knn(20,x,y):tree.Search(new Envelope(x-r,y-r,x+r,y+r));
 const elapsed=performance.now()-start,selected=new Set(found);
 ctx.fillStyle=document.documentElement.dataset.theme==='dark'?'#14171c':'#f6f7f9';ctx.fillRect(0,0,900,440);
 for(const item of items){ctx.fillStyle=selected.has(item)?'#a7d260':'#606a78';ctx.fillRect(item.x,item.y,selected.has(item)?5:2,selected.has(item)?5:2);}
 ctx.strokeStyle='#b9e477';ctx.lineWidth=1;
 if(!near){ctx.fillStyle='#a7d26015';ctx.fillRect(x-r,y-r,r*2,r*2);ctx.strokeRect(x-r,y-r,r*2,r*2);}
 else {for(const p of found){ctx.beginPath();ctx.moveTo(x,y);ctx.lineTo(p.x,p.y);ctx.stroke();}}
 ctx.beginPath();ctx.arc(x,y,5,0,Math.PI*2);ctx.stroke();
 document.querySelector('#result').textContent=found.length+' / '+count.toLocaleString()+' · '+elapsed.toFixed(2)+' ms query';
}
canvas.onpointermove=e=>{const b=canvas.getBoundingClientRect();x=(e.clientX-b.left)*900/b.width;y=(e.clientY-b.top)*440/b.height;draw();};
canvas.onkeydown=e=>{if(!['ArrowLeft','ArrowRight','ArrowUp','ArrowDown'].includes(e.key))return;e.preventDefault();x=Math.max(0,Math.min(900,x+(e.key==='ArrowRight'?12:e.key==='ArrowLeft'?-12:0)));y=Math.max(0,Math.min(440,y+(e.key==='ArrowDown'?12:e.key==='ArrowUp'?-12:0)));draw();};
document.querySelector('#center').onclick=()=>{x=450;y=220;draw();};
document.querySelector('#radius').oninput=draw;document.querySelector('#mode').onchange=draw;
draw();console.log('Indexed',tree.Count,'synthetic points. Query time excludes drawing.');
Show the HTML host
HTML
<div class="toolbar"><label>Query <select id="mode"><option value="area">Rectangle intersection</option><option value="nearest">20 nearest neighbors</option></select></label><label>Radius <input id="radius" type="range" min="20" max="140" value="75"></label><button id="center">Center query</button><output id="result"></output></div><canvas id="spatial" width="900" height="440" tabindex="0" aria-label="Spatial query canvas. Use arrow keys to move the query." style="width:100%;height:auto;border:1px solid var(--line);border-radius:10px"></canvas><p class="hint">Move the pointer, touch the canvas, or focus it and use arrow keys. Results come from RBush.Search or RBush.Knn.</p>

How it works

Give geometry an index

Index immutable envelopes, query the relevant area, and keep rendering separate. The same headless engine works in the browser and workers.

Create an RBush, then Insert or BulkLoad objects with an Envelope. Search with a rectangle or use Knn for nearest neighbors.

Own the lifetime

Delete an item using its old bounds before moving it, then insert it with the new envelope. Clear an index when its dataset is discarded.

The playground replaces its entire isolated frame on each run. In your application, use the framework’s unmount or disposal hook instead. Do not dispose a shared model while another view still owns it.

Read the lifecycle guide →

Know the contract

Coordinates are planar numbers. Euclidean nearest-neighbor results are not geodesic distances. Query timings shown here are measured locally, not general benchmarks.

Source repositories can contain work newer than the published package. The showcase uses @wieslawsoltes/rbushweb@0.1.1.

Upstream compatibility documentation ↗
↑ ↓ to explore · Enter to openEsc to close