Hexbin 六边形热图
大量散点的 2D 密度聚合,每个六边形按区域内点数加权填色。
基础用法
数据点用 { x, y, weight? }[] 传入。组件根据 radius 把平面切成六边形网格,落到同一格的点累加 weight,最终按权重最大值映射不透明度。
背景 视口
<script setup lang="ts">
import { CfHexbin } from '@chufix-design/vue';
const data = (() => {
const out: { x: number; y: number }[] = [];
const clusters = [
{ cx: 25, cy: 30, sd: 8, n: 380 },
{ cx: 65, cy: 60, sd: 14, n: 520 },
{ cx: 80, cy: 25, sd: 6, n: 200 },
];
for (const c of clusters) {
for (let i = 0; i < c.n; i++) {
let u = 0;
let v = 0;
while (u === 0) u = Math.random();
while (v === 0) v = Math.random();
const g = Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
const g2 = Math.sqrt(-2 * Math.log(u)) * Math.sin(2 * Math.PI * v);
out.push({ x: c.cx + g * c.sd, y: c.cy + g2 * c.sd });
}
}
return out;
})();
</script>
<template>
<CfHexbin :data="data" :width="580" :height="360" :radius="14" />
</template> <script setup>
import { CfHexbin } from '@chufix-design/vue';
const data = (() => {
const out= [];
const clusters = [
{ cx: 25, cy: 30, sd: 8, n: 380 },
{ cx: 65, cy: 60, sd: 14, n: 520 },
{ cx: 80, cy: 25, sd: 6, n: 200 },
];
for (const c of clusters) {
for (let i = 0; i < c.n; i++) {
let u = 0;
let v = 0;
while (u === 0) u = Math.random();
while (v === 0) v = Math.random();
const g = Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
const g2 = Math.sqrt(-2 * Math.log(u)) * Math.sin(2 * Math.PI * v);
out.push({ x: c.cx + g * c.sd, y: c.cy + g2 * c.sd });
}
}
return out;
})();
</script>
<template>
<CfHexbin :data="data" :width="580" :height="360" :radius="14" />
</template> import { CfHexbin } from '@chufix-design/react';
export default function Demo() {
const data = (() => {
const out: { x: number; y: number }[] = [];
const clusters = [
{ cx: 25, cy: 30, sd: 8, n: 380 },
{ cx: 65, cy: 60, sd: 14, n: 520 },
{ cx: 80, cy: 25, sd: 6, n: 200 },
];
for (const c of clusters) {
for (let i = 0; i < c.n; i++) {
let u = 0;
let v = 0;
while (u === 0) u = Math.random();
while (v === 0) v = Math.random();
const g = Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
const g2 = Math.sqrt(-2 * Math.log(u)) * Math.sin(2 * Math.PI * v);
out.push({ x: c.cx + g * c.sd, y: c.cy + g2 * c.sd });
}
}
return out;
})();
return (
<>
<CfHexbin data={data} width={580} height={360} radius={14} />
</>
);
} import { CfHexbin } from '@chufix-design/react';
export default function Demo() {
const data = (() => {
const out= [];
const clusters = [
{ cx: 25, cy: 30, sd: 8, n: 380 },
{ cx: 65, cy: 60, sd: 14, n: 520 },
{ cx: 80, cy: 25, sd: 6, n: 200 },
];
for (const c of clusters) {
for (let i = 0; i < c.n; i++) {
let u = 0;
let v = 0;
while (u === 0) u = Math.random();
while (v === 0) v = Math.random();
const g = Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
const g2 = Math.sqrt(-2 * Math.log(u)) * Math.sin(2 * Math.PI * v);
out.push({ x: c.cx + g * c.sd, y: c.cy + g2 * c.sd });
}
}
return out;
})();
return (
<>
<CfHexbin data={data} width={580} height={360} radius={14} />
</>
);
} 何时用 hexbin
普通散点图在 N > 10k 时会被「过度绘制」掩盖密度结构,Hexbin 把每个点变成「网格内的一份贡献」,能正确反映高密度区域。
API
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
data | HexbinPoint[] | — | { x, y, weight? }[] |
width / height | number | 560/360 | — |
radius | number | 14 | 六边形外接圆半径,越小密度越细 |
xDomain / yDomain | [number, number] | 自动 | 强制坐标域 |
showAxis | boolean | true | 是否绘制极简轴 |
Events
| Vue | React | 载荷 |
|---|---|---|
cell-enter / cell-leave | onCellEnter / onCellLeave | { cell: { cx, cy, count, weight } } |
反馈与讨论
Hexbin 六边形热图 的讨论