Preview Updated 2026-05-10

ChartCrosshair

Crosshair locator + tooltip helper that can be embedded inside any SVG chart.

Basic usage

Data is passed in via props and rendered as plain SVG — no third-party charting library. Colors come from the --viz-1..8 tokens and are color-blind friendly.

背景
y=60
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfChartCrosshair } from '@chufix-design/vue';
const x = ref(180);
const y = ref(60);
function onMove(e: MouseEvent) {
  const svg = (e.currentTarget as SVGSVGElement).getBoundingClientRect();
  x.value = e.clientX - svg.left;
  y.value = e.clientY - svg.top;
}
</script>
<template>
  <svg viewBox="0 0 480 200" width="100%" height="200" style="background: var(--bg-inset); border-radius: var(--r-6); cursor: crosshair;" @mousemove="onMove">
    <path d="M 0 150 L 60 130 L 120 110 L 180 90 L 240 70 L 300 80 L 360 60 L 420 50 L 480 40" fill="none" stroke="var(--accent-1)" stroke-width="2" />
    <CfChartCrosshair :x="x" :y="y" :width="480" :height="200" :tooltip="`y=${Math.round(y)}`" show-horizontal />
  </svg>
</template>
<script setup>
import { ref } from 'vue';
import { CfChartCrosshair } from '@chufix-design/vue';
const x = ref(180);
const y = ref(60);
function onMove(e) {
  const svg = (e.currentTarget).getBoundingClientRect();
  x.value = e.clientX - svg.left;
  y.value = e.clientY - svg.top;
}
</script>
<template>
  <svg viewBox="0 0 480 200" width="100%" height="200" style="background: var(--bg-inset); border-radius: var(--r-6); cursor: crosshair;" @mousemove="onMove">
    <path d="M 0 150 L 60 130 L 120 110 L 180 90 L 240 70 L 300 80 L 360 60 L 420 50 L 480 40" fill="none" stroke="var(--accent-1)" stroke-width="2" />
    <CfChartCrosshair :x="x" :y="y" :width="480" :height="200" :tooltip="`y=${Math.round(y)}`" show-horizontal />
  </svg>
</template>
import { useState } from 'react';
import { CfChartCrosshair } from '@chufix-design/react';

export default function Demo() {
  const [x, setX] = useState(180);
  const [y, setY] = useState(60);
  function onMove(e: MouseEvent) {
    const svg = (e.currentTarget as SVGSVGElement).getBoundingClientRect();
    x.value = e.clientX - svg.left;
    y.value = e.clientY - svg.top;
  }
  return (
    <>
      <svg viewBox="0 0 480 200" width="100%" height="200" style={{ background: "var(--bg-inset)", borderRadius: "var(--r-6)", cursor: "crosshair" }} onMousemove={onMove}>
          <path d="M 0 150 L 60 130 L 120 110 L 180 90 L 240 70 L 300 80 L 360 60 L 420 50 L 480 40" fill="none" stroke="var(--accent-1)" stroke-width="2" />
          <CfChartCrosshair x={x} y={y} width={480} height={200} tooltip={`y=${Math.round(y)}`} showHorizontal />
        </svg>
    </>
  );
}
import { useState } from 'react';
import { CfChartCrosshair } from '@chufix-design/react';

export default function Demo() {
  const [x, setX] = useState(180);
  const [y, setY] = useState(60);
  function onMove(e) {
    const svg = (e.currentTarget).getBoundingClientRect();
    x.value = e.clientX - svg.left;
    y.value = e.clientY - svg.top;
  }
  return (
    <>
      <svg viewBox="0 0 480 200" width="100%" height="200" style={{ background: "var(--bg-inset)", borderRadius: "var(--r-6)", cursor: "crosshair" }} onMousemove={onMove}>
          <path d="M 0 150 L 60 130 L 120 110 L 180 90 L 240 70 L 300 80 L 360 60 L 420 50 L 480 40" fill="none" stroke="var(--accent-1)" stroke-width="2" />
          <CfChartCrosshair x={x} y={y} width={480} height={200} tooltip={`y=${Math.round(y)}`} showHorizontal />
        </svg>
    </>
  );
}

API

PropTypeDefaultDescription
visiblebooleantrue
x / ynumberPixel coordinates (within the parent SVG coordinate system)
width / heightnumberTotal parent SVG size (used to size the lines)
showVertical / showHorizontalbooleantrue / false
tooltipstringValue label that follows the cursor

反馈与讨论

ChartCrosshair · Discussion

0
0 / 600
一键发送
正在加载评论...