Cesium Map
gaopengbin/cesium-mcp
Open and operate the Cesium MCP 3D map, create map objects and GeoJSON layers, or inspect the selected object in the connected map.
基于 WebGL 的大规模地理空间数据可视化引擎。适用于: (1) 创建交互式 WebGL 地图应用 (2) 可视化地理空间数据(点、线、面、热力图) (3) 构建位置数据驾驶舱 (4) 添加地图图层、交互和动画效果 (5) 处理并展示 GeoJSON、CSV 等空间数据
$ npx skills add antvis/L7 --skill antv-l7 -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install antvis/L7 antv-l7 --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/antvis/L7.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/l7-single .claude/skills/antv-l7 && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "antv-l7" agent skill from https://github.com/antvis/L7/tree/master/skills/l7-single into .claude/skills/antv-l7/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "antv-l7", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/antvis/L7/tree/master/skills/l7-singleType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add antvis/L7 --skill antv-l7 -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install antvis/L7 antv-l7 --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/antvis/L7.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/l7-single .agents/skills/antv-l7 && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "antv-l7" agent skill from https://github.com/antvis/L7/tree/master/skills/l7-single into .agents/skills/antv-l7/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "antv-l7", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add antvis/L7 --skill antv-l7 -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install antvis/L7 antv-l7 --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/antvis/L7.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/l7-single .cursor/skills/antv-l7 && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "antv-l7" agent skill from https://github.com/antvis/L7/tree/master/skills/l7-single into .cursor/skills/antv-l7/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "antv-l7", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/antvis/L7.git --path skills/l7-single--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add antvis/L7 --skill antv-l7 -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install antvis/L7 antv-l7 --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/antvis/L7.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/l7-single .gemini/skills/antv-l7 && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "antv-l7" agent skill from https://github.com/antvis/L7/tree/master/skills/l7-single into .gemini/skills/antv-l7/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "antv-l7", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install antvis/L7 antv-l7Installs for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add antvis/L7 --skill antv-l7 -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/antvis/L7.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/l7-single .github/skills/antv-l7 && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "antv-l7" agent skill from https://github.com/antvis/L7/tree/master/skills/l7-single into .github/skills/antv-l7/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "antv-l7", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add antvis/L7 --skill antv-l7 -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install antvis/L7 antv-l7 --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/antvis/L7.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/l7-single .opencode/skills/antv-l7 && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "antv-l7" agent skill from https://github.com/antvis/L7/tree/master/skills/l7-single into .opencode/skills/antv-l7/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "antv-l7", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
antv-l7基于 WebGL 的大规模地理空间数据可视化引擎。适用于: (1) 创建交互式 WebGL 地图应用 (2) 可视化地理空间数据(点、线、面、热力图) (3) 构建位置数据驾驶舱 (4) 添加地图图层、交互和动画效果 (5) 处理并展示 GeoJSON、CSV 等空间数据
Antv L7 is an agent skill from antvis/L7. 基于 WebGL 的大规模地理空间数据可视化引擎。适用于: (1) 创建交互式 WebGL 地图应用 (2) 可视化地理空间数据(点、线、面、热力图) (3) 构建位置数据驾驶舱 (4) 添加地图图层、交互和动画效果 (5) 处理并展示 GeoJSON、CSV 等空间数据
Its SKILL.md is about 4.4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Game Development, covering 3D graphics and WebGL, Geospatial analysis and CSV and tabular files. It works with JavaScript and Mapbox. The repository describes itself as: 🌎 Large-scale WebGL-powered Geospatial Data Visualization analysis engine. The licence is MIT.
4 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 6e3dbfe. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript and javascript).
From the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
l7.antv.antgroup.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Antv L7 loads about 4.4k tokens when it runs. Until then it costs about 36 tokens; SKILL.md has 422 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from antvis/L7 at commit 6e3dbfe, republished under its MIT licence (© antvis). 422 words, ~4,408 tokens.
.claude/skills/antv-l7/SKILL.md (or your agent's skills folder).AntV L7 是基于 WebGL 的大规模地理空间数据可视化引擎,支持多种地图底图和丰富的可视化图层类型。
作用域声明:以下约束仅适用于 WeaveFox(本仓库)环境。
在 WeaveFox 环境下,高德地图配置禁止传入 token 参数。
在 WeaveFox 项目中,L7 已配置默认 token。在该环境下,GaodeMap 配置中不要设置 token 字段,否则会导致地图加载失败。
// ✅ 正确 - 不传 token
new GaodeMap({
center: [120.19, 30.26],
zoom: 10,
style: 'light',
});
// ❌ 错误 - 禁止传入 token
new GaodeMap({
center: [120.19, 30.26],
zoom: 10,
style: 'light',
token: 'xxx', // 不要这样做!
});优先使用 Marker,而非 PointLayer:
import { Marker, Popup } from '@antv/l7';
let currentPopup = null;
// ✅ 推荐 - 少量点位使用 Marker
data.forEach((point) => {
const marker = new Marker({
color: '#5B8FF9',
draggable: false,
}).setLnglat([point.lng, point.lat]);
marker.on('click', () => {
// 统一单实例 popup:先移除旧 popup,再创建新 popup
if (currentPopup) scene.removePopup(currentPopup);
currentPopup = new Popup({
anchor: 'bottom',
className: 'outing-popup',
lngLat: { lng: point.lng, lat: point.lat },
html: `<div>${point.name}</div>`,
});
scene.addPopup(currentPopup);
});
// 必须使用 scene.addMarker,否则地图缩放/平移时 Marker 不会更新位置
scene.addMarker(marker);
});Marker vs PointLayer 对比:
| 特性 | Marker | PointLayer |
|---|---|---|
| 适用场景 | < 100 个点位 | > 100 个点位/大规模数据 |
| 性能 | DOM 渲染,轻量 | WebGL 渲染,高性能 |
| 交互 | 原生 DOM 事件,灵活 | 需绑定图层事件 |
| 自定义 | 支持任意 HTML/CSS | 受限于 L7 样式配置 |
| Popup | 内置支持 | 需额外配置 |
使用 PointLayer 进行 WebGL 渲染:
import { PointLayer } from '@antv/l7';
// ✅ 推荐 - 大量点位使用 PointLayer
const pointLayer = new PointLayer()
.source(data, {
parser: { type: 'json', x: 'lng', y: 'lat' },
})
.shape('circle')
.size(10)
.color('#5B8FF9');
scene.addLayer(pointLayer);以下规则为强约束,生成 React + L7 代码时必须遵守:
new Scene() 的 useEffect 依赖必须是 []。selectedId、筛选条件、分页参数。onSelect、onClick、onChange。destroy + new Scene。loaded 回调里若需要最新 props,使用 latestXxxRef.current,不要依赖闭包旧值。scene.destroy() 只能放在初始化 effect 的 cleanup 中,不能由状态变化触发。Scene/Layer 首建,更新负责 setData、更新 Marker 或样式。anchor: 'bottom',让弹窗显示在点位上方。scene.addPopup(...),禁止与 marker.setPopup(...)、popup.addTo(scene) 混用。scene.removePopup(oldPopup),避免页面出现多个弹窗。anchor 必须使用 'bottom',禁止使用 'center' 导致点位偏移。max-width 与 word-break,且尖角保持 margin: 0 auto 居中,防止尖角偏离点位。z-index >= 1000,确保显示在地图 logo 和其他地图固定元素之上。closeButton: true,允许用户点击关闭按钮关闭弹窗,提升交互体验。offset: [0, -40] 向上移动,避免与 Marker 气泡重叠遮挡。反例(禁止):
// 会导致 selectedId 变化时反复销毁并重建 Scene
useEffect(() => {
const scene = new Scene(...);
return () => scene.destroy();
}, [selectedId, onSelectLocation]);正例(推荐):
// 只初始化一次
useEffect(() => {
const scene = new Scene(...);
return () => scene.destroy();
}, []);
// 状态变化只更新图层,不重建 Scene
useEffect(() => {
pointLayerRef.current?.setData(nextData);
}, [nextData]);说明:React 18 开发环境 StrictMode 会对 mount 做额外检查,可能看到两次初始化日志。只要初始化 effect 为空依赖且职责正确,生产环境不会因此重复重建。
当使用自定义 Marker DOM 时,默认采用“主体 + 尖角”结构:
function createMarkerElement(point: { name: string; color: string }) {
const el = document.createElement('div');
el.style.cssText = 'position: relative; transform: translateY(-8px);';
el.innerHTML = `
<div style="
min-width: 88px;
padding: 6px 10px;
border-radius: 999px;
background: ${point.color};
color: #fff;
font-size: 12px;
font-weight: 600;
text-align: center;
line-height: 1.2;
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
position: relative;
max-width: 160px;
white-space: normal;
word-break: break-word;
">${point.name}</div>
<div style="
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: 8px solid ${point.color};
margin: 0 auto;
"></div>
`;
return el;
}
const marker = new Marker({
element: createMarkerElement(point),
anchor: 'bottom',
}).setLnglat([point.lng, point.lat]);约束说明:
text-align: center,并保持左右内边距对称。translateY(-8px))。'use client';
import { useEffect, useRef, useCallback } from 'react';
import { Scene, Marker, Popup } from '@antv/l7';
import { GaodeMap } from '@antv/l7-maps';
interface Location {
id: string;
lng: number;
lat: number;
name: string;
}
export function MarkerMap({ locations }: { locations: Location[] }) {
const mapContainerRef = useRef<HTMLDivElement>(null);
const sceneRef = useRef<Scene | null>(null);
const markersRef = useRef<Marker[]>([]);
const popupRef = useRef<Popup | null>(null);
const isInitializedRef = useRef(false);
// 创建/更新 Markers
const updateMarkers = useCallback((scene: Scene, data: Location[]) => {
// 1. 清理旧 marker(避免重复渲染和内存泄漏)
markersRef.current.forEach(marker => {
marker.remove();
});
markersRef.current = [];
// 2. 创建新 marker
data.forEach(point => {
const marker = new Marker({ color: '#5B8FF9' })
.setLnglat([point.lng, point.lat]);
marker.on('click', () => {
if (popupRef.current) {
scene.removePopup(popupRef.current);
}
popupRef.current = new Popup({
anchor: 'bottom',
closeButton: true,
offset: [0, -40],
lngLat: { lng: point.lng, lat: point.lat },
html: `<div>${point.name}</div>`,
});
scene.addPopup(popupRef.current);
});
// 必须使用 scene.addMarker,否则地图缩放/平移时 Marker 不会联动
scene.addMarker(marker);
markersRef.current.push(marker);
});
}, []);
useEffect(() => {
if (!mapContainerRef.current || isInitializedRef.current) return;
const scene = new Scene({
id: mapContainerRef.current,
map: new GaodeMap({
center: [105, 35],
zoom: 4,
style: 'light',
}),
});
sceneRef.current = scene;
isInitializedRef.current = true;
scene.on('loaded', () => {
updateMarkers(scene, locations);
});
return () => {
if (sceneRef.current) {
if (popupRef.current) {
sceneRef.current.removePopup(popupRef.current);
popupRef.current = null;
}
markersRef.current.forEach(marker => marker.remove());
markersRef.current = [];
sceneRef.current.destroy();
sceneRef.current = null;
isInitializedRef.current = false;
}
};
}, []);
// 数据更新时重建 markers
useEffect(() => {
if (isInitializedRef.current && sceneRef.current) {
updateMarkers(sceneRef.current, locations);
}
}, [locations]);
return (
<div
ref={mapContainerRef}
style={{ width: '100%', height: 'min(70vh, 600px)', minHeight: '360px' }}
/>
);
}Marker 关键注意点:
markersRef 保存实例数组,用于数据更新时清理旧 markerscene.addMarker(marker) 必须用它,.addTo(scene) 不会注册相机事件,导致 marker 与地图不同步scene.addPopup(...),不要和 marker.setPopup(...) 混用anchor: 'bottom',确保弹窗显示在 marker 上方markersRef.current 逐一 remove()'use client';
import { useEffect, useRef, useCallback } from 'react';
import { Scene, PointLayer, Popup } from '@antv/l7';
import { GaodeMap } from '@antv/l7-maps';
interface Location {
id: string;
lng: number;
lat: number;
name: string;
color: string;
}
interface MapProps {
locations: Location[];
onLocationClick?: (location: Location) => void;
}
export function TravelMap({ locations, onLocationClick }: MapProps) {
const mapContainerRef = useRef<HTMLDivElement>(null);
const sceneRef = useRef<Scene | null>(null);
const pointLayerRef = useRef<PointLayer | null>(null);
const popupRef = useRef<Popup | null>(null);
const isInitializedRef = useRef(false);
const latestLocationsRef = useRef<Location[]>(locations);
// 保持最新数据,避免 scene loaded 回调拿到旧闭包数据
useEffect(() => {
latestLocationsRef.current = locations;
}, [locations]);
// 初始化地图(只执行一次)
const initMap = useCallback(() => {
if (!mapContainerRef.current || isInitializedRef.current) return;
try {
const scene = new Scene({
id: mapContainerRef.current,
map: new GaodeMap({
center: [105, 35],
zoom: 4,
style: 'light',
}),
});
sceneRef.current = scene;
isInitializedRef.current = true;
return scene;
} catch (error) {
console.error('地图初始化失败:', error);
throw error;
}
}, []);
// 创建图层
const createLayer = useCallback((scene: Scene, data: Location[]) => {
const pointData = data.map(loc => ({
lng: loc.lng,
lat: loc.lat,
name: loc.name,
color: loc.color,
id: loc.id,
}));
const pointLayer = new PointLayer()
.source(pointData, {
parser: { type: 'json', x: 'lng', y: 'lat' },
})
.shape('circle')
.size(20)
.color('color', (color: string) => color)
.style({
opacity: 0.9,
strokeWidth: 2,
stroke: '#ffffff',
});
// 点击事件
pointLayer.on('click', (e: any) => {
if (popupRef.current) scene.removePopup(popupRef.current);
const feature = e?.feature;
if (!feature) return;
const location: Location = {
id: feature.id,
lng: feature.lng,
lat: feature.lat,
name: feature.name,
color: feature.color,
};
onLocationClick?.(location);
const lng = e?.lngLat?.lng ?? feature.lng;
const lat = e?.lngLat?.lat ?? feature.lat;
if (typeof lng !== 'number' || typeof lat !== 'number') return;
popupRef.current = new Popup({
anchor: 'bottom',
closeButton: true,
offset: [0, -40],
lngLat: { lng, lat },
title: feature.name ?? '',
html: `<div style="padding: 12px;">${feature.name ?? ''}</div>`,
});
scene.addPopup(popupRef.current);
});
scene.addLayer(pointLayer);
pointLayerRef.current = pointLayer;
}, [onLocationClick]);
// 更新数据
const updateLayers = useCallback((data: Location[]) => {
const pointLayer = pointLayerRef.current;
if (!pointLayer) return;
const pointData = data.map(loc => ({
lng: loc.lng,
lat: loc.lat,
name: loc.name,
color: loc.color,
id: loc.id,
}));
pointLayer.setData(pointData);
}, []);
// 初始化 effect
useEffect(() => {
const scene = initMap();
if (!scene) return;
scene.on('loaded', () => {
createLayer(scene, latestLocationsRef.current);
});
return () => {
if (sceneRef.current) {
if (pointLayerRef.current) {
sceneRef.current.removeLayer(pointLayerRef.current);
}
if (popupRef.current) {
sceneRef.current.removePopup(popupRef.current);
}
sceneRef.current.destroy();
sceneRef.current = null;
isInitializedRef.current = false;
}
};
}, []);
// 数据更新 effect
useEffect(() => {
if (isInitializedRef.current && pointLayerRef.current) {
updateLayers(locations);
}
}, [locations]);
return (
<div
ref={mapContainerRef}
style={{ width: '100%', height: 'min(70vh, 600px)', minHeight: '360px' }}
/>
);
}L7 的典型开发流程:
1. 场景初始化 (Scene) → 2. 数据准备 → 3. 创建图层 (Layer) → 4. 添加交互 → 5. 优化性能| 图层类型 | 说明 | 适用场景 |
|---|---|---|
| PointLayer | 点图层 | 散点、气泡、符号、文本标注 |
| LineLayer | 线图层 | 路径、弧线、流向线、3D 弧墙 |
| PolygonLayer | 面图层 | 区域填充、3D 挤出、海面效果 |
| HeatmapLayer | 热力图 | 密度分布、聚合热力 |
| 图层类型 | 说明 | 适用场景 |
|---|---|---|
| RasterLayer | 栅格图层 | 卫星影像、地形高程 |
| ImageLayer | 图片图层 | 单张图片叠加 |
| WindLayer | 风场图层 | 风向、气流可视化 |
| CityBuildingLayer | 建筑图层 | 3D 城市建筑、扫描光效果 |
| CanvasLayer | Canvas 图层 | 自定义 Canvas 绘制 |
| EarthLayer | 地球图层 | 3D 地球、大气层效果 |
| Marker | DOM 标注 | 少量点位、自定义 DOM |
.shape('circle') // 圆形
.shape('square') // 方形
.shape('triangle') // 三角形
.shape('text') // 文本标注
.shape('image') // 图片图标
.shape('cylinder') // 3D 圆柱.shape('line') // 直线
.shape('arc') // 弧线
.shape('arc3d') // 3D 弧线
.shape('greatcircle') // 大圆航线
.shape('wall') // 墙
.shape('flowline') // 流向线
.shape('dash') // 虚线| 类型 | parser.type | 数据格式 | 配置示例 |
|---|---|---|---|
| GeoJSON | 'geojson' | FeatureCollection | { type: 'geojson' } |
| JSON | 'json' | Array<Object> | { type: 'json', x: 'lng', y: 'lat' } |
| CSV | 'csv' | CSV 字符串 | { type: 'csv', x: 'lng', y: 'lat' } |
| MVT | 'mvt' | Vector Tile URL | { type: 'mvt', minZoom: 0, maxZoom: 18 } |
| Raster | 'raster' | 栅格数据 | { type: 'raster', width: 100, height: 100 } |
.source(data, {
parser: { type: 'json', x: 'lng', y: 'lat' },
transforms: [
// 聚合
{
type: 'cluster',
radius: 80,
method: 'sum',
field: 'value'
},
// 过滤
{
type: 'filter',
callback: (item) => item.value > 100
},
],
})// L7 2.x 推荐:统一从 @antv/l7 导入
import { Zoom, Fullscreen, LayerSwitch, ExportImage } from '@antv/l7';
// 等价写法:按子包导入(在按需拆包场景下可用)
// import { Zoom, Fullscreen, LayerSwitch, ExportImage } from '@antv/l7-component';
// 缩放控件
scene.addControl(
new Zoom({
position: 'bottomright',
zoomInText: '+',
zoomOutText: '-',
}),
);
// 全屏控件
scene.addControl(
new Fullscreen({
position: 'topleft',
}),
);
// 图层切换
scene.addControl(
new LayerSwitch({
layers: [layer1, layer2],
position: 'topright',
}),
);
// 导出图片
scene.addControl(
new ExportImage({
position: 'topright',
imageType: 'png',
}),
);// 设置中心点
scene.setCenter([120.19, 30.26]);
// 设置缩放
scene.setZoom(12);
// 适应边界 - 自动缩放地图以容纳指定范围
scene.fitBounds([
[minLng, minLat],
[maxLng, maxLat],
]);
// 完整参数
scene.fitBounds(
[
[minLng, minLat],
[maxLng, maxLat],
], // 边界范围 [西南角, 东北角]
{
padding: [50, 50, 50, 50], // 内边距 [上, 右, 下, 左],单位像素
duration: 500, // 动画时长(毫秒),默认无动画
maxZoom: 15, // 最大缩放级别限制
},
);
// 根据数据范围自动适配(配合 Layer 使用)
scene.fitBounds(pointLayer.getBounds());
// 切换地图样式
scene.setMapStyle('dark');
// 获取当前状态
const zoom = scene.getZoom();
const center = scene.getCenter();// 导出为 PNG
const png = await scene.exportPng('png');
// 导出地图(含底图)
const mapImage = await scene.exportMap('png');// 高亮
layer.active({ color: '#ff0000' });
// 选中
layer.select({ color: '#00ff00' });
// 框选
scene.enableBoxSelect(true);| 问题 | 解决方案 |
|---|---|
| 重复初始化 | 使用 isInitializedRef 标记 + 空依赖数组 |
| 初始化多次(React) | 初始化 useEffect 仅用 [];不要依赖 selectedId/父回调,状态变化走独立更新 effect |
| 弹窗重复出现 | 统一 scene.addPopup(...);新建前先移除旧 popup;禁止与 marker.setPopup(...) 混用 |
| 图层重复创建 | 分离初始化和更新逻辑 |
| Popup 累积 | 创建前先移除旧 popup |
| 清理不完整 | 完整的 cleanup 函数 |
| 缺少错误处理 | try-catch 包裹初始化 |
| autoFit 跳动 | 移除 autoFit,手动控制视图 |
© antvis, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/l7-single of antvis/L7.
Open the folder on GitHubat commit 6e3dbfe
Antv L7 next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Antv L7 this skillantvis/L7 | 4.1k | — | ~4.4k | Automated safety check: Pass | MIT | |
| Cesium Mapgaopengbin/cesium-mcp | 140 | — | ~964 | Automated safety check: Pass | MIT | |
| Blockbench Pluginsjasonjgardner/blockbench-mcp-plugin | 495 | — | ~2.8k | Automated safety check: Pass | GPL-3.0 | |
| Polycsslayoutit/polycss | 761 | — | ~2.4k | Automated safety check: Pass | MIT | |
| Cesium Quickstartgaopengbin/cesium-mcp | 140 | — | ~354 | Automated safety check: Pass | MIT | |
| Game Enginegithub/awesome-copilot | 40k | 1 repos | ~1.6k | Automated safety check: Pass | MIT |
gaopengbin/cesium-mcp
Open and operate the Cesium MCP 3D map, create map objects and GeoJSON layers, or inspect the selected object in the connected map.
jasonjgardner/blockbench-mcp-plugin
Blockbench plugin/extension development for the 3D modeling tool.
layoutit/polycss
Build PolyCSS scenes that render 3D meshes, primitive shapes, or custom polygons as DOM/CSS polygon elements.
gaopengbin/cesium-mcp
Guide users through their first interaction with the Cesium 3D globe via MCP tools
github/awesome-copilot
Expert skill for building web-based game engines and games using HTML5, Canvas, WebGL, and JavaScript.
scenario-labs/skills
A skill your agent uses when turning a song into a kinetic-typography or motion-design music video, lyric video, visualizer or K-pop style MV with Scenario: a generated subject sheet, style frames…
antvis/L7
Comprehensive guide for AntV L7 geospatial visualization library.
Works with
Categories
基于 WebGL 的大规模地理空间数据可视化引擎。适用于: (1) 创建交互式 WebGL 地图应用 (2) 可视化地理空间数据(点、线、面、热力图) (3) 构建位置数据驾驶舱 (4) 添加地图图层、交互和动画效果 (5) 处理并展示 GeoJSON、CSV 等空间数据. Antv L7 is an agent skill from antvis/L7.
Antv L7 fits situations like: tasks that involve 3D graphics and WebGL; tasks that involve Geospatial analysis; tasks that involve CSV and tabular files.
Run `npx skills add antvis/L7 --skill antv-l7 -a claude-code`. Or copy the skill folder (skills/l7-single in antvis/L7) into .claude/skills/antv-l7 in your project. Claude Code loads it when a task matches its description.
Run `npx skills add antvis/L7 --skill antv-l7 -a codex`. Or copy the skill folder (skills/l7-single in antvis/L7) into .agents/skills/antv-l7 in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add antvis/L7 --skill antv-l7 -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/antv-l7, .gemini/skills/antv-l7, .github/skills/antv-l7 and .opencode/skills/antv-l7 in your project.
SKILL.md names no scripts, command-line tools or credentials: Antv L7 is instructions for the agent only.
SKILL.md names 1 domain. As links in the text: l7.antv.antgroup.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Antv L7 is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.4k tokens (SKILL.md is roughly 18k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Antv L7: Cesium Map (gaopengbin/cesium-mcp, 140 stars), Blockbench Plugins (jasonjgardner/blockbench-mcp-plugin, 495 stars), Polycss (layoutit/polycss, 761 stars) and Cesium Quickstart (gaopengbin/cesium-mcp, 140 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
antvis (a GitHub organization) maintains it in antvis/L7, which has 4,071 GitHub stars. The repository holds 2 skills in this directory. The repository was last updated on September 8, 2026.
Source: antvis/L7 on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.