Measure ruler
Click two points to measure the change between them.
Why it matters no ruler tool in core; app-level: two clicks drop markers and an annotation shows Δ value and Δ time
Open the chart without page chrome ↗
const options = {
chart: {
height: 380,
fontFamily: "Inter, Geist, \"IBM Plex Sans\", system-ui, sans-serif",
type: "line",
events: {
markerClick: () => {},
click: (e, ch, o) => { const i = o.dataPointIndex; if (i == null || i < 0) return; pick = pick.length >= 2 ? [i] : pick.concat(i); const pts = pick.map((k) => ({ x: d[k][0], y: d[k][1], marker: { size: 6, fillColor: '#e11d48', strokeColor: '#fff' } })); let xs = []; if (pick.length === 2) { const [a, b] = pick.slice().sort((p, q) => p - q); const dv = d[b][1] - d[a][1]; xs = [{ x: d[a][0], x2: d[b][0], fillColor: '#e11d48', opacity: 0.08, label: { text: (dv >= 0 ? '+' : '\u2212') + Math.abs(dv).toFixed(1) + ' (' + ((dv / d[a][1]) * 100).toFixed(1) + '%) over ' + (b - a) + ' days', style: { background: '#e11d48', color: '#fff' } } }] } ch.updateOptions({ annotations: { points: pts, xaxis: xs } }, false, false) }
},
toolbar: {
show: false
}
},
series: [
{
name: "Price",
data: [
[1767571200000, 99],
[1767657600000, 100.5],
[1767744000000, 101],
[1767830400000, 99.3],
[1767916800000, 100.6],
[1768003200000, 99.7],
[1768089600000, 100.6],
[1768176000000, 100.9],
[1768262400000, 101],
[1768348800000, 101],
[1768435200000, 101.5],
[1768521600000, 100.9],
[1768608000000, 102],
[1768694400000, 100.9],
[1768780800000, 102.3],
[1768867200000, 103],
[1768953600000, 105],
[1769040000000, 106.7],
[1769126400000, 105.8],
[1769212800000, 104],
[1769299200000, 104.6],
[1769385600000, 105.7],
[1769472000000, 105.1],
[1769558400000, 105.8],
[1769644800000, 107.6],
[1769731200000, 108.7],
[1769817600000, 108],
[1769904000000, 107.5],
[1769990400000, 106.1],
[1770076800000, 104.3],
[1770163200000, 104.4],
[1770249600000, 105.6],
[1770336000000, 107.1],
[1770422400000, 105.4],
[1770508800000, 103.9],
[1770595200000, 104.3],
[1770681600000, 103.9],
[1770768000000, 105.9],
[1770854400000, 106.7],
[1770940800000, 107],
[1771027200000, 107.8],
[1771113600000, 107.9],
[1771200000000, 108.4],
[1771286400000, 108],
[1771372800000, 106.1],
[1771459200000, 107.5],
[1771545600000, 107.1],
[1771632000000, 108.6],
[1771718400000, 107],
[1771804800000, 106.9],
[1771891200000, 106.7],
[1771977600000, 104.9],
[1772064000000, 103.4],
[1772150400000, 104.1],
[1772236800000, 103],
[1772323200000, 101.1],
[1772409600000, 100.7],
[1772496000000, 102.5],
[1772582400000, 103.4],
[1772668800000, 103.3],
[1772755200000, 102.7],
[1772841600000, 104.4],
[1772928000000, 106],
[1773014400000, 107.4],
[1773100800000, 105.5],
[1773187200000, 106.1],
[1773273600000, 106],
[1773360000000, 104.5],
[1773446400000, 105.1],
[1773532800000, 106.4],
[1773619200000, 107.2],
[1773705600000, 105.5],
[1773792000000, 104.5],
[1773878400000, 106.3],
[1773964800000, 107.7],
[1774051200000, 107.7],
[1774137600000, 108.1],
[1774224000000, 109.7],
[1774310400000, 109],
[1774396800000, 109.8],
[1774483200000, 108.6],
[1774569600000, 108.3],
[1774656000000, 109.3],
[1774742400000, 110.5],
[1774828800000, 110.6],
[1774915200000, 109.6],
[1775001600000, 109.7],
[1775088000000, 110.6],
[1775174400000, 112.1],
[1775260800000, 113.3],
[1775347200000, 114.3],
[1775433600000, 113.8],
[1775520000000, 113.3],
[1775606400000, 114.1],
[1775692800000, 112.8],
[1775779200000, 112.3],
[1775865600000, 112.2],
[1775952000000, 114.2],
[1776038400000, 115.1],
[1776124800000, 116],
[1776211200000, 115.2],
[1776297600000, 115.5],
[1776384000000, 116.1],
[1776470400000, 116],
[1776556800000, 117.1],
[1776643200000, 116.5],
[1776729600000, 117.1],
[1776816000000, 116.6],
[1776902400000, 115.5],
[1776988800000, 113.9],
[1777075200000, 113.1],
[1777161600000, 112.4],
[1777248000000, 113.3],
[1777334400000, 112.7],
[1777420800000, 113.8],
[1777507200000, 115.4],
[1777593600000, 115.1],
[1777680000000, 113.4],
[1777766400000, 114.7],
[1777852800000, 114.9]
]
}
],
xaxis: {
type: "datetime"
},
tooltip: {
shared: true,
intersect: false
},
stroke: {
width: 2
},
title: {
text: "Click two points to measure"
},
theme: {
mode: "light",
preset: "coastal"
}
}
const chart = new WestCoastCharts(document.querySelector('#chart'), options)
chart.render()import WestCoastCharts from 'west-coast-charts'
const options = {
chart: {
height: 380,
fontFamily: "Inter, Geist, \"IBM Plex Sans\", system-ui, sans-serif",
type: "line",
events: {
markerClick: () => {},
click: (e, ch, o) => { const i = o.dataPointIndex; if (i == null || i < 0) return; pick = pick.length >= 2 ? [i] : pick.concat(i); const pts = pick.map((k) => ({ x: d[k][0], y: d[k][1], marker: { size: 6, fillColor: '#e11d48', strokeColor: '#fff' } })); let xs = []; if (pick.length === 2) { const [a, b] = pick.slice().sort((p, q) => p - q); const dv = d[b][1] - d[a][1]; xs = [{ x: d[a][0], x2: d[b][0], fillColor: '#e11d48', opacity: 0.08, label: { text: (dv >= 0 ? '+' : '\u2212') + Math.abs(dv).toFixed(1) + ' (' + ((dv / d[a][1]) * 100).toFixed(1) + '%) over ' + (b - a) + ' days', style: { background: '#e11d48', color: '#fff' } } }] } ch.updateOptions({ annotations: { points: pts, xaxis: xs } }, false, false) }
},
toolbar: {
show: false
}
},
series: [
{
name: "Price",
data: [
[1767571200000, 99],
[1767657600000, 100.5],
[1767744000000, 101],
[1767830400000, 99.3],
[1767916800000, 100.6],
[1768003200000, 99.7],
[1768089600000, 100.6],
[1768176000000, 100.9],
[1768262400000, 101],
[1768348800000, 101],
[1768435200000, 101.5],
[1768521600000, 100.9],
[1768608000000, 102],
[1768694400000, 100.9],
[1768780800000, 102.3],
[1768867200000, 103],
[1768953600000, 105],
[1769040000000, 106.7],
[1769126400000, 105.8],
[1769212800000, 104],
[1769299200000, 104.6],
[1769385600000, 105.7],
[1769472000000, 105.1],
[1769558400000, 105.8],
[1769644800000, 107.6],
[1769731200000, 108.7],
[1769817600000, 108],
[1769904000000, 107.5],
[1769990400000, 106.1],
[1770076800000, 104.3],
[1770163200000, 104.4],
[1770249600000, 105.6],
[1770336000000, 107.1],
[1770422400000, 105.4],
[1770508800000, 103.9],
[1770595200000, 104.3],
[1770681600000, 103.9],
[1770768000000, 105.9],
[1770854400000, 106.7],
[1770940800000, 107],
[1771027200000, 107.8],
[1771113600000, 107.9],
[1771200000000, 108.4],
[1771286400000, 108],
[1771372800000, 106.1],
[1771459200000, 107.5],
[1771545600000, 107.1],
[1771632000000, 108.6],
[1771718400000, 107],
[1771804800000, 106.9],
[1771891200000, 106.7],
[1771977600000, 104.9],
[1772064000000, 103.4],
[1772150400000, 104.1],
[1772236800000, 103],
[1772323200000, 101.1],
[1772409600000, 100.7],
[1772496000000, 102.5],
[1772582400000, 103.4],
[1772668800000, 103.3],
[1772755200000, 102.7],
[1772841600000, 104.4],
[1772928000000, 106],
[1773014400000, 107.4],
[1773100800000, 105.5],
[1773187200000, 106.1],
[1773273600000, 106],
[1773360000000, 104.5],
[1773446400000, 105.1],
[1773532800000, 106.4],
[1773619200000, 107.2],
[1773705600000, 105.5],
[1773792000000, 104.5],
[1773878400000, 106.3],
[1773964800000, 107.7],
[1774051200000, 107.7],
[1774137600000, 108.1],
[1774224000000, 109.7],
[1774310400000, 109],
[1774396800000, 109.8],
[1774483200000, 108.6],
[1774569600000, 108.3],
[1774656000000, 109.3],
[1774742400000, 110.5],
[1774828800000, 110.6],
[1774915200000, 109.6],
[1775001600000, 109.7],
[1775088000000, 110.6],
[1775174400000, 112.1],
[1775260800000, 113.3],
[1775347200000, 114.3],
[1775433600000, 113.8],
[1775520000000, 113.3],
[1775606400000, 114.1],
[1775692800000, 112.8],
[1775779200000, 112.3],
[1775865600000, 112.2],
[1775952000000, 114.2],
[1776038400000, 115.1],
[1776124800000, 116],
[1776211200000, 115.2],
[1776297600000, 115.5],
[1776384000000, 116.1],
[1776470400000, 116],
[1776556800000, 117.1],
[1776643200000, 116.5],
[1776729600000, 117.1],
[1776816000000, 116.6],
[1776902400000, 115.5],
[1776988800000, 113.9],
[1777075200000, 113.1],
[1777161600000, 112.4],
[1777248000000, 113.3],
[1777334400000, 112.7],
[1777420800000, 113.8],
[1777507200000, 115.4],
[1777593600000, 115.1],
[1777680000000, 113.4],
[1777766400000, 114.7],
[1777852800000, 114.9]
]
}
],
xaxis: {
type: "datetime"
},
tooltip: {
shared: true,
intersect: false
},
stroke: {
width: 2
},
title: {
text: "Click two points to measure"
},
theme: {
mode: "light",
preset: "coastal"
}
}
const chart = new WestCoastCharts(document.querySelector('#chart'), options)
await chart.render() Waiting for the chart.
Open Data & agent view to read this chart through chart.describe().
Read from the running library through its optional agent/describe module. Text, table and JSON share the same snapshot. Demo data only.
$ wcc chart export interactivity-measure-ruler.json --out interactivity-measure-ruler.svg --with-table Public agent tools 0.2.3, tested with Library 1.1.5; available from the versioned GitHub release and npm. Save a JSON spec first and check the loaded runtime and supported modules before rendering. Command reference
Loading /gallery/interactivity/measure-ruler/index.md …