@zerodep-dev/vue-tsx-pro-ui 0.3.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/charts/AreaChart.d.ts +1 -1
- package/dist/charts/AreaChart.js +6 -48
- package/dist/charts/AreaChart.js.map +1 -1
- package/dist/charts/BarChart.js +6 -49
- package/dist/charts/BarChart.js.map +1 -1
- package/dist/charts/ChordChart.d.ts +7 -2
- package/dist/charts/ChordChart.js +151 -60
- package/dist/charts/ChordChart.js.map +1 -1
- package/dist/charts/ComboChart.d.ts +2 -1
- package/dist/charts/ComboChart.js +17 -93
- package/dist/charts/ComboChart.js.map +1 -1
- package/dist/charts/DonutChart.d.ts +6 -1
- package/dist/charts/DonutChart.js +134 -51
- package/dist/charts/DonutChart.js.map +1 -1
- package/dist/charts/FunnelChart.js.map +1 -1
- package/dist/charts/GraphChart.d.ts +22 -10
- package/dist/charts/GraphChart.js +415 -175
- package/dist/charts/GraphChart.js.map +1 -1
- package/dist/charts/LineChart.d.ts +1 -29
- package/dist/charts/LineChart.js +6 -54
- package/dist/charts/LineChart.js.map +1 -1
- package/dist/charts/MapChart.d.ts +21 -48
- package/dist/charts/MapChart.js +426 -353
- package/dist/charts/MapChart.js.map +1 -1
- package/dist/charts/RadarChart.js.map +1 -1
- package/dist/charts/SankeyChart.d.ts +7 -2
- package/dist/charts/SankeyChart.js +164 -76
- package/dist/charts/SankeyChart.js.map +1 -1
- package/dist/charts/ScatterChart.d.ts +7 -1
- package/dist/charts/ScatterChart.js +45 -30
- package/dist/charts/ScatterChart.js.map +1 -1
- package/dist/charts/TimelineChart.d.ts +8 -1
- package/dist/charts/TimelineChart.js +141 -89
- package/dist/charts/TimelineChart.js.map +1 -1
- package/dist/charts/TreemapChart.d.ts +6 -0
- package/dist/charts/TreemapChart.js +174 -58
- package/dist/charts/TreemapChart.js.map +1 -1
- package/dist/charts/WaterfallChart.d.ts +6 -7
- package/dist/charts/WaterfallChart.js +46 -51
- package/dist/charts/WaterfallChart.js.map +1 -1
- package/dist/charts/XYChart.d.ts +44 -35
- package/dist/charts/XYChart.js +493 -281
- package/dist/charts/XYChart.js.map +1 -1
- package/dist/charts/axis-ticks.d.ts +1 -1
- package/dist/charts/axis-ticks.js +4 -5
- package/dist/charts/axis-ticks.js.map +1 -1
- package/dist/charts/flow.d.ts +4 -11
- package/dist/charts/flow.js +4 -4
- package/dist/charts/flow.js.map +1 -1
- package/dist/charts/frame.d.ts +6 -30
- package/dist/charts/frame.js +6 -99
- package/dist/charts/frame.js.map +1 -1
- package/dist/charts/geo/projection.d.ts +45 -0
- package/dist/charts/geo/projection.js +201 -0
- package/dist/charts/geo/projection.js.map +1 -0
- package/dist/charts/geo/topojson.d.ts +50 -0
- package/dist/charts/geo/topojson.js +119 -0
- package/dist/charts/geo/topojson.js.map +1 -0
- package/dist/charts/index.d.ts +21 -9
- package/dist/charts/index.js +19 -8
- package/dist/charts/label-layout.js.map +1 -1
- package/dist/charts/layout/chord.d.ts +44 -0
- package/dist/charts/layout/chord.js +45 -0
- package/dist/charts/layout/chord.js.map +1 -0
- package/dist/charts/layout/graph.d.ts +49 -0
- package/dist/charts/layout/graph.js +268 -0
- package/dist/charts/layout/graph.js.map +1 -0
- package/dist/charts/layout/sankey.d.ts +79 -0
- package/dist/charts/layout/sankey.js +200 -0
- package/dist/charts/layout/sankey.js.map +1 -0
- package/dist/charts/layout/treemap.d.ts +46 -0
- package/dist/charts/layout/treemap.js +152 -0
- package/dist/charts/layout/treemap.js.map +1 -0
- package/dist/charts/marks.d.ts +79 -0
- package/dist/charts/marks.js +231 -0
- package/dist/charts/marks.js.map +1 -0
- package/dist/charts/plot.d.ts +107 -0
- package/dist/charts/plot.js +231 -0
- package/dist/charts/plot.js.map +1 -0
- package/dist/charts/scale.d.ts +29 -0
- package/dist/charts/scale.js +244 -0
- package/dist/charts/scale.js.map +1 -0
- package/dist/charts/shape.d.ts +46 -0
- package/dist/charts/shape.js +131 -0
- package/dist/charts/shape.js.map +1 -0
- package/dist/charts/stack.d.ts +17 -0
- package/dist/charts/stack.js +35 -0
- package/dist/charts/stack.js.map +1 -0
- package/dist/charts/text-size.d.ts +12 -0
- package/dist/charts/text-size.js +32 -0
- package/dist/charts/text-size.js.map +1 -0
- package/dist/display/VirtualList.d.ts +1 -2
- package/dist/display/VirtualList.js +11 -21
- package/dist/display/VirtualList.js.map +1 -1
- package/dist/input/Combobox.d.ts +1 -1
- package/dist/input/Combobox.js.map +1 -1
- package/dist/input/ListPopover.d.ts +1 -1
- package/dist/input/ListPopover.js.map +1 -1
- package/dist/input/Listbox.d.ts +1 -2
- package/dist/input/Listbox.js +7 -19
- package/dist/input/Listbox.js.map +1 -1
- package/dist/input/Select.d.ts +1 -1
- package/dist/input/Select.js.map +1 -1
- package/dist/maps/china-provinces.js +35680 -0
- package/dist/maps/china-provinces.js.map +1 -0
- package/dist/maps/china.d.ts +13 -0
- package/dist/maps/china.js +8 -0
- package/dist/maps/china.js.map +1 -0
- package/dist/maps/index.d.ts +9 -0
- package/dist/maps/index.js +3 -0
- package/dist/maps/world-countries.js +22273 -0
- package/dist/maps/world-countries.js.map +1 -0
- package/dist/maps/world.d.ts +13 -0
- package/dist/maps/world.js +8 -0
- package/dist/maps/world.js.map +1 -0
- package/dist/overlay/CommandPalette.d.ts +1 -1
- package/dist/overlay/CommandPalette.js.map +1 -1
- package/dist/overlay/detached.js +14 -1
- package/dist/overlay/detached.js.map +1 -1
- package/dist/patterns/QueryTable.js +0 -2
- package/dist/patterns/QueryTable.js.map +1 -1
- package/dist/table/DataTable.js +1 -1
- package/dist/table/DataTable.js.map +1 -1
- package/dist/table/DataTableView.d.ts +0 -3
- package/dist/table/DataTableView.js +32 -26
- package/dist/table/DataTableView.js.map +1 -1
- package/dist/table/table-styles.d.ts +1 -1
- package/dist/table/table-styles.js +0 -13
- package/dist/table/table-styles.js.map +1 -1
- package/package.json +7 -8
- package/dist/charts/single.d.ts +0 -41
- package/dist/charts/single.js +0 -66
- package/dist/charts/single.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapChart.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_computed","_vue_shallowRef","_createVNode","_mergeProps","_createTextVNode","_vue_ref"],"sources":["../../src/charts/MapChart.tsx"],"sourcesContent":["/**\n * 地图:按区域着色(分省的销售额、各国的采购额),标出地点(工厂、供应商)与它们之间的流向。\n * 地理数据是 TopoJSON:Unovis 自带中国省份、世界、美国等(`@unovis/ts/maps`),也可以用自己的。\n *\n * import { ChinaTopoJSON } from '@unovis/ts/maps';\n * <MapChart\n * aria-label=\"各省销售额\"\n * topology={ChinaTopoJSON}\n * feature=\"provinces\"\n * areas={[{ id: 'CN-JS', label: '江苏', value: 623 }, …]} // id 是地图要素的 id\n * points={[{ id: 'sh', label: '上海组装', longitude: 121.47, latitude: 31.23, value: 860 }]}\n * links={[{ from: 'xa', to: 'sh', value: 120 }]}\n * bins={5}\n * areaLabels\n * />\n *\n * 投影:默认按地理数据的范围选——一个国家、一个地区用以它为中心的等积圆锥投影(中国地图常用的 Albers,正着、不歪),\n * 跨了大半个地球时用 Natural Earth;也可以指定 mercator、equalEarth、orthographic(地球仪)或自己的 d3 投影。\n *\n * 着色:sequential(默认)按数值深浅;diverging 以 midpoint 为界两头两种颜色(同比的涨跌);\n * bins 分成几档(分级着色,图例是几个色块),不写时连续着色(图例是色带);区域写了 color 时按它(分类着色)。\n * 没有数据的区域是底色。地点:value 决定大小(面积按比例),color、shape 决定颜色与形状;名字自动避让\n * (换方位、挤时往外退并画引线,数值大的先放,放不下的悬停看;压住名字、地点的区域名藏起来);\n * links 是地点之间的流向,粗细按 value,flow 时有流动的粒子。\n * zoomable 时可以拖动、按住 Ctrl 滚轮缩放,右上角有放大、缩小、复位的按钮。悬停看名称与数值;读屏的数据表列出各区域、地点与流向。\n */\nimport {\n MapProjection,\n TopoJSONMap,\n type MapGraphData,\n type TopoJSONMapConfigInterface,\n} from '@unovis/ts';\nimport { Maximize, Minus, Plus } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { presimplify, simplify } from 'topojson-simplify';\nimport type { VNodeChild } from 'vue';\nimport { IconButton } from '../base/IconButton';\nimport { useLang } from '../config/context';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { colors } from '../config/theme/tokens';\nimport { Skeleton } from '../feedback/Skeleton';\nimport { toNumber, type NumericValue } from '../utils/data/numeric';\nimport { useEventListener } from '../utils/dom/event-listener';\nimport type { PartProps } from '../utils/props';\nimport { chartTooltip, ChartFrame, type ChartFrameParts } from './frame';\nimport { placeLabels, rectsOverlap, type LabelRect } from './label-layout';\nimport { resolveColor, type ChartColor } from './series';\nimport { useSingleChart, type SingleChart } from './single';\n\n/** 一个区域的数据 */\nexport interface MapArea {\n /** 地图要素的 id(Unovis 的中国省份是 'CN-JS' 这样的写法) */\n id: string;\n /** 显示的名称:提示框、区域名、数据表 */\n label: string;\n /** 数值:决定颜色 */\n value?: NumericValue;\n /** 指定颜色:不按数值着色(分类着色,如所属大区) */\n color?: ChartColor;\n}\n\n/** 一个地点 */\nexport interface MapPoint {\n /** 标识:流向的 from、to 指向它 */\n id: string;\n /** 名称:写在点下方 */\n label: string;\n /** 经度 */\n longitude: number;\n /** 纬度 */\n latitude: number;\n /** 数值:决定点的大小(面积按比例),也显示在提示框 */\n value?: NumericValue;\n /** 颜色,默认 danger */\n color?: ChartColor;\n /** 形状,默认 circle */\n shape?: 'circle' | 'square' | 'triangle';\n}\n\n/** 两个地点之间的流向 */\nexport interface MapLink {\n /** 起点(地点的 id) */\n from: string;\n /** 终点(地点的 id) */\n to: string;\n /** 数值:决定线的粗细,也显示在数据表 */\n value?: NumericValue;\n /** 颜色,默认次要色 */\n color?: ChartColor;\n}\n\n/** 投影的预设 */\nexport interface MapProjections {\n /** 等积圆锥(Albers):以数据为中心,一个国家、一个地区用它(中国地图常用),正着、面积不失真 */\n conic: unknown;\n /** 墨卡托:网页地图常见,高纬度会放大 */\n mercator: unknown;\n /** Natural Earth:世界地图,形状与面积都比较自然 */\n naturalEarth: unknown;\n /** Equal Earth:世界地图,面积准确 */\n equalEarth: unknown;\n /** 正射(地球仪):以数据为中心看半个地球 */\n orthographic: unknown;\n}\n\n/** d3 的投影(TopoJSONMap 的 projection) */\nexport type MapGeoProjection = NonNullable<TopoJSONMapConfigInterface<MapArea>['projection']>;\n\n/** 未声明的属性落到外层 div(role=\"figure\")上;aria-label 是图表的名称 */\nexport interface MapChartProps extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {\n /** 地理数据(TopoJSON),如 `@unovis/ts/maps` 的 ChinaTopoJSON、WorldMapTopoJSON */\n topology: NonNullable<TopoJSONMapConfigInterface<MapArea>['topojson']>;\n /** 画哪一组要素(TopoJSON 的 objects 里的名字),如中国省份是 'provinces'、世界是 'countries' */\n feature: string;\n /** 投影:预设的名字,或 d3 的投影;不写时按数据的范围选 conic 或 naturalEarth */\n projection?: keyof MapProjections | MapGeoProjection;\n /** 投影的中心 [经度, 纬度]:中央经线(世界地图写 [150, 0] 以太平洋为中心),orthographic 还用纬度;不写时取地理数据范围的中心 */\n center?: readonly [number, number];\n /** 各区域的数值 */\n areas?: readonly MapArea[];\n /** 地点 */\n points?: readonly MapPoint[];\n /** 地点之间的流向 */\n links?: readonly MapLink[];\n /** 着色方式:sequential 按数值深浅(默认),diverging 以 midpoint 为界两头两种颜色 */\n scheme?: 'sequential' | 'diverging';\n /** sequential 的基色,默认 accent */\n color?: ChartColor;\n /** diverging 的两头 [低, 高],默认 ['danger', 'success'] */\n divergingColors?: readonly [ChartColor, ChartColor];\n /** diverging 的分界,默认 0 */\n midpoint?: number;\n /** 分成几档(分级着色);不写时连续着色 */\n bins?: number;\n /** 在区域上写名字(区域够大时) */\n areaLabels?: boolean;\n /** 流向上有流动的粒子 */\n flow?: boolean;\n /** 数值的格式 */\n valueFormat?: NumericFormat;\n /** 单位:显示在左上方,提示框与数据表的数值后面带上 */\n unit?: string;\n /**\n * 绘图区的高度;数字按 px\n * @default 400\n */\n height?: number | string;\n /** 可以拖动、滚轮缩放,右上角有放大、缩小、复位的按钮;默认关(不抢页面的滚动) */\n zoomable?: boolean;\n /** 加载中:绘图区显示骨架 */\n loading?: boolean;\n /** 没有数据时显示的内容 */\n empty?: VNodeChild;\n /** 悬停时的提示框,默认 true */\n tooltip?: boolean;\n /** 点了一个有数据的区域 */\n onAreaClick?: (area: MapArea) => void;\n /** 点了一个地点 */\n onPointClick?: (point: MapPoint) => void;\n}\n\n/** MapChart 的样式 */\nexport const mapChartStyles = css.create({\n // 地图跟随主题:底色、边界是表面色,文字是正文色\n root: {\n '--vis-map-feature-color': colors.fill,\n '--vis-map-boundary-color': colors.surface,\n '--vis-map-point-label-text-color-dark': colors.text,\n '--vis-map-point-label-text-color-light': colors.text,\n '--vis-map-area-label-text-color': colors.text,\n '--vis-map-area-label-font-size': '10px',\n '--vis-map-area-label-font-weight': '400',\n '--vis-map-point-default-stroke-color': colors.surface,\n '--vis-map-point-default-stroke-width': '1.5px',\n },\n skeleton: { display: 'block', width: '100%', height: '100%' },\n // 地点的标签:描一圈表面色的边,压在区域、连线上也看得清;字号、描边宽度随缩放在行内设置\n pointLabels: {\n fontWeight: 600,\n fill: colors.text,\n stroke: colors.surface,\n paintOrder: 'stroke',\n strokeLinejoin: 'round',\n pointerEvents: 'none',\n },\n leader: { stroke: colors.textMuted },\n // 缩放按钮:在标题行的结束边(导出菜单前面)\n zoom: { display: 'inline-flex', alignItems: 'center', gap: '2px', marginInlineStart: 'auto' },\n wheelHint: { marginInlineEnd: '_sm', color: '_textMuted', fontSize: '_xs' },\n // 图例:连续是色带,分档是一排色块\n legend: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n columnGap: '_md',\n rowGap: '_xs',\n fontSize: '_xs',\n color: '_textMuted',\n paddingInline: '_sm',\n },\n ramp: { flexGrow: 1, maxWidth: '16rem', height: '0.5rem', borderRadius: '_full' },\n rampColors: (gradient: string) => ({ backgroundImage: gradient }),\n bin: { display: 'inline-flex', alignItems: 'center', gap: '0.375em', whiteSpace: 'nowrap' },\n swatch: { width: '0.875rem', height: '0.625rem', borderRadius: '2px' },\n swatchColor: (color: string) => ({ backgroundColor: color }),\n});\n\n/** 地点的标签四周留的空(屏幕像素) */\nconst labelPadding = 3;\n\n/** 新建一个 SVG 元素 */\nconst svgElement = <K extends keyof SVGElementTagNameMap>(name: K) =>\n document.createElementNS('http://www.w3.org/2000/svg', name);\n\n/** 混色:基色占 percent,其余透明(落在底色上) */\nconst tint = (color: string, percent: number) =>\n `color-mix(in srgb, ${color} ${Math.round(percent)}%, transparent)`;\n\ntype MapTopology = MapChartProps['topology'];\n\n/** 算好了各点权重的地理数据:同一份 TopoJSON 只算一次 */\nconst presimplified = new WeakMap<MapTopology, MapTopology>();\n/**\n * 简化过的地理数据放进这个类的实例:Unovis 的 setConfig 深拷贝配置,但跳过类的实例,\n * 每次更新就不必把整份 TopoJSON 再拷一遍\n */\nclass SharedTopology {}\n\n/** 简化过的地理数据:TopoJSON → 档位 → 结果 */\nconst simplified = new WeakMap<MapTopology, Map<number, MapTopology>>();\n\n/**\n * 简化地理数据:去掉与前后两点围成的三角形面积不到 minArea(坐标单位的平方,经纬度是平方度)的点\n * (Visvalingam,topojson-simplify)。相邻区域共用的边界一起简化,不会出现缝隙;各段弧的两端总保留。\n * minArea 按 2 的整数次幂分档缓存:绘图区大小变一点不重算。\n */\nexport function simplifyTopology(topology: MapTopology, minArea: number): MapTopology {\n if (!(minArea > 0) || !Number.isFinite(minArea)) return topology;\n const level = 2 ** Math.floor(Math.log2(minArea));\n let byLevel = simplified.get(topology);\n if (!byLevel) simplified.set(topology, (byLevel = new Map()));\n let result = byLevel.get(level);\n if (!result) {\n // topojson-simplify 的类型里要素属性不能是 null(GeoJSON 允许):边界上转一下\n type Input = Parameters<typeof presimplify>[0];\n let weighted = presimplified.get(topology);\n if (!weighted)\n presimplified.set(topology, (weighted = presimplify(topology as Input) as MapTopology));\n result = Object.assign(new SharedTopology(), simplify(weighted as Input, level)) as MapTopology;\n byLevel.set(level, result);\n }\n return result;\n}\n\n/** TopoJSON 的经纬度范围 [西, 南, 东, 北]:有 bbox 用它,否则解出各段弧的坐标(量化的弧是逐点的差值) */\nexport function topologyBounds(\n topology: MapChartProps['topology'],\n): [number, number, number, number] {\n if (topology.bbox) {\n const [west, south, east, north] = topology.bbox;\n return [west, south, east, north];\n }\n const quantized = topology.transform;\n const [scaleX, scaleY] = quantized?.scale ?? [1, 1];\n const [translateX, translateY] = quantized?.translate ?? [0, 0];\n let [west, south, east, north] = [Infinity, Infinity, -Infinity, -Infinity];\n for (const arc of topology.arcs) {\n let x = 0;\n let y = 0;\n for (const position of arc) {\n x = quantized ? x + position[0]! : position[0]!;\n y = quantized ? y + position[1]! : position[1]!;\n const longitude = x * scaleX + translateX;\n const latitude = y * scaleY + translateY;\n west = Math.min(west, longitude);\n east = Math.max(east, longitude);\n south = Math.min(south, latitude);\n north = Math.max(north, latitude);\n }\n }\n return [west, south, east, north];\n}\n\n/** 地图 */\nexport const MapChart = _component(\n ({\n topology,\n feature,\n projection,\n center,\n areas = [],\n points = [],\n links = [],\n scheme = 'sequential',\n color = 'accent',\n divergingColors = ['danger', 'success'],\n midpoint = 0,\n bins,\n areaLabels = false,\n flow = false,\n valueFormat,\n unit,\n height = 400,\n zoomable = false,\n loading = false,\n empty,\n tooltip = true,\n onAreaClick,\n onPointClick,\n sx,\n ...rest\n }: MapChartProps) => {\n const lang = useLang();\n const format = useFormat();\n const bounds = _derived(topologyBounds(topology));\n const numbers = _derived(\n areas.flatMap((area) => (area.value === undefined ? [] : [toNumber(area.value)])),\n );\n const extent = _derived<[number, number] | null>(\n numbers.length ? [Math.min(...numbers), Math.max(...numbers)] : null,\n );\n const largest = (values: readonly { value?: NumericValue }[]) =>\n Math.max(0, ...values.map((item) => (item.value === undefined ? 0 : toNumber(item.value))));\n const valueText = (value: NumericValue | undefined) =>\n value === undefined\n ? lang.emptyValue\n : format.number(value, unit ? { ...valueFormat, suffix: unit } : valueFormat);\n const numberText = (value: number) => format.number(value, valueFormat);\n\n /** 数值 → 颜色:sequential 从 12% 到 100%;diverging 两头各自从分界往外加深;bins 时按档取 */\n function colorOf(value: number): string {\n const [low, high] = extent ?? [0, 0];\n if (scheme === 'diverging') {\n const [lowColor, highColor] = divergingColors.map((item) => resolveColor(item, 0));\n const reach = Math.max(midpoint - low, high - midpoint) || 1;\n let ratio = Math.min(Math.abs(value - midpoint) / reach, 1);\n if (bins) ratio = Math.max(Math.ceil(ratio * bins), 1) / bins;\n return tint(value < midpoint ? lowColor! : highColor!, 12 + ratio * 88);\n }\n let ratio = high === low ? 1 : (value - low) / (high - low);\n if (bins) ratio = Math.min(Math.floor(ratio * bins), bins - 1) / Math.max(bins - 1, 1);\n return tint(resolveColor(color, 0), 12 + ratio * 88);\n }\n const areaColor = (area: MapArea) =>\n area.color\n ? resolveColor(area.color, 0)\n : area.value === undefined\n ? undefined\n : colorOf(toNumber(area.value));\n\n /** 投影:预设按中心旋转;不写时按范围选 */\n function createProjection(): MapGeoProjection {\n if (projection && typeof projection !== 'string') return projection;\n const [west, south, east, north] = bounds;\n const [longitude, latitude] = center ?? [(west + east) / 2, (south + north) / 2];\n const kind = projection ?? (east - west > 180 ? 'naturalEarth' : 'conic');\n if (kind === 'conic')\n // 标准纬线取范围的 1/6 与 5/6 处(中国约是 25°、47°),中央经线是中心\n return MapProjection.ConicEqualArea()\n .rotate([-longitude, 0])\n .parallels([south + (north - south) / 6, north - (north - south) / 6]);\n if (kind === 'orthographic')\n return MapProjection.Orthographic().rotate([-longitude, -latitude]);\n const create =\n kind === 'mercator'\n ? MapProjection.Mercator\n : kind === 'equalEarth'\n ? MapProjection.EqualEarth\n : MapProjection.NaturalEarth1;\n return create().rotate([-longitude, 0]);\n }\n\n // Unovis 只在第一次画时按绘图区适配投影(之后变了大小也会),换上的新投影只沿用旧的比例与平移,地图会画歪、画小;\n // 所以投影的输入(预设、中心、范围、自己的投影)变了就换一个新的 TopoJSONMap,第一次画时由它自己适配\n let mapKey: unknown[] = [];\n let generation = 0;\n let mapProjection: MapGeoProjection | undefined;\n function updateProjection() {\n const key = [projection, center?.[0], center?.[1], ...bounds];\n if (key.some((item, index) => item !== mapKey[index])) {\n if (mapKey.length) {\n map?.destroy();\n generation += 1;\n }\n mapKey = key;\n mapProjection = createProjection();\n }\n }\n\n // Unovis 每次绘制都把整份 TopoJSON 投影成路径:自带的中国省份有 3.5 万个点,画在几百像素里大多看不出来。\n // 按绘图区里一像素对应的经纬度简化(三角形不到一平方像素的点去掉),绘制快一个数量级;\n // 能缩放时留到放大一倍也看不出折角\n function drawnTopology(): MapTopology {\n const width = plot?.clientWidth ?? 0;\n const height = plot?.clientHeight ?? 0;\n if (!width || !height) return topology;\n const [west, south, east, north] = bounds;\n const degreesPerPixel =\n Math.max((east - west) / width, (north - south) / height) / (zoomable ? 2 : 1);\n return simplifyTopology(topology, degreesPerPixel ** 2);\n }\n\n const pointOf = (id: string) => points.find((point) => point.id === id);\n /** Unovis 画连线时给的是 { source, target }(克隆过的地点),不是原来的流向:按两端的 id 找回 */\n const linkOf = (drawn: MapLink) => {\n const { source, target } = drawn as unknown as { source: MapPoint; target: MapPoint };\n return links.find((link) => link.from === source.id && link.to === target.id);\n };\n let map: TopoJSONMap<MapArea, MapPoint, MapLink> | undefined;\n let plot = _state.raw<HTMLElement | null>(null);\n\n const pointMax = _derived(largest(points));\n // 面积按数值比例:半径 3–8 px\n const radiusOf = (point: MapPoint) =>\n point.value === undefined || pointMax === 0\n ? 4\n : 3 + Math.sqrt(toNumber(point.value) / pointMax) * 5;\n\n let labelFrame = 0;\n /** 画完、缩放之后,下一帧重排地点的标签 */\n function scheduleLabels() {\n cancelAnimationFrame(labelFrame);\n labelFrame = requestAnimationFrame(layoutLabels);\n }\n _effect(() => () => cancelAnimationFrame(labelFrame));\n\n /**\n * 地点的标签:Unovis 的标签相撞时只会藏起来,这里用 placeLabels 挪到放得下的方位(挤时画引线),\n * 画在地点那一组里(跟着缩放、拖动);压在标签、地点上的区域名藏起来。\n * 按屏幕像素算:地点那一组的坐标乘缩放级别\n */\n function layoutLabels() {\n const root = map?.g.node();\n const group = root?.querySelector<SVGGElement>(`.${TopoJSONMap.selectors.points}`);\n const svg = group?.ownerSVGElement;\n if (!root || !group || !svg || !mapProjection) return;\n const projectionAt = mapProjection;\n const zoom = Number(svg.style.getPropertyValue('--vis-map-current-zoom-level')) || 1;\n const layer =\n group.querySelector<SVGGElement>(':scope > [data-point-labels]') ?? svgElement('g');\n layer.setAttribute('data-point-labels', '');\n layer.setAttribute('class', css.attrs(mapChartStyles.pointLabels).class ?? '');\n layer.style.fontSize = `${11 / zoom}px`;\n layer.style.strokeWidth = `${3 / zoom}px`;\n // 放在最后:之后加入的地点不会盖住标签\n group.append(layer);\n\n const items = points.flatMap((point) => {\n const position = projectionAt([point.longitude, point.latitude]);\n if (!position || !point.label) return [];\n const text = svgElement('text');\n text.textContent = point.label;\n text.setAttribute('text-anchor', 'middle');\n return [{ point, text, x: position[0] * zoom, y: position[1] * zoom }];\n });\n layer.replaceChildren(...items.map((item) => item.text));\n // 在原点量字形的框:中文字体的行高、基线的位置各浏览器不同,摆放时按量到的上沿对齐\n const glyphs = items.map((item) => item.text.getBBox());\n const anchors = items.map((item, index) => {\n const box = glyphs[index]!;\n return {\n x: item.x,\n y: item.y,\n radius: radiusOf(item.point),\n // 四周留出描边(1.5 px)与一点空隙;Firefox 量到的框比字形的墨迹窄一点\n width: box.width * zoom + labelPadding * 2,\n height: box.height * zoom + labelPadding * 2,\n priority: item.point.value === undefined ? 0 : toNumber(item.point.value),\n };\n });\n\n const areaTexts = [\n ...root.querySelectorAll<SVGTextElement>(`text.${TopoJSONMap.selectors.areaLabel}`),\n ].filter((text) => text.getAttribute('visibility') !== 'hidden');\n const areaBoxes = areaTexts.map((text): LabelRect => {\n text.style.display = '';\n const { e, f } = text.transform.baseVal.consolidate()?.matrix ?? { e: 0, f: 0 };\n const box = text.getBBox();\n return {\n x: (e + box.x) * zoom,\n y: (f + box.y) * zoom,\n width: box.width * zoom,\n height: box.height * zoom,\n };\n });\n // 没放大时整张图在绘图区里:标签也不出界;放大后本来就只看得到一部分\n const bounds =\n zoom === 1 ? { x: 0, y: 0, width: svg.clientWidth, height: svg.clientHeight } : undefined;\n const placements = placeLabels(anchors, { bounds, soft: areaBoxes });\n\n const taken: LabelRect[] = anchors.map((anchor) => ({\n x: anchor.x - anchor.radius,\n y: anchor.y - anchor.radius,\n width: anchor.radius * 2,\n height: anchor.radius * 2,\n }));\n placements.forEach((placement, index) => {\n const { text } = items[index]!;\n if (!placement) {\n text.remove();\n return;\n }\n const { box, leader } = placement;\n taken.push(box);\n text.setAttribute('x', String((box.x + box.width / 2) / zoom));\n text.setAttribute('y', String((box.y + labelPadding) / zoom - glyphs[index]!.y));\n if (leader) layer.insertBefore(leaderLine(anchors[index]!, box, zoom), text);\n });\n areaTexts.forEach((text, index) => {\n if (taken.some((rect) => rectsOverlap(rect, areaBoxes[index]!)))\n text.style.display = 'none';\n });\n }\n\n /** 引线:从标记的边到标签矩形上离标记最近的点 */\n function leaderLine(\n anchor: { x: number; y: number; radius: number },\n box: LabelRect,\n zoom: number,\n ) {\n const toX = Math.min(Math.max(anchor.x, box.x), box.x + box.width);\n const toY = Math.min(Math.max(anchor.y, box.y), box.y + box.height);\n const length = Math.hypot(toX - anchor.x, toY - anchor.y) || 1;\n const line = svgElement('line');\n line.setAttribute('class', css.attrs(mapChartStyles.leader).class ?? '');\n line.setAttribute(\n 'x1',\n String((anchor.x + ((toX - anchor.x) / length) * anchor.radius) / zoom),\n );\n line.setAttribute(\n 'y1',\n String((anchor.y + ((toY - anchor.y) / length) * anchor.radius) / zoom),\n );\n line.setAttribute('x2', String(toX / zoom));\n line.setAttribute('y2', String(toY / zoom));\n line.style.strokeWidth = `${1 / zoom}px`;\n return line;\n }\n const chart: SingleChart = useSingleChart<MapGraphData<MapArea, MapPoint, MapLink>>(() => ({\n element: plot,\n ready: !loading,\n tooltip,\n build: (instance) => {\n const linkMax = largest(links);\n updateProjection();\n map = instance(`map-${generation}`, () => {\n const created = new TopoJSONMap<MapArea, MapPoint, MapLink>();\n // 热力模式的滤镜是写死的 id=\"heatmapFilter\",一页多张地图时 id 重复;不用热力模式,去掉\n created.g.select('filter#heatmapFilter').remove();\n // 缩放时 Unovis 把缩放级别写到 svg 的 style 上:跟着重排标签(拖动只是平移,标签随地点那一组走)\n const observer = new MutationObserver(scheduleLabels);\n queueMicrotask(() => {\n const svg = created.g.node()?.parentElement;\n if (svg) observer.observe(svg, { attributes: true, attributeFilter: ['style'] });\n });\n const destroy = created.destroy.bind(created);\n created.destroy = () => {\n observer.disconnect();\n destroy();\n };\n return created;\n });\n map.setConfig({\n topojson: drawnTopology(),\n mapFeatureName: feature,\n projection: mapProjection,\n disableZoom: !zoomable,\n areaId: (area) => area.id,\n areaColor,\n areaLabel: areaLabels ? (area) => area.label : undefined,\n areaCursor: onAreaClick ? () => 'pointer' : undefined,\n pointId: (point) => point.id,\n longitude: (point) => point.longitude,\n latitude: (point) => point.latitude,\n pointColor: (point) => resolveColor(point.color ?? 'danger', 0),\n pointRadius: radiusOf,\n pointShape: (point) => point.shape ?? 'circle',\n pointCursor: onPointClick ? () => 'pointer' : undefined,\n // 名字由 layoutLabels 自己画(pointLabel 写在点里面,pointBottomLabel 相撞时只会藏起来)\n pointLabel: () => '',\n pointBottomLabel: () => '',\n // 两端给 id:Unovis 克隆了地点,按对象找不到\n linkSource: (link) => link.from,\n linkTarget: (link) => link.to,\n linkColor: (drawn) => resolveColor(linkOf(drawn)?.color ?? 'neutral', 0),\n linkWidth: (drawn) => {\n const value = linkOf(drawn)?.value;\n return value === undefined || linkMax === 0 ? 1.5 : 1 + (toNumber(value) / linkMax) * 4;\n },\n enableFlowAnimation: flow,\n // 流动的粒子按原来的流向画,两端的经纬度直接给;起点已经有地点的标记,不再加一个\n sourceLongitude: (link) => pointOf(link.from)?.longitude,\n sourceLatitude: (link) => pointOf(link.from)?.latitude,\n targetLongitude: (link) => pointOf(link.to)?.longitude,\n targetLatitude: (link) => pointOf(link.to)?.latitude,\n sourcePointRadius: 0,\n flowParticleColor: (link) => resolveColor(link.color ?? 'accent', 0),\n flowParticleRadius: 2,\n // 每经度 0.15 个粒子:默认的 0.6 太密,连成一条线盖住了连线\n flowParticleDensity: 0.15,\n events: {\n [TopoJSONMap.selectors.feature]: {\n click: (shape: { data?: MapArea }) => {\n if (shape.data) onAreaClick?.(shape.data);\n },\n },\n [TopoJSONMap.selectors.point]: {\n click: (point: MapPoint) => onPointClick?.(point),\n },\n },\n });\n return {\n component: map,\n onRender: scheduleLabels,\n data: {\n areas: [...areas],\n points: [...points],\n links: links.filter((link) => pointOf(link.from) && pointOf(link.to)),\n },\n triggers: {\n [TopoJSONMap.selectors.feature]: (shape: { data?: MapArea }) =>\n shape.data\n ? chart.tooltip(\n chartTooltip(shape.data.label, [\n {\n label: lang.chartValue,\n color: areaColor(shape.data) ?? 'transparent',\n value: valueText(shape.data.value),\n },\n ]),\n )\n : undefined,\n [TopoJSONMap.selectors.point]: (point: MapPoint) =>\n chart.tooltip(\n chartTooltip(point.label, [\n {\n label: lang.chartValue,\n color: resolveColor(point.color ?? 'danger', 0),\n value: valueText(point.value),\n },\n ]),\n ),\n },\n };\n },\n }));\n\n /** 图例:分档时每档一个色块与范围,连续时一条色带两端写最小最大 */\n function legend() {\n if (!extent || areas.every((area) => area.color)) return null;\n const [low, high] = extent;\n if (bins) {\n const step = (high - low) / bins;\n return (\n <div {...css.attrs(mapChartStyles.legend)} aria-hidden=\"true\">\n {Array.from({ length: bins }, (_, index) => {\n const from = low + step * index;\n const to = index === bins - 1 ? high : from + step;\n return (\n <span key={index} {...css.attrs(mapChartStyles.bin)}>\n <span\n {...css.attrs(\n mapChartStyles.swatch,\n mapChartStyles.swatchColor(colorOf((from + to) / 2)),\n )}\n />\n {numberText(from)} – {numberText(to)}\n </span>\n );\n })}\n </div>\n );\n }\n const stops =\n scheme === 'diverging'\n ? [colorOf(low), colors.fill, colorOf(high)]\n : [colorOf(low), colorOf(high)];\n return (\n <div {...css.attrs(mapChartStyles.legend)} aria-hidden=\"true\">\n <span>{numberText(low)}</span>\n <span\n {...css.attrs(\n mapChartStyles.ramp,\n mapChartStyles.rampColors(`linear-gradient(to right, ${stops.join(', ')})`),\n )}\n />\n <span>{numberText(high)}</span>\n </div>\n );\n }\n\n // 滚轮默认滚动页面,按住 Ctrl(或 ⌘、触控板捏合)才缩放地图(同 Google 地图的 cooperative 手势):\n // 否则滚动页面经过地图时会把地图缩小。拦下的滚轮在顶栏提示一下\n let wheelHint = _state(false);\n let hintTimer: ReturnType<typeof setTimeout> | undefined;\n useEventListener(\n () => (zoomable ? plot : null),\n 'wheel',\n (event) => {\n if (event.ctrlKey || event.metaKey) return;\n event.stopPropagation();\n wheelHint = true;\n clearTimeout(hintTimer);\n hintTimer = setTimeout(() => (wheelHint = false), 1500);\n },\n { capture: true },\n );\n _effect(() => () => clearTimeout(hintTimer));\n\n /** 缩放按钮:放大、缩小、复位;前面是滚轮的提示 */\n const zoomButtons = () => (\n <span {...css.attrs(mapChartStyles.zoom)}>\n {wheelHint && (\n <span {...css.attrs(mapChartStyles.wheelHint)} role=\"status\">\n {lang.chartZoomWheelHint}\n </span>\n )}\n {(\n [\n [Plus, lang.chartZoomIn, () => map?.zoomIn()],\n [Minus, lang.chartZoomOut, () => map?.zoomOut()],\n [Maximize, lang.chartZoomFit, () => map?.fitView()],\n ] as const\n ).map(([icon, label, action]) => (\n <IconButton\n key={label}\n icon={icon}\n size=\"sm\"\n variant=\"ghost\"\n tone=\"neutral\"\n aria-label={label}\n onClick={action}\n />\n ))}\n </span>\n );\n\n return () => (\n <ChartFrame\n {...rest}\n sx={[mapChartStyles.root, sx]}\n unit={unit}\n height={height}\n legend={[]}\n hiddenKeys={[]}\n onLegendToggle={() => {}}\n loading={loading}\n skeleton={<Skeleton sx={mapChartStyles.skeleton} />}\n isEmpty={false}\n empty={empty}\n actions={zoomable ? zoomButtons() : undefined}\n footer={legend()}\n table={{\n columns: [lang.chartCategory, unit ? `${lang.chartValue}(${unit})` : lang.chartValue],\n rows: [\n ...areas.map((area) => ({ header: area.label, value: area.value })),\n ...points.map((point) => ({ header: point.label, value: point.value })),\n ...links.map((link) => ({\n header: lang.chartFlowLabel(\n pointOf(link.from)?.label ?? link.from,\n pointOf(link.to)?.label ?? link.to,\n ),\n value: link.value,\n })),\n ].map((row) => ({\n header: row.header,\n cells: [\n row.value === undefined ? lang.emptyValue : format.number(row.value, valueFormat),\n ],\n })),\n }}\n plotRef={(element) => (plot = element)}\n />\n );\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MapChart.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_vue_computed","_vue_ref","_createVNode","_mergeProps","_createTextVNode"],"sources":["../../src/charts/MapChart.tsx"],"sourcesContent":["/**\n * 地图:按区域着色(分省的销售额、各国的采购额),标出地点(工厂、供应商)与它们之间的流向。\n * 地理数据是 TopoJSON:`@zerodep-dev/vue-tsx-pro-ui/maps` 带着中国省份与世界各国,也可以用自己的。\n *\n * import { chinaProvinces } from '@zerodep-dev/vue-tsx-pro-ui/maps';\n * <MapChart\n * aria-label=\"各省销售额\"\n * topology={chinaProvinces}\n * feature=\"provinces\"\n * areas={[{ id: 'CN-JS', label: '江苏', value: 623 }, …]} // id 是地图要素的 id\n * points={[{ id: 'sh', label: '上海组装', longitude: 121.47, latitude: 31.23, value: 860 }]}\n * links={[{ from: 'xa', to: 'sh', value: 120 }]}\n * bins={5}\n * areaLabels\n * />\n *\n * 投影(见 createProjection):默认按地理数据的范围选——一个国家、一个地区用以它为中心的等积圆锥投影\n * (中国地图常用的 Albers,正着、不歪),跨了大半个地球时用 Natural Earth;也可以指定 mercator、equalEarth、\n * equirectangular、orthographic(地球仪)或自己的投影函数(d3-geo 的投影可以直接传)。\n * 地理数据先按绘图区的像素简化(看不出的点去掉),再投影、按绘图区缩放居中。\n *\n * 着色:sequential(默认)按数值深浅;diverging 以 midpoint 为界两头两种颜色(同比的涨跌);\n * bins 分成几档(分级着色,图例是几个色块),不写时连续着色(图例是色带);区域写了 color 时按它(分类着色)。\n * 没有数据的区域是底色。地点:value 决定大小(面积按比例),color、shape 决定颜色与形状;名字自动避让\n * (换方位、挤时往外退并画引线,数值大的先放,放不下的悬停看;压住名字、地点的区域名藏起来);\n * links 是地点之间的流向,粗细按 value,flow 时有流动的粒子(“减少动态效果”时不播)。\n * zoomable 时可以拖动、按住 Ctrl 滚轮缩放,右上角有放大、缩小、复位的按钮;缩放时区域放大,地点与文字保持原来的大小。\n * 悬停看名称与数值;读屏的数据表列出各区域、地点与流向。\n */\nimport { Maximize, Minus, Plus } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { shallowRef, type VNodeChild } from 'vue';\nimport { IconButton } from '../base/IconButton';\nimport { useLang } from '../config/context';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { colors, t } from '../config/theme/tokens';\nimport { Skeleton } from '../feedback/Skeleton';\nimport { svgNumber } from '../utils/data/number';\nimport { toNumber, type NumericValue } from '../utils/data/numeric';\nimport { useReducedMotion } from '../utils/dom/media-query';\nimport { usePanZoom } from '../utils/dom/pan-zoom';\nimport type { PartProps } from '../utils/props';\nimport { chartTooltip, ChartFrame, type ChartFrameParts } from './frame';\nimport { createProjection, type MapGeoProjection, type MapProjectionName } from './geo/projection';\nimport {\n simplifyTopology,\n topologyBounds,\n topologyFeatures,\n type MapTopology,\n} from './geo/topojson';\nimport { placeLabels, rectsOverlap, type LabelRect } from './label-layout';\nimport { ChartTooltipBox, chartSvgStyles, pointerIn, usePlotArea, type ChartTip } from './plot';\nimport { resolveColor, type ChartColor } from './series';\nimport { estimateTextWidth } from './text-size';\n\n/** 一个区域的数据 */\nexport interface MapArea {\n /** 地图要素的 id(中国省份是 'CN-JS' 这样的写法,世界各国是 ISO 两位代码) */\n id: string;\n /** 显示的名称:提示框、区域名、数据表 */\n label: string;\n /** 数值:决定颜色 */\n value?: NumericValue;\n /** 指定颜色:不按数值着色(分类着色,如所属大区) */\n color?: ChartColor;\n}\n\n/** 一个地点 */\nexport interface MapPoint {\n /** 标识:流向的 from、to 指向它 */\n id: string;\n /** 名称:写在点旁边 */\n label: string;\n /** 经度 */\n longitude: number;\n /** 纬度 */\n latitude: number;\n /** 数值:决定点的大小(面积按比例),也显示在提示框 */\n value?: NumericValue;\n /** 颜色,默认 danger */\n color?: ChartColor;\n /** 形状,默认 circle */\n shape?: 'circle' | 'square' | 'triangle';\n}\n\n/** 两个地点之间的流向 */\nexport interface MapLink {\n /** 起点(地点的 id) */\n from: string;\n /** 终点(地点的 id) */\n to: string;\n /** 数值:决定线的粗细,也显示在数据表 */\n value?: NumericValue;\n /** 颜色,默认次要色 */\n color?: ChartColor;\n}\n\n/** 投影的预设 */\nexport interface MapProjections {\n /** 等积圆锥(Albers):以数据为中心,一个国家、一个地区用它(中国地图常用),正着、面积不失真 */\n conic: unknown;\n /** 墨卡托:网页地图常见,高纬度会放大 */\n mercator: unknown;\n /** Natural Earth:世界地图,形状与面积都比较自然 */\n naturalEarth: unknown;\n /** Equal Earth:世界地图,面积准确 */\n equalEarth: unknown;\n /** 等距圆柱:经纬度直接当横纵坐标,经纬网是方格 */\n equirectangular: unknown;\n /** 正射(地球仪):以数据为中心看半个地球 */\n orthographic: unknown;\n}\n\n/** 未声明的属性落到外层 div(role=\"figure\")上;aria-label 是图表的名称 */\nexport interface MapChartProps extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {\n /** 地理数据(TopoJSON),如 `@zerodep-dev/vue-tsx-pro-ui/maps` 的 chinaProvinces、worldCountries */\n topology: MapTopology;\n /** 画哪一组要素(TopoJSON 的 objects 里的名字),如中国省份是 'provinces'、世界是 'countries' */\n feature: string;\n /** 投影:预设的名字,或自己的投影函数([经度, 纬度] → [x, y]);不写时按数据的范围选 conic 或 naturalEarth */\n projection?: keyof MapProjections | MapGeoProjection;\n /** 投影的中心 [经度, 纬度]:中央经线(世界地图写 [150, 0] 以太平洋为中心),orthographic 还用纬度;不写时取地理数据范围的中心 */\n center?: readonly [number, number];\n /** 各区域的数值 */\n areas?: readonly MapArea[];\n /** 地点 */\n points?: readonly MapPoint[];\n /** 地点之间的流向 */\n links?: readonly MapLink[];\n /** 着色方式:sequential 按数值深浅(默认),diverging 以 midpoint 为界两头两种颜色 */\n scheme?: 'sequential' | 'diverging';\n /** sequential 的基色,默认 accent */\n color?: ChartColor;\n /** diverging 的两头 [低, 高],默认 ['danger', 'success'] */\n divergingColors?: readonly [ChartColor, ChartColor];\n /** diverging 的分界,默认 0 */\n midpoint?: number;\n /** 分成几档(分级着色);不写时连续着色 */\n bins?: number;\n /** 在区域上写名字(区域够大时) */\n areaLabels?: boolean;\n /** 流向上有流动的粒子 */\n flow?: boolean;\n /** 数值的格式 */\n valueFormat?: NumericFormat;\n /** 单位:显示在左上方,提示框与数据表的数值后面带上 */\n unit?: string;\n /**\n * 绘图区的高度;数字按 px\n * @default 400\n */\n height?: number | string;\n /** 可以拖动、按住 Ctrl 滚轮缩放,右上角有放大、缩小、复位的按钮;默认关(不抢页面的滚动) */\n zoomable?: boolean;\n /** 加载中:绘图区显示骨架 */\n loading?: boolean;\n /** 没有数据时显示的内容 */\n empty?: VNodeChild;\n /** 悬停时的提示框,默认 true */\n tooltip?: boolean;\n /** 点了一个有数据的区域 */\n onAreaClick?: (area: MapArea) => void;\n /** 点了一个地点 */\n onPointClick?: (point: MapPoint) => void;\n}\n\n/** MapChart 的样式 */\nexport const mapChartStyles = css.create({\n skeleton: { display: 'block', width: '100%', height: '100%' },\n viewport: { position: 'absolute', inset: 0 },\n // 地图跟随主题:底色、边界是表面色;缩放时边界不跟着变粗\n feature: {\n stroke: '_surface',\n strokeWidth: 0.8,\n fillRule: 'evenodd',\n transition: `fill ${t.durations.md} ${t.easings.standard}`,\n },\n featureHover: {\n fill: 'none',\n stroke: '_text',\n strokeWidth: 1.5,\n pointerEvents: 'none',\n },\n sphere: { fill: '_surfaceMuted', stroke: '_border', strokeWidth: 1 },\n link: { fill: 'none', strokeOpacity: 0.7, strokeLinecap: 'round', pointerEvents: 'none' },\n particle: { pointerEvents: 'none' },\n point: { stroke: '_surface', strokeWidth: 1.5 },\n clickable: { cursor: 'pointer' },\n // 地点的名字:描一圈表面色的边,压在区域、连线上也看得清\n pointLabel: { fill: '_text', fontSize: '11px', fontWeight: '_semibold' },\n areaLabel: { fill: '_text', fontSize: '10px' },\n leader: { stroke: '_textMuted', strokeWidth: 1 },\n // 缩放按钮:在标题行的结束边(导出菜单前面)\n zoom: { display: 'inline-flex', alignItems: 'center', gap: '2px', marginInlineStart: 'auto' },\n wheelHint: { marginInlineEnd: '_sm', color: '_textMuted', fontSize: '_xs' },\n // 图例:连续是色带,分档是一排色块\n legend: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n columnGap: '_md',\n rowGap: '_xs',\n fontSize: '_xs',\n color: '_textMuted',\n paddingInline: '_sm',\n },\n ramp: { flexGrow: 1, maxWidth: '16rem', height: '0.5rem', borderRadius: '_full' },\n rampColors: (gradient: string) => ({ backgroundImage: gradient }),\n bin: { display: 'inline-flex', alignItems: 'center', gap: '0.375em', whiteSpace: 'nowrap' },\n swatch: { width: '0.875rem', height: '0.625rem', borderRadius: '2px' },\n swatchColor: (color: string) => ({ backgroundColor: color }),\n});\n\n/** 地点名字的字号、区域名的字号(px) */\nconst POINT_FONT = 11;\nconst AREA_FONT = 10;\n/** 地点的名字四周留的空(px) */\nconst LABEL_PADDING = 3;\n/** 地图与绘图区边缘的距离(px) */\nconst FIT_PADDING = 8;\n\n/** 混色:基色占 percent,其余透明(落在底色上) */\nconst tint = (color: string, percent: number) =>\n `color-mix(in srgb, ${color} ${Math.round(percent)}%, transparent)`;\n\n/** 一组环写成路径;坐标保留一位小数(像素) */\nfunction ringsPath(rings: readonly (readonly (readonly [number, number])[])[]): string {\n const round = (value: number) => Math.round(value * 10) / 10;\n return rings\n .map((ring) => `M${ring.map(([x, y]) => `${round(x)},${round(y)}`).join('L')}Z`)\n .join('');\n}\n\n/** 地点的标记:中心在 (x, y)、半径 r 的路径 */\nfunction markerPath(shape: MapPoint['shape'], x: number, y: number, r: number): string {\n const [cx, cy] = [svgNumber(x), svgNumber(y)];\n if (shape === 'square') {\n const half = svgNumber(r * 0.9);\n return `M${cx - half},${cy - half}h${half * 2}v${half * 2}h${-half * 2}Z`;\n }\n if (shape === 'triangle') {\n const h = svgNumber(r * 1.15);\n return `M${cx},${svgNumber(cy - h)}L${svgNumber(cx + h)},${svgNumber(cy + h * 0.75)}L${svgNumber(cx - h)},${svgNumber(cy + h * 0.75)}Z`;\n }\n return `M${svgNumber(cx - r)},${cy}A${r},${r},0,1,1,${svgNumber(cx + r)},${cy}A${r},${r},0,1,1,${svgNumber(cx - r)},${cy}Z`;\n}\n\n/** 悬停的区域或地点 */\ninterface MapHover {\n kind: 'feature' | 'point';\n index: number;\n x: number;\n y: number;\n}\n\n/** 地图 */\nexport const MapChart = _component(\n ({\n topology,\n feature,\n projection,\n center,\n areas = [],\n points = [],\n links = [],\n scheme = 'sequential',\n color = 'accent',\n divergingColors = ['danger', 'success'],\n midpoint = 0,\n bins,\n areaLabels = false,\n flow = false,\n valueFormat,\n unit,\n height = 400,\n zoomable = false,\n loading = false,\n empty,\n tooltip = true,\n onAreaClick,\n onPointClick,\n ...rest\n }: MapChartProps) => {\n const lang = useLang();\n const format = useFormat();\n const area = usePlotArea();\n const reducedMotion = useReducedMotion();\n const viewport = shallowRef<HTMLElement | null>(null);\n let hovered = _state.raw<MapHover | null>(null);\n const bounds = _derived(topologyBounds(topology));\n const numbers = _derived(\n areas.flatMap((item) => (item.value === undefined ? [] : [toNumber(item.value)])),\n );\n const extent = _derived<[number, number] | null>(\n numbers.length ? [Math.min(...numbers), Math.max(...numbers)] : null,\n );\n const largest = (values: readonly { value?: NumericValue }[]) =>\n Math.max(0, ...values.map((item) => (item.value === undefined ? 0 : toNumber(item.value))));\n const valueText = (value: NumericValue | undefined) =>\n value === undefined\n ? lang.emptyValue\n : format.number(value, unit ? { ...valueFormat, suffix: unit } : valueFormat);\n const numberText = (value: number) => format.number(value, valueFormat);\n const areaById = _derived(new Map(areas.map((item) => [item.id, item])));\n const pointById = _derived(new Map(points.map((point) => [point.id, point])));\n\n /** 数值 → 颜色:sequential 从 12% 到 100%;diverging 两头各自从分界往外加深;bins 时按档取 */\n function colorOf(value: number): string {\n const [low, high] = extent ?? [0, 0];\n if (scheme === 'diverging') {\n const [lowColor, highColor] = divergingColors.map((item) => resolveColor(item, 0));\n const reach = Math.max(midpoint - low, high - midpoint) || 1;\n let ratio = Math.min(Math.abs(value - midpoint) / reach, 1);\n if (bins) ratio = Math.max(Math.ceil(ratio * bins), 1) / bins;\n return tint(value < midpoint ? lowColor! : highColor!, 12 + ratio * 88);\n }\n let ratio = high === low ? 1 : (value - low) / (high - low);\n if (bins) ratio = Math.min(Math.floor(ratio * bins), bins - 1) / Math.max(bins - 1, 1);\n return tint(resolveColor(color, 0), 12 + ratio * 88);\n }\n const areaColor = (item: MapArea | undefined) =>\n !item\n ? undefined\n : item.color\n ? resolveColor(item.color, 0)\n : item.value === undefined\n ? undefined\n : colorOf(toNumber(item.value));\n\n const pointMax = _derived(largest(points));\n // 面积按数值比例:半径 3–8 px\n const radiusOf = (point: MapPoint) =>\n point.value === undefined || pointMax === 0\n ? 4\n : 3 + Math.sqrt(toNumber(point.value) / pointMax) * 5;\n\n // 滚轮默认滚动页面,按住 Ctrl(或 ⌘、触控板捏合)才缩放地图(同 Google 地图的 cooperative 手势):\n // 否则滚动页面经过地图时会把地图缩小。拦下的滚轮在顶栏提示一下\n let wheelHint = _state(false);\n let hintTimer: ReturnType<typeof setTimeout> | undefined;\n _effect(() => () => clearTimeout(hintTimer));\n const view = usePanZoom({\n viewport: () => viewport.value,\n min: 1,\n max: 12,\n step: 1.5,\n disabled: () => !zoomable,\n filter: (event) => {\n if (event instanceof WheelEvent && !event.ctrlKey && !event.metaKey) {\n wheelHint = true;\n clearTimeout(hintTimer);\n hintTimer = setTimeout(() => (wheelHint = false), 1500);\n return false;\n }\n return true;\n },\n });\n\n /** 投影:预设按中心旋转;不写时按范围选 */\n const projector = _derived.by(() => {\n const [west, south, east, north] = bounds;\n const middle = center ?? [(west + east) / 2, (south + north) / 2];\n const name: MapProjectionName | MapGeoProjection =\n projection ?? (east - west > 180 ? 'naturalEarth' : 'conic');\n return createProjection(name, { center: middle, bounds });\n });\n\n /**\n * 区域的路径:按绘图区里一像素对应的经纬度简化(三角形不到一平方像素的点去掉;能缩放时留到放大一倍也看不出折角),\n * 投影后按绘图区缩放、居中。地点、连线用同一个换算(toScreen)\n */\n const geometry = _derived.by(() => {\n const { width, height: plotHeight } = area;\n const [west, south, east, north] = bounds;\n const degreesPerPixel =\n width && plotHeight\n ? Math.max((east - west) / width, (north - south) / plotHeight) / (zoomable ? 2 : 1)\n : 0;\n const features = topologyFeatures(simplifyTopology(topology, degreesPerPixel ** 2), feature);\n const projected = features.map((item) => ({\n feature: item,\n // 简化后只剩一两个点的环(很小的岛)画不出来,也不能算进适配的范围,否则地图四周留空\n rings: item.polygons\n .flatMap((polygon) => projector.polygon(polygon))\n .filter((ring) => ring.length > 2),\n }));\n let [x0, y0, x1, y1] = [Infinity, Infinity, -Infinity, -Infinity];\n for (const item of projected)\n for (const ring of item.rings)\n for (const [x, y] of ring) {\n x0 = Math.min(x0, x);\n x1 = Math.max(x1, x);\n y0 = Math.min(y0, y);\n y1 = Math.max(y1, y);\n }\n const fits = Number.isFinite(x0) && x1 > x0 && y1 > y0;\n const k = fits\n ? Math.min(\n (width - FIT_PADDING * 2) / (x1 - x0),\n (plotHeight - FIT_PADDING * 2) / (y1 - y0),\n )\n : 1;\n const tx = fits ? (width - (x1 - x0) * k) / 2 - x0 * k : 0;\n const ty = fits ? (plotHeight - (y1 - y0) * k) / 2 - y0 * k : 0;\n const toScreen = ([x, y]: readonly [number, number]): [number, number] => [\n x * k + tx,\n y * k + ty,\n ];\n return {\n toScreen,\n sphere: projector.sphere && {\n ...projector.sphere,\n cx: tx,\n cy: ty,\n r: projector.sphere.r * k,\n },\n shapes: projected.map((item) => {\n const screen = item.rings.map((ring) => ring.map(toScreen));\n // 区域名写在最大的那一块的外接矩形中心\n let best: { box: LabelRect; size: number } | undefined;\n for (const ring of screen) {\n const xs = ring.map(([x]) => x);\n const ys = ring.map(([, y]) => y);\n const box = {\n x: Math.min(...xs),\n y: Math.min(...ys),\n width: Math.max(...xs) - Math.min(...xs),\n height: Math.max(...ys) - Math.min(...ys),\n };\n if (!best || box.width * box.height > best.size)\n best = { box, size: box.width * box.height };\n }\n return { id: item.feature.id, d: ringsPath(screen), box: best?.box };\n }),\n };\n });\n\n /** 缩放后屏幕上的位置:地点、连线、文字不随缩放变大,只跟着移动 */\n const zoomed = ([x, y]: readonly [number, number]): [number, number] => [\n x * view.scale + view.x,\n y * view.scale + view.y,\n ];\n\n /** 地点在屏幕上的位置;看不见(地球背面)的不画 */\n const placedPoints = _derived.by(() =>\n points.flatMap((point, index) => {\n const projected = projector.point([point.longitude, point.latitude]);\n if (!projected) return [];\n const [x, y] = zoomed(geometry.toScreen(projected));\n return [{ point, index, x, y, r: radiusOf(point) }];\n }),\n );\n\n /** 地点的名字:placeLabels 挪到放得下的方位(挤时画引线);压住名字、地点的区域名藏起来 */\n const labels = _derived.by(() => {\n const anchors = placedPoints.map((item) => ({\n x: item.x,\n y: item.y,\n radius: item.r,\n width: estimateTextWidth(item.point.label, POINT_FONT) + LABEL_PADDING * 2,\n height: POINT_FONT * 1.25 + LABEL_PADDING * 2,\n priority: item.point.value === undefined ? 0 : toNumber(item.point.value),\n }));\n const areaBoxes = areaLabels\n ? geometry.shapes.flatMap((shape) => {\n const info = areaById.get(shape.id);\n if (!info || !shape.box) return [];\n const width = estimateTextWidth(info.label, AREA_FONT);\n const box = {\n x: shape.box.x * view.scale + view.x,\n y: shape.box.y * view.scale + view.y,\n width: shape.box.width * view.scale,\n height: shape.box.height * view.scale,\n };\n // 区域放不下名字时不写\n if (box.width < width + 4 || box.height < AREA_FONT + 4) return [];\n const rect = {\n x: box.x + box.width / 2 - width / 2,\n y: box.y + box.height / 2 - AREA_FONT / 2,\n width,\n height: AREA_FONT,\n };\n return [{ label: info.label, rect }];\n })\n : [];\n // 没放大时整张图在绘图区里:名字也不出界;放大后本来就只看得到一部分\n const placements = placeLabels(anchors, {\n bounds:\n view.scale === 1 ? { x: 0, y: 0, width: area.width, height: area.height } : undefined,\n soft: areaBoxes.map((item) => item.rect),\n });\n const taken: LabelRect[] = anchors.map((anchor) => ({\n x: anchor.x - anchor.radius,\n y: anchor.y - anchor.radius,\n width: anchor.radius * 2,\n height: anchor.radius * 2,\n }));\n for (const placement of placements) if (placement) taken.push(placement.box);\n return {\n points: placements.map((placement, index) => ({\n placement,\n anchor: anchors[index]!,\n item: placedPoints[index]!,\n })),\n areas: areaBoxes.filter((item) => !taken.some((rect) => rectsOverlap(rect, item.rect))),\n };\n });\n\n /** 连线:两个地点之间往上拱起的弧,粗细按数值 */\n const linkShapes = _derived.by(() => {\n const linkMax = largest(links);\n const byId = new Map(placedPoints.map((item) => [item.point.id, item]));\n return links.flatMap((link, index) => {\n const from = byId.get(link.from);\n const to = byId.get(link.to);\n if (!from || !to) return [];\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const length = Math.hypot(dx, dy) || 1;\n // 法线朝上的那一侧:弧往上拱\n const [nx, ny] = dx >= 0 ? [dy / length, -dx / length] : [-dy / length, dx / length];\n const bend = length * 0.2;\n const cx = (from.x + to.x) / 2 + nx * bend;\n const cy = (from.y + to.y) / 2 + ny * bend;\n return [\n {\n link,\n index,\n length,\n d: `M${svgNumber(from.x)},${svgNumber(from.y)}Q${svgNumber(cx)},${svgNumber(cy)},${svgNumber(to.x)},${svgNumber(to.y)}`,\n width:\n link.value === undefined || linkMax === 0\n ? 1.5\n : 1 + (toNumber(link.value) / linkMax) * 4,\n },\n ];\n });\n });\n\n function onPointermove(event: PointerEvent) {\n const target = (event.target as Element).closest?.('[data-feature],[data-point]');\n if (!target) {\n hovered = null;\n return;\n }\n const { x, y } = pointerIn(event, viewport.value ?? (event.currentTarget as Element));\n const point = target.getAttribute('data-point');\n hovered =\n point === null\n ? { kind: 'feature', index: Number(target.getAttribute('data-feature')), x, y }\n : { kind: 'point', index: Number(point), x, y };\n }\n\n function onClick(event: MouseEvent) {\n const target = (event.target as Element).closest?.('[data-feature],[data-point]');\n if (!target) return;\n const point = target.getAttribute('data-point');\n if (point !== null) {\n onPointClick?.(points[Number(point)]!);\n return;\n }\n const shape = geometry.shapes[Number(target.getAttribute('data-feature'))];\n const info = shape && areaById.get(shape.id);\n if (info) onAreaClick?.(info);\n }\n\n function renderPlot() {\n const { width, height: plotHeight } = area;\n const { shapes, sphere } = geometry;\n const current = hovered;\n const hoveredShape = current?.kind === 'feature' ? shapes[current.index] : undefined;\n return (\n <svg width={width} height={plotHeight} {...css.attrs(chartSvgStyles.svg)} onClick={onClick}>\n <g\n data-part=\"features\"\n transform={`translate(${svgNumber(view.x)} ${svgNumber(view.y)}) scale(${svgNumber(view.scale)})`}\n {...css.attrs(chartSvgStyles.fadeIn)}\n >\n {sphere && (\n <circle\n cx={sphere.cx}\n cy={sphere.cy}\n r={sphere.r}\n {...css.attrs(mapChartStyles.sphere)}\n />\n )}\n {shapes.map((shape, index) => {\n const info = areaById.get(shape.id);\n return (\n <path\n key={`${shape.id}:${index}`}\n data-part=\"feature\"\n data-feature={index}\n d={shape.d}\n vector-effect=\"non-scaling-stroke\"\n {...css.attrs(\n mapChartStyles.feature,\n chartSvgStyles.fill(areaColor(info) ?? colors.fill),\n info && onAreaClick && mapChartStyles.clickable,\n )}\n />\n );\n })}\n {hoveredShape && (\n <path\n d={hoveredShape.d}\n vector-effect=\"non-scaling-stroke\"\n {...css.attrs(mapChartStyles.featureHover)}\n />\n )}\n </g>\n <g data-part=\"links\">\n {linkShapes.map((shape) => {\n const tone = resolveColor(shape.link.color ?? 'neutral', 0);\n return (\n <path\n key={shape.index}\n data-part=\"link\"\n d={shape.d}\n stroke-width={svgNumber(shape.width)}\n {...css.attrs(mapChartStyles.link, chartSvgStyles.stroke(tone))}\n />\n );\n })}\n {flow &&\n !reducedMotion.value &&\n linkShapes.flatMap((shape) => {\n // 每 120px 一个粒子,速度约每秒 60px;错开起点,看起来连续流动\n const count = Math.max(1, Math.round(shape.length / 120));\n const duration = Math.max(1.5, shape.length / 60);\n const tone = resolveColor(shape.link.color ?? 'accent', 0);\n return Array.from({ length: count }, (_, k) => (\n <circle\n key={`${shape.index}:${k}`}\n r={2}\n {...css.attrs(mapChartStyles.particle, chartSvgStyles.fill(tone))}\n >\n <animateMotion\n dur={`${svgNumber(duration)}s`}\n begin={`${svgNumber(-(duration * k) / count)}s`}\n repeatCount=\"indefinite\"\n // JSX 的类型里没有 animateMotion 的 path 属性\n {...{ path: shape.d }}\n />\n </circle>\n ));\n })}\n </g>\n <g data-part=\"points\">\n {placedPoints.map((item) => (\n <path\n key={item.point.id}\n data-part=\"point\"\n data-point={item.index}\n d={markerPath(item.point.shape, item.x, item.y, item.r)}\n {...css.attrs(\n mapChartStyles.point,\n chartSvgStyles.fill(resolveColor(item.point.color ?? 'danger', 0)),\n onPointClick && mapChartStyles.clickable,\n )}\n />\n ))}\n </g>\n <g data-part=\"area-labels\" {...css.attrs(chartSvgStyles.noPointer)}>\n {labels.areas.map((item) => (\n <text\n key={item.label}\n x={svgNumber(item.rect.x + item.rect.width / 2)}\n y={svgNumber(item.rect.y + item.rect.height / 2)}\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n {...css.attrs(mapChartStyles.areaLabel, chartSvgStyles.halo)}\n >\n {item.label}\n </text>\n ))}\n </g>\n <g data-part=\"point-labels\" {...css.attrs(chartSvgStyles.noPointer)}>\n {labels.points.map(({ placement, anchor, item }) => {\n if (!placement) return null;\n const { box, leader } = placement;\n // 引线:从标记的边到名字矩形上离标记最近的点\n const toX = Math.min(Math.max(anchor.x, box.x), box.x + box.width);\n const toY = Math.min(Math.max(anchor.y, box.y), box.y + box.height);\n const length = Math.hypot(toX - anchor.x, toY - anchor.y) || 1;\n return (\n <g key={item.point.id}>\n {leader && (\n <line\n x1={svgNumber(anchor.x + ((toX - anchor.x) / length) * anchor.radius)}\n y1={svgNumber(anchor.y + ((toY - anchor.y) / length) * anchor.radius)}\n x2={svgNumber(toX)}\n y2={svgNumber(toY)}\n {...css.attrs(mapChartStyles.leader)}\n />\n )}\n <text\n x={svgNumber(box.x + box.width / 2)}\n y={svgNumber(box.y + box.height / 2)}\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n {...css.attrs(mapChartStyles.pointLabel, chartSvgStyles.halo)}\n >\n {item.point.label}\n </text>\n </g>\n );\n })}\n </g>\n </svg>\n );\n }\n\n const tip = (): ChartTip | null => {\n const current = hovered;\n if (!tooltip || !current) return null;\n if (current.kind === 'point') {\n const point = points[current.index];\n if (!point) return null;\n return {\n x: current.x,\n y: current.y,\n content: chartTooltip(point.label, [\n {\n label: lang.chartValue,\n color: resolveColor(point.color ?? 'danger', 0),\n value: valueText(point.value),\n },\n ]),\n };\n }\n const shape = geometry.shapes[current.index];\n const info = shape && areaById.get(shape.id);\n if (!info) return null;\n return {\n x: current.x,\n y: current.y,\n content: chartTooltip(info.label, [\n {\n label: lang.chartValue,\n color: areaColor(info) ?? 'transparent',\n value: valueText(info.value),\n },\n ]),\n };\n };\n\n /** 图例:分档时每档一个色块与范围,连续时一条色带两端写最小最大 */\n function legend() {\n if (!extent || areas.every((item) => item.color)) return null;\n const [low, high] = extent;\n if (bins) {\n const step = (high - low) / bins;\n return (\n <div {...css.attrs(mapChartStyles.legend)} aria-hidden=\"true\">\n {Array.from({ length: bins }, (_, index) => {\n const from = low + step * index;\n const to = index === bins - 1 ? high : from + step;\n return (\n <span key={index} {...css.attrs(mapChartStyles.bin)}>\n <span\n {...css.attrs(\n mapChartStyles.swatch,\n mapChartStyles.swatchColor(colorOf((from + to) / 2)),\n )}\n />\n {numberText(from)} – {numberText(to)}\n </span>\n );\n })}\n </div>\n );\n }\n const stops =\n scheme === 'diverging'\n ? [colorOf(low), colors.fill, colorOf(high)]\n : [colorOf(low), colorOf(high)];\n return (\n <div {...css.attrs(mapChartStyles.legend)} aria-hidden=\"true\">\n <span>{numberText(low)}</span>\n <span\n {...css.attrs(\n mapChartStyles.ramp,\n mapChartStyles.rampColors(`linear-gradient(to right, ${stops.join(', ')})`),\n )}\n />\n <span>{numberText(high)}</span>\n </div>\n );\n }\n\n /** 缩放按钮:放大、缩小、复位;前面是滚轮的提示 */\n const zoomButtons = () => (\n <span {...css.attrs(mapChartStyles.zoom)}>\n {wheelHint && (\n <span {...css.attrs(mapChartStyles.wheelHint)} role=\"status\">\n {lang.chartZoomWheelHint}\n </span>\n )}\n {(\n [\n [Plus, lang.chartZoomIn, () => view.zoomIn()],\n [Minus, lang.chartZoomOut, () => view.zoomOut()],\n [Maximize, lang.chartZoomFit, () => view.reset()],\n ] as const\n ).map(([icon, label, action]) => (\n <IconButton\n key={label}\n icon={icon}\n size=\"sm\"\n variant=\"ghost\"\n tone=\"neutral\"\n aria-label={label}\n onClick={action}\n />\n ))}\n </span>\n );\n\n return () => (\n <ChartFrame\n {...rest}\n unit={unit}\n height={height}\n legend={[]}\n hiddenKeys={[]}\n onLegendToggle={() => {}}\n loading={loading}\n skeleton={<Skeleton sx={mapChartStyles.skeleton} />}\n isEmpty={false}\n empty={empty}\n actions={zoomable ? zoomButtons() : undefined}\n footer={legend()}\n table={{\n columns: [lang.chartCategory, unit ? `${lang.chartValue}(${unit})` : lang.chartValue],\n rows: [\n ...areas.map((item) => ({ header: item.label, value: item.value })),\n ...points.map((point) => ({ header: point.label, value: point.value })),\n ...links.map((link) => ({\n header: lang.chartFlowLabel(\n pointById.get(link.from)?.label ?? link.from,\n pointById.get(link.to)?.label ?? link.to,\n ),\n value: link.value,\n })),\n ].map((row) => ({\n header: row.header,\n cells: [\n row.value === undefined ? lang.emptyValue : format.number(row.value, valueFormat),\n ],\n })),\n }}\n plotRef={area.ref}\n plot={\n area.ready ? (\n <div\n {...css.attrs(mapChartStyles.viewport)}\n {...(zoomable ? view.viewportProps : {})}\n ref={(element) => (viewport.value = element as HTMLElement | null)}\n onPointermove={(event: PointerEvent) => {\n // 平移缩放也要指针移动(两指捏合):两个都调\n if (zoomable)\n (view.viewportProps.onPointermove as (event: PointerEvent) => void)(event);\n onPointermove(event);\n }}\n onPointerleave={() => (hovered = null)}\n >\n {renderPlot()}\n <ChartTooltipBox tip={tip()} width={area.width} />\n </div>\n ) : null\n }\n />\n );\n },\n);\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RadarChart.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_vue_ref","_createVNode","_mergeProps"],"sources":["../../src/charts/RadarChart.tsx"],"sourcesContent":["/**\n * 雷达图:几个维度上同时比较几个对象(供应商的质量、交期、价格、服务评分,方案的各项指标)。\n * 每个维度一根轴,从中心往外是 0 到 max;每个系列连成一个多边形,填一层浅色。\n *\n * <RadarChart\n * aria-label=\"供应商评分\"\n * data={[{ dimension: '质量', huachen: 86, hengyuan: 78 }, …]}\n * index=\"dimension\"\n * series={[{ key: 'huachen', label: '华辰精密' }, { key: 'hengyuan', label: '恒远五金' }]}\n * max={100}\n * />\n *\n * Unovis 没有雷达图:这里用 SVG 直接画,外层结构(图例、单位、加载与空状态、给读屏的数据表)同其他图表。\n * 悬停一个维度时那根轴加粗,各系列在这一维的数值标在顶点旁边;点图例隐藏系列。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { useLang } from '../config/context';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { Skeleton } from '../feedback/Skeleton';\nimport type { PartProps } from '../utils/props';\nimport { niceStep } from './axis-ticks';\nimport { ChartFrame, type ChartFrameParts } from './frame';\nimport { resolveSeries, seriesNumber, seriesValue, type ChartSeries } from './series';\nimport { svgNumber } from '../utils/data/number';\n\n/** 未声明的属性落到外层 div(role=\"figure\")上;aria-label 是图表的名称 */\nexport interface RadarChartProps<T extends object>\n extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {\n /** 数据:每一行是一个维度(质量、交期…) */\n data: readonly T[];\n /** 维度名的字段 */\n index: keyof T & string;\n /** 系列:每个系列连成一个多边形 */\n series: readonly ChartSeries<T>[];\n /** 轴的最大值;不写时按数据取一个整齐的值 */\n max?: number;\n /**\n * 网格的圈数\n * @default 4\n */\n levels?: number;\n /** 网格画成多边形(默认)或圆 */\n grid?: 'polygon' | 'circle';\n /** 数值的格式:刻度、顶点旁的数值、数据表共用 */\n valueFormat?: NumericFormat;\n /** 单位:显示在左上方 */\n unit?: string;\n /**\n * 绘图区的高度;数字按 px\n * @default 300\n */\n height?: number | string;\n /** 图例:默认多于一个系列时显示 */\n legend?: boolean;\n /** 隐藏的系列:点图例时写回,父级可以写 _hiddenSeries={keys} */\n _hiddenSeries?: string[];\n /** 加载中:绘图区显示骨架 */\n loading?: boolean;\n /** 没有数据时显示的内容 */\n empty?: VNodeChild;\n}\n\n/** RadarChart 的样式 */\nexport const radarChartStyles = css.create({\n svg: { display: 'block', width: '100%', height: '100%', overflow: 'visible' },\n grid: { fill: 'none', stroke: '_borderMuted', strokeWidth: 1 },\n spoke: { stroke: '_borderMuted', strokeWidth: 1 },\n spokeActive: { stroke: '_textMuted', strokeWidth: 1.5 },\n tick: { fill: '_textMuted', fontSize: '9px' },\n label: { fill: '_text', fontSize: '11px' },\n labelActive: { fontWeight: '_semibold' },\n // 几个系列叠在一起:填充很浅,混在一起也不发灰\n area: { fillOpacity: 0.08, strokeWidth: 2, strokeLinejoin: 'round' },\n vertex: { strokeWidth: 0 },\n value: { fontSize: '10px', fontWeight: '_semibold', paintOrder: 'stroke', strokeWidth: 3 },\n // 悬停用的扇区:透明,只接指针\n sector: { fill: 'transparent' },\n skeleton: {\n display: 'block',\n height: '100%',\n aspectRatio: '1',\n marginInline: 'auto',\n borderRadius: '50%',\n },\n stroke: (color: string) => ({ stroke: color, fill: color }),\n surfaceStroke: { stroke: '_surface' },\n});\n\n// 画布:360 × 300,中心 (180, 150),半径 108;文字在半径 124 的圈上\nconst WIDTH = 360;\nconst HEIGHT = 300;\nconst CX = WIDTH / 2;\nconst CY = HEIGHT / 2;\nconst RADIUS = 108;\nconst LABEL_RADIUS = 124;\n\n/** 第 index 个维度(共 count 个)、比例 ratio 处的点:第一个维度在正上方,顺时针 */\nfunction polar(index: number, count: number, ratio: number) {\n const angle = (Math.PI * 2 * index) / count - Math.PI / 2;\n return {\n x: svgNumber(CX + Math.cos(angle) * RADIUS * ratio),\n y: svgNumber(CY + Math.sin(angle) * RADIUS * ratio),\n angle,\n };\n}\n\n/** 雷达图 */\nexport const RadarChart = _component(\n <T extends object>({\n data,\n index,\n series,\n max,\n levels = 4,\n grid = 'polygon',\n valueFormat,\n unit,\n height = 300,\n legend,\n _hiddenSeries: hiddenSeries = _bindable<string[]>([]),\n loading = false,\n empty,\n ...rest\n }: RadarChartProps<T>) => {\n const lang = useLang();\n const format = useFormat();\n const resolved = _derived(resolveSeries(series));\n const visible = _derived(resolved.filter((item) => !hiddenSeries.includes(item.key)));\n // 悬停的维度\n let active = _state<number | null>(null);\n\n function toggle(key: string) {\n hiddenSeries = hiddenSeries.includes(key)\n ? hiddenSeries.filter((item) => item !== key)\n : [...hiddenSeries, key];\n }\n\n return () => {\n const count = data.length;\n const values = data.flatMap((row) => visible.map((item) => seriesNumber(row, item.key) ?? 0));\n // 轴的最大值:给了用它,否则取 levels 格整齐步长的整数倍\n const top = max ?? niceStep(Math.max(...values, 1) / levels) * levels;\n const ratioOf = (value: number) => Math.max(0, Math.min(value / top, 1));\n const ring = (ratio: number) =>\n grid === 'circle'\n ? null\n : data\n .map((_row, position) => polar(position, count, ratio))\n .map((p) => `${p.x},${p.y}`)\n .join(' ');\n\n const plot =\n count < 3 ? null : (\n <svg\n {...css.attrs(radarChartStyles.svg)}\n viewBox={`0 0 ${WIDTH} ${HEIGHT}`}\n aria-hidden=\"true\"\n onPointerleave={() => (active = null)}\n >\n {Array.from({ length: levels }, (_, level) => {\n const ratio = (level + 1) / levels;\n return grid === 'circle' ? (\n <circle\n key={level}\n cx={CX}\n cy={CY}\n r={RADIUS * ratio}\n {...css.attrs(radarChartStyles.grid)}\n />\n ) : (\n <polygon key={level} points={ring(ratio)!} {...css.attrs(radarChartStyles.grid)} />\n );\n })}\n {data.map((row, position) => {\n const end = polar(position, count, 1);\n const label = polar(position, count, LABEL_RADIUS / RADIUS);\n const cos = Math.cos(label.angle);\n return (\n <g key={position}>\n <line\n x1={CX}\n y1={CY}\n x2={end.x}\n y2={end.y}\n {...css.attrs(\n radarChartStyles.spoke,\n active === position && radarChartStyles.spokeActive,\n )}\n />\n <text\n x={label.x}\n y={label.y}\n text-anchor={Math.abs(cos) < 0.2 ? 'middle' : cos > 0 ? 'start' : 'end'}\n dominant-baseline=\"middle\"\n {...css.attrs(\n radarChartStyles.label,\n active === position && radarChartStyles.labelActive,\n )}\n >\n {String(row[index] ?? '')}\n </text>\n </g>\n );\n })}\n {Array.from({ length: levels }, (_, level) => (\n <text\n key={`tick-${level}`}\n x={CX + 3}\n y={CY - (RADIUS * (level + 1)) / levels}\n dominant-baseline=\"middle\"\n {...css.attrs(radarChartStyles.tick)}\n >\n {format.number((top * (level + 1)) / levels, valueFormat)}\n </text>\n ))}\n {visible.map((item) => {\n const points = data.map((row, position) =>\n polar(position, count, ratioOf(seriesNumber(row, item.key) ?? 0)),\n );\n return (\n <g key={item.key}>\n <polygon\n points={points.map((p) => `${p.x},${p.y}`).join(' ')}\n {...css.attrs(radarChartStyles.area, radarChartStyles.stroke(item.color))}\n />\n {points.map((p, position) => (\n <circle\n key={position}\n cx={p.x}\n cy={p.y}\n r={active === position ? 4 : 2.5}\n {...css.attrs(radarChartStyles.vertex, radarChartStyles.stroke(item.color))}\n />\n ))}\n {active !== null && (\n <text\n x={points[active]!.x}\n y={points[active]!.y - 8}\n text-anchor=\"middle\"\n {...css.attrs(\n radarChartStyles.value,\n radarChartStyles.stroke(item.color),\n radarChartStyles.surfaceStroke,\n )}\n >\n {format.number(seriesValue(data[active]!, item.key) ?? 0, valueFormat)}\n </text>\n )}\n </g>\n );\n })}\n {/* 悬停:每个维度一块扇区 */}\n {data.map((_row, position) => {\n const a = polar(position - 0.5, count, 1.2);\n const b = polar(position + 0.5, count, 1.2);\n return (\n <path\n key={`sector-${position}`}\n d={`M${CX} ${CY} L${a.x} ${a.y} L${b.x} ${b.y} Z`}\n {...css.attrs(radarChartStyles.sector)}\n onPointerenter={() => (active = position)}\n />\n );\n })}\n </svg>\n );\n\n return (\n <ChartFrame\n {...rest}\n unit={unit}\n height={height}\n legend={(legend ?? resolved.length > 1) ? resolved : []}\n hiddenKeys={hiddenSeries}\n onLegendToggle={toggle}\n loading={loading}\n skeleton={<Skeleton sx={radarChartStyles.skeleton} />}\n isEmpty={data.length === 0}\n empty={empty}\n table={{\n columns: [\n lang.chartCategory,\n ...resolved.map((item) => (unit ? `${item.label}(${unit})` : item.label)),\n ],\n rows: data.map((row) => ({\n header: String(row[index] ?? ''),\n cells: resolved.map((item) => {\n const value = seriesValue(row, item.key);\n return value === undefined ? lang.emptyValue : format.number(value, valueFormat);\n }),\n })),\n }}\n plot={plot}\n />\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RadarChart.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_vue_ref","_createVNode","_mergeProps"],"sources":["../../src/charts/RadarChart.tsx"],"sourcesContent":["/**\n * 雷达图:几个维度上同时比较几个对象(供应商的质量、交期、价格、服务评分,方案的各项指标)。\n * 每个维度一根轴,从中心往外是 0 到 max;每个系列连成一个多边形,填一层浅色。\n *\n * <RadarChart\n * aria-label=\"供应商评分\"\n * data={[{ dimension: '质量', huachen: 86, hengyuan: 78 }, …]}\n * index=\"dimension\"\n * series={[{ key: 'huachen', label: '华辰精密' }, { key: 'hengyuan', label: '恒远五金' }]}\n * max={100}\n * />\n *\n * SVG 按固定的画布画、随绘图区缩放;外层结构(图例、单位、加载与空状态、给读屏的数据表)同其他图表。\n * 悬停一个维度时那根轴加粗,各系列在这一维的数值标在顶点旁边;点图例隐藏系列。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { useLang } from '../config/context';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { Skeleton } from '../feedback/Skeleton';\nimport type { PartProps } from '../utils/props';\nimport { niceStep } from './axis-ticks';\nimport { ChartFrame, type ChartFrameParts } from './frame';\nimport { resolveSeries, seriesNumber, seriesValue, type ChartSeries } from './series';\nimport { svgNumber } from '../utils/data/number';\n\n/** 未声明的属性落到外层 div(role=\"figure\")上;aria-label 是图表的名称 */\nexport interface RadarChartProps<T extends object>\n extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {\n /** 数据:每一行是一个维度(质量、交期…) */\n data: readonly T[];\n /** 维度名的字段 */\n index: keyof T & string;\n /** 系列:每个系列连成一个多边形 */\n series: readonly ChartSeries<T>[];\n /** 轴的最大值;不写时按数据取一个整齐的值 */\n max?: number;\n /**\n * 网格的圈数\n * @default 4\n */\n levels?: number;\n /** 网格画成多边形(默认)或圆 */\n grid?: 'polygon' | 'circle';\n /** 数值的格式:刻度、顶点旁的数值、数据表共用 */\n valueFormat?: NumericFormat;\n /** 单位:显示在左上方 */\n unit?: string;\n /**\n * 绘图区的高度;数字按 px\n * @default 300\n */\n height?: number | string;\n /** 图例:默认多于一个系列时显示 */\n legend?: boolean;\n /** 隐藏的系列:点图例时写回,父级可以写 _hiddenSeries={keys} */\n _hiddenSeries?: string[];\n /** 加载中:绘图区显示骨架 */\n loading?: boolean;\n /** 没有数据时显示的内容 */\n empty?: VNodeChild;\n}\n\n/** RadarChart 的样式 */\nexport const radarChartStyles = css.create({\n svg: { display: 'block', width: '100%', height: '100%', overflow: 'visible' },\n grid: { fill: 'none', stroke: '_borderMuted', strokeWidth: 1 },\n spoke: { stroke: '_borderMuted', strokeWidth: 1 },\n spokeActive: { stroke: '_textMuted', strokeWidth: 1.5 },\n tick: { fill: '_textMuted', fontSize: '9px' },\n label: { fill: '_text', fontSize: '11px' },\n labelActive: { fontWeight: '_semibold' },\n // 几个系列叠在一起:填充很浅,混在一起也不发灰\n area: { fillOpacity: 0.08, strokeWidth: 2, strokeLinejoin: 'round' },\n vertex: { strokeWidth: 0 },\n value: { fontSize: '10px', fontWeight: '_semibold', paintOrder: 'stroke', strokeWidth: 3 },\n // 悬停用的扇区:透明,只接指针\n sector: { fill: 'transparent' },\n skeleton: {\n display: 'block',\n height: '100%',\n aspectRatio: '1',\n marginInline: 'auto',\n borderRadius: '50%',\n },\n stroke: (color: string) => ({ stroke: color, fill: color }),\n surfaceStroke: { stroke: '_surface' },\n});\n\n// 画布:360 × 300,中心 (180, 150),半径 108;文字在半径 124 的圈上\nconst WIDTH = 360;\nconst HEIGHT = 300;\nconst CX = WIDTH / 2;\nconst CY = HEIGHT / 2;\nconst RADIUS = 108;\nconst LABEL_RADIUS = 124;\n\n/** 第 index 个维度(共 count 个)、比例 ratio 处的点:第一个维度在正上方,顺时针 */\nfunction polar(index: number, count: number, ratio: number) {\n const angle = (Math.PI * 2 * index) / count - Math.PI / 2;\n return {\n x: svgNumber(CX + Math.cos(angle) * RADIUS * ratio),\n y: svgNumber(CY + Math.sin(angle) * RADIUS * ratio),\n angle,\n };\n}\n\n/** 雷达图 */\nexport const RadarChart = _component(\n <T extends object>({\n data,\n index,\n series,\n max,\n levels = 4,\n grid = 'polygon',\n valueFormat,\n unit,\n height = 300,\n legend,\n _hiddenSeries: hiddenSeries = _bindable<string[]>([]),\n loading = false,\n empty,\n ...rest\n }: RadarChartProps<T>) => {\n const lang = useLang();\n const format = useFormat();\n const resolved = _derived(resolveSeries(series));\n const visible = _derived(resolved.filter((item) => !hiddenSeries.includes(item.key)));\n // 悬停的维度\n let active = _state<number | null>(null);\n\n function toggle(key: string) {\n hiddenSeries = hiddenSeries.includes(key)\n ? hiddenSeries.filter((item) => item !== key)\n : [...hiddenSeries, key];\n }\n\n return () => {\n const count = data.length;\n const values = data.flatMap((row) => visible.map((item) => seriesNumber(row, item.key) ?? 0));\n // 轴的最大值:给了用它,否则取 levels 格整齐步长的整数倍\n const top = max ?? niceStep(Math.max(...values, 1) / levels) * levels;\n const ratioOf = (value: number) => Math.max(0, Math.min(value / top, 1));\n const ring = (ratio: number) =>\n grid === 'circle'\n ? null\n : data\n .map((_row, position) => polar(position, count, ratio))\n .map((p) => `${p.x},${p.y}`)\n .join(' ');\n\n const plot =\n count < 3 ? null : (\n <svg\n {...css.attrs(radarChartStyles.svg)}\n viewBox={`0 0 ${WIDTH} ${HEIGHT}`}\n aria-hidden=\"true\"\n onPointerleave={() => (active = null)}\n >\n {Array.from({ length: levels }, (_, level) => {\n const ratio = (level + 1) / levels;\n return grid === 'circle' ? (\n <circle\n key={level}\n cx={CX}\n cy={CY}\n r={RADIUS * ratio}\n {...css.attrs(radarChartStyles.grid)}\n />\n ) : (\n <polygon key={level} points={ring(ratio)!} {...css.attrs(radarChartStyles.grid)} />\n );\n })}\n {data.map((row, position) => {\n const end = polar(position, count, 1);\n const label = polar(position, count, LABEL_RADIUS / RADIUS);\n const cos = Math.cos(label.angle);\n return (\n <g key={position}>\n <line\n x1={CX}\n y1={CY}\n x2={end.x}\n y2={end.y}\n {...css.attrs(\n radarChartStyles.spoke,\n active === position && radarChartStyles.spokeActive,\n )}\n />\n <text\n x={label.x}\n y={label.y}\n text-anchor={Math.abs(cos) < 0.2 ? 'middle' : cos > 0 ? 'start' : 'end'}\n dominant-baseline=\"middle\"\n {...css.attrs(\n radarChartStyles.label,\n active === position && radarChartStyles.labelActive,\n )}\n >\n {String(row[index] ?? '')}\n </text>\n </g>\n );\n })}\n {Array.from({ length: levels }, (_, level) => (\n <text\n key={`tick-${level}`}\n x={CX + 3}\n y={CY - (RADIUS * (level + 1)) / levels}\n dominant-baseline=\"middle\"\n {...css.attrs(radarChartStyles.tick)}\n >\n {format.number((top * (level + 1)) / levels, valueFormat)}\n </text>\n ))}\n {visible.map((item) => {\n const points = data.map((row, position) =>\n polar(position, count, ratioOf(seriesNumber(row, item.key) ?? 0)),\n );\n return (\n <g key={item.key}>\n <polygon\n points={points.map((p) => `${p.x},${p.y}`).join(' ')}\n {...css.attrs(radarChartStyles.area, radarChartStyles.stroke(item.color))}\n />\n {points.map((p, position) => (\n <circle\n key={position}\n cx={p.x}\n cy={p.y}\n r={active === position ? 4 : 2.5}\n {...css.attrs(radarChartStyles.vertex, radarChartStyles.stroke(item.color))}\n />\n ))}\n {active !== null && (\n <text\n x={points[active]!.x}\n y={points[active]!.y - 8}\n text-anchor=\"middle\"\n {...css.attrs(\n radarChartStyles.value,\n radarChartStyles.stroke(item.color),\n radarChartStyles.surfaceStroke,\n )}\n >\n {format.number(seriesValue(data[active]!, item.key) ?? 0, valueFormat)}\n </text>\n )}\n </g>\n );\n })}\n {/* 悬停:每个维度一块扇区 */}\n {data.map((_row, position) => {\n const a = polar(position - 0.5, count, 1.2);\n const b = polar(position + 0.5, count, 1.2);\n return (\n <path\n key={`sector-${position}`}\n d={`M${CX} ${CY} L${a.x} ${a.y} L${b.x} ${b.y} Z`}\n {...css.attrs(radarChartStyles.sector)}\n onPointerenter={() => (active = position)}\n />\n );\n })}\n </svg>\n );\n\n return (\n <ChartFrame\n {...rest}\n unit={unit}\n height={height}\n legend={(legend ?? resolved.length > 1) ? resolved : []}\n hiddenKeys={hiddenSeries}\n onLegendToggle={toggle}\n loading={loading}\n skeleton={<Skeleton sx={radarChartStyles.skeleton} />}\n isEmpty={data.length === 0}\n empty={empty}\n table={{\n columns: [\n lang.chartCategory,\n ...resolved.map((item) => (unit ? `${item.label}(${unit})` : item.label)),\n ],\n rows: data.map((row) => ({\n header: String(row[index] ?? ''),\n cells: resolved.map((item) => {\n const value = seriesValue(row, item.key);\n return value === undefined ? lang.emptyValue : format.number(value, valueFormat);\n }),\n })),\n }}\n plot={plot}\n />\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
@@ -48,10 +48,15 @@ export interface SankeyChartProps extends PartProps<'div', 'role' | 'aria-busy'>
|
|
|
48
48
|
/** 没有数据时显示的内容,默认是“暂无数据” */
|
|
49
49
|
empty?: VNodeChild;
|
|
50
50
|
}
|
|
51
|
-
/** SankeyChart
|
|
51
|
+
/** SankeyChart 的样式:节点、带子、名字、骨架 */
|
|
52
52
|
export declare const sankeyChartStyles: Readonly<{
|
|
53
|
-
|
|
53
|
+
link: css.CompiledStyles;
|
|
54
|
+
linkActive: css.CompiledStyles;
|
|
55
|
+
linkFaded: css.CompiledStyles;
|
|
56
|
+
name: css.CompiledStyles;
|
|
57
|
+
node: css.CompiledStyles;
|
|
54
58
|
skeleton: css.CompiledStyles;
|
|
59
|
+
value: css.CompiledStyles;
|
|
55
60
|
}>;
|
|
56
61
|
/** 桑基图 */
|
|
57
62
|
export declare const SankeyChart: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<SankeyChartProps>;
|