Map 地图
轻量矢量地图容器,支持 marker、polygon overlay、route、缩放与交互事件。
基础用法
Map 先提供零依赖的矢量地图底座:坐标使用 0–100 的归一化空间,适合机房平面图、园区拓扑、区域监控、网络节点图等后台系统场景。
标记、区域覆盖物、路线都可以交互,点击覆盖物时会触发 overlay-click,点击标记会触发 marker-click,点击空白地图会触发 map-click。
背景
edge-a
点击地图、标记或区域后,这里会显示事件 payload。<script setup lang="ts">
import { ref } from 'vue';
import {
CfBadge,
CfMap,
type MapCanvasEvent,
type MapMarkerEvent,
type MapOverlayEvent,
type MapViewport,
} from '@chufix-design/vue';
const activeId = ref('edge-a');
const lastEvent = ref('点击地图、标记或区域后,这里会显示事件 payload。');
const markers = [
{ id: 'edge-a', label: 'Edge A', x: 24, y: 34, tone: 'success' as const, value: '99%' },
{ id: 'dc-core', label: 'Core', x: 52, y: 46, tone: 'info' as const, value: '12ms' },
{ id: 'edge-b', label: 'Edge B', x: 72, y: 38, tone: 'warning' as const, value: '3 alerts' },
{ id: 'backup', label: 'Backup', x: 42, y: 74, tone: 'default' as const, value: 'idle' },
];
const overlays = [
{
id: 'zone-north',
label: '北区覆盖层',
tone: 'info' as const,
interactive: true,
points: [
{ x: 18, y: 20 },
{ x: 56, y: 18 },
{ x: 60, y: 48 },
{ x: 28, y: 55 },
],
},
{
id: 'zone-risk',
label: '风险区域',
tone: 'warning' as const,
interactive: true,
points: [
{ x: 61, y: 30 },
{ x: 84, y: 38 },
{ x: 78, y: 62 },
{ x: 58, y: 56 },
],
},
];
const routes = [
{
id: 'primary-link',
tone: 'success' as const,
points: [
{ x: 24, y: 34 },
{ x: 52, y: 46 },
{ x: 72, y: 38 },
],
},
{
id: 'backup-link',
tone: 'warning' as const,
dashed: true,
points: [
{ x: 24, y: 34 },
{ x: 42, y: 74 },
{ x: 72, y: 38 },
],
},
];
function onMarkerClick(event: MapMarkerEvent) {
activeId.value = event.marker.id;
lastEvent.value = `marker-click: ${event.marker.label} / ${event.marker.value ?? '-'}`;
}
function onOverlayClick(event: MapOverlayEvent) {
activeId.value = event.overlay.id;
lastEvent.value = `overlay-click: ${event.overlay.label} / ${event.overlay.points.length} points`;
}
function onMapClick(event: MapCanvasEvent) {
lastEvent.value = `map-click: x=${event.point.x.toFixed(1)}, y=${event.point.y.toFixed(1)}`;
}
function onViewportChange(viewport: MapViewport) {
lastEvent.value = `viewport-change: zoom=${viewport.zoom.toFixed(1)}, center=${viewport.center.x},${viewport.center.y}`;
}
</script>
<template>
<div class="map-demo">
<CfMap
:markers="markers"
:overlays="overlays"
:routes="routes"
:active-id="activeId"
:height="420"
@marker-click="onMarkerClick"
@overlay-click="onOverlayClick"
@map-click="onMapClick"
@viewport-change="onViewportChange"
/>
<div class="map-demo__status">
<CfBadge tone="info" :content="activeId" />
<code>{{ lastEvent }}</code>
</div>
</div>
</template>
<style scoped>
.map-demo {
display: grid;
gap: 12px;
width: 100%;
}
.map-demo__status {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
}
.map-demo__status code {
white-space: normal;
}
</style>
<CfMap
markers={markers}
overlays={overlays}
routes={routes}
onMarkerClick={onMarkerClick}
onOverlayClick={onOverlayClick}
onMapClick={onMapClick}
/> API
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
markers | MapMarker[] | [] | 标记点,字段为 id / label / x / y / tone? / value? / disabled? |
overlays | MapOverlay[] | [] | 多边形覆盖物,interactive 为 true 时支持点击与键盘触发 |
routes | MapRoute[] | [] | 折线路线,支持 tone 与 dashed |
height | number | string | 360 | 地图高度 |
center | { x: number; y: number } | { x: 50, y: 50 } | 视口中心点 |
zoom | number | 1 | 初始缩放级别 |
minZoom / maxZoom | number | 0.7 / 2.4 | 缩放边界 |
showGrid | boolean | true | 是否显示地图网格 |
showLabels | boolean | true | 是否显示 marker label |
controls | boolean | true | 是否显示缩放 / 重置控件 |
activeId | string | — | 高亮 marker 或 overlay |
Events
| Vue 事件 | React 回调 | payload | 说明 |
|---|---|---|---|
marker-click | onMarkerClick | { marker, nativeEvent } | 点击或键盘激活 marker |
marker-enter / marker-leave | onMarkerEnter / onMarkerLeave | { marker, nativeEvent } | marker hover 状态 |
overlay-click | onOverlayClick | { overlay, nativeEvent } | 点击或键盘激活交互覆盖物 |
map-click | onMapClick | { point, nativeEvent } | 点击地图空白区域,返回归一化坐标 |
viewport-change | onViewportChange | { center, zoom } | 点击缩放 / 重置控件后触发 |
设计说明
这个版本故意不绑定具体地图服务,优先把 UI 库应该有的“覆盖物、事件、状态、可访问性”能力打实。后续如果接入 Leaflet / Mapbox,可以保留同一组 markers / overlays / events API,只把渲染适配到真实瓦片或 WebGL 地图。
反馈与讨论
Map 地图 的讨论