ScatterPlot 散点图
二维散点,可按 group 分色。
基础用法
数据通过 props 传入,纯 SVG 渲染,无第三方图表库依赖。
配色取自 --viz-1..8 token,色盲友好。
背景 视口
<script setup lang="ts">
import { CfScatterPlot } from '@chufix-design/vue';
const data = Array.from({ length: 60 }, (_, i) => ({
x: (i * 37) % 100,
y: (i * 53 + 17) % 100,
group: i % 4 === 0 ? 'a' : i % 4 === 1 ? 'b' : i % 4 === 2 ? 'c' : 'd',
}));
</script>
<template>
<CfScatterPlot :data="data" />
</template> <script setup>
import { CfScatterPlot } from '@chufix-design/vue';
const data = Array.from({ length: 60 }, (_, i) => ({
x: (i * 37) % 100,
y: (i * 53 + 17) % 100,
group: i % 4 === 0 ? 'a' : i % 4 === 1 ? 'b' : i % 4 === 2 ? 'c' : 'd',
}));
</script>
<template>
<CfScatterPlot :data="data" />
</template> import { CfScatterPlot } from '@chufix-design/react';
export default function Demo() {
const data = Array.from({ length: 60 }, (_, i) => ({
x: (i * 37) % 100,
y: (i * 53 + 17) % 100,
group: i % 4 === 0 ? 'a' : i % 4 === 1 ? 'b' : i % 4 === 2 ? 'c' : 'd',
}));
return (
<>
<CfScatterPlot data={data} />
</>
);
} import { CfScatterPlot } from '@chufix-design/react';
export default function Demo() {
const data = Array.from({ length: 60 }, (_, i) => ({
x: (i * 37) % 100,
y: (i * 53 + 17) % 100,
group: i % 4 === 0 ? 'a' : i % 4 === 1 ? 'b' : i % 4 === 2 ? 'c' : 'd',
}));
return (
<>
<CfScatterPlot data={data} />
</>
);
} 多 group 聚类
点的 group 字段决定颜色,未传则归到 default。
背景 视口
<script setup lang="ts">
import { CfScatterPlot } from '@chufix-design/vue';
function gen(n: number, group: string, cx: number, cy: number, spread = 20) {
return Array.from({ length: n }, (_, i) => ({
x: cx + ((((i * 29) % 100) / 100) - 0.5) * spread,
y: cy + ((((i * 43 + 11) % 100) / 100) - 0.5) * spread,
group,
}));
}
const data = [
...gen(30, 'cluster-a', 30, 30),
...gen(30, 'cluster-b', 70, 60),
...gen(30, 'cluster-c', 50, 85),
...gen(20, 'outliers', 80, 20, 40),
];
</script>
<template>
<CfScatterPlot :data="data" />
</template> <script setup>
import { CfScatterPlot } from '@chufix-design/vue';
function gen(n, group, cx, cy, spread = 20) {
return Array.from({ length: n }, (_, i) => ({
x: cx + ((((i * 29) % 100) / 100) - 0.5) * spread,
y: cy + ((((i * 43 + 11) % 100) / 100) - 0.5) * spread,
group,
}));
}
const data = [
...gen(30, 'cluster-a', 30, 30),
...gen(30, 'cluster-b', 70, 60),
...gen(30, 'cluster-c', 50, 85),
...gen(20, 'outliers', 80, 20, 40),
];
</script>
<template>
<CfScatterPlot :data="data" />
</template> import { CfScatterPlot } from '@chufix-design/react';
export default function Demo() {
function gen(n: number, group: string, cx: number, cy: number, spread = 20) {
return Array.from({ length: n }, (_, i) => ({
x: cx + ((((i * 29) % 100) / 100) - 0.5) * spread,
y: cy + ((((i * 43 + 11) % 100) / 100) - 0.5) * spread,
group,
}));
}
const data = [
...gen(30, 'cluster-a', 30, 30),
...gen(30, 'cluster-b', 70, 60),
...gen(30, 'cluster-c', 50, 85),
...gen(20, 'outliers', 80, 20, 40),
];
return (
<>
<CfScatterPlot data={data} />
</>
);
} import { CfScatterPlot } from '@chufix-design/react';
export default function Demo() {
function gen(n, group, cx, cy, spread = 20) {
return Array.from({ length: n }, (_, i) => ({
x: cx + ((((i * 29) % 100) / 100) - 0.5) * spread,
y: cy + ((((i * 43 + 11) % 100) / 100) - 0.5) * spread,
group,
}));
}
const data = [
...gen(30, 'cluster-a', 30, 30),
...gen(30, 'cluster-b', 70, 60),
...gen(30, 'cluster-c', 50, 85),
...gen(20, 'outliers', 80, 20, 40),
];
return (
<>
<CfScatterPlot data={data} />
</>
);
} API
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
data | ScatterPoint[] | — | { x, y, r?, group?, label? }[] |
width | number | 480 | SVG 宽度 |
height | number | 240 | SVG 高度 |
showGrid | boolean | true | 显示网格 |
showTooltip | boolean | true | 启用 hover tooltip |
tooltipFormatter | (payload: ScatterPlotInteractionPayload) => string | — | 完整 tooltip HTML 自渲染 |
ariaLabel | string | — | 透传给根 <svg> 的 aria-label |
Events
| Vue 事件 | React 回调 | 载荷类型 | 说明 |
|---|---|---|---|
item-enter | onItemEnter | ScatterPlotInteractionPayload | 鼠标进入某点时触发 |
item-leave | onItemLeave | ScatterPlotInteractionPayload | 鼠标离开时触发 |
类型
interface ScatterPoint {
x: number;
y: number;
r?: number; // 气泡半径(默认按数据自适应)
group?: string; // 用于按组分色
label?: string; // 单点标签
}
interface ScatterPlotInteractionPayload {
point: ScatterPoint;
dataIndex: number;
groupIndex: number;
nativeEvent?: MouseEvent;
}
反馈与讨论
ScatterPlot 散点图 的讨论