Agent skill

Antv L7

by antvis in antvis/L7

基于 WebGL 的大规模地理空间数据可视化引擎。适用于: (1) 创建交互式 WebGL 地图应用 (2) 可视化地理空间数据(点、线、面、热力图) (3) 构建位置数据驾驶舱 (4) 添加地图图层、交互和动画效果 (5) 处理并展示 GeoJSON、CSV 等空间数据

MITAuto-check passedGame Development

Install Antv L7

skills CLI
$ npx skills add antvis/L7 --skill antv-l7 -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install antvis/L7 antv-l7 --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ 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-src

Use ~/.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/

Facts

Skill name
antv-l7
GitHub stars
4.1k
Token cost
~4.4k tokens
SKILL.md length
422 words
Files
1
Skills in repo
2
Repo updated
First seen
Licence
MIT

At a glance

基于 WebGL 的大规模地理空间数据可视化引擎。适用于: (1) 创建交互式 WebGL 地图应用 (2) 可视化地理空间数据(点、线、面、热力图) (3) 构建位置数据驾驶舱 (4) 添加地图图层、交互和动画效果 (5) 处理并展示 GeoJSON、CSV 等空间数据

  • Works in 4 steps: 单次初始化:地图场景只初始化一次 → 图层分离:数据更新时只更新图层,不重建地图 → 完整清理:组件卸载时清理所有资源 → …
  • Tasks that involve 3D graphics and WebGL
  • SKILL.md covers ⚠️ 重要约束, 选型指南, React 最佳实践 and Core Workflow, plus 6 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

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.

When your agent uses it

  • Tasks that involve 3D graphics and WebGL
  • Tasks that involve Geospatial analysis
  • Tasks that involve CSV and tabular files

Example prompts

  • “/antv-l7”

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. 单次初始化:地图场景只初始化一次
  2. 图层分离:数据更新时只更新图层,不重建地图
  3. 完整清理:组件卸载时清理所有资源
  4. 错误处理:捕获初始化异常

What it can do on your machine

Read from SKILL.md and the folder at commit 6e3dbfe. It shows what the files ask for, not the result of running them.

  • Tool permissions

    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.

  • Runs code

    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.

  • Network

    Links to these hosts (documentation or services it may open):

    • l7.antv.antgroup.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

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.

Always · name and description, kept in context so the agent knows when to use it
~36
When it runs · the whole SKILL.md, loaded when a task matches
~4.4k

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.

Safety

Auto-check passed

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.

SKILL.md

The full file from antvis/L7 at commit 6e3dbfe, republished under its MIT licence (© antvis). 422 words, ~4,408 tokens.

Download SKILL.mdSave it as .claude/skills/antv-l7/SKILL.md (or your agent's skills folder).
name
antv-l7
description
基于 WebGL 的大规模地理空间数据可视化引擎。适用于: (1) 创建交互式 WebGL 地图应用 (2) 可视化地理空间数据(点、线、面、热力图) (3) 构建位置数据驾驶舱 (4) 添加地图图层、交互和动画效果 (5) 处理并展示 GeoJSON、CSV 等空间数据
title
AntV L7 地理空间可视化
license
MIT

AntV L7 地理空间可视化

AntV L7 是基于 WebGL 的大规模地理空间数据可视化引擎,支持多种地图底图和丰富的可视化图层类型。

⚠️ 重要约束

作用域声明:以下约束仅适用于 WeaveFox(本仓库)环境。

在 WeaveFox 环境下,高德地图配置禁止传入 token 参数。

在 WeaveFox 项目中,L7 已配置默认 token。在该环境下,GaodeMap 配置中不要设置 token 字段,否则会导致地图加载失败。

javascript
// ✅ 正确 - 不传 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', // 不要这样做!
});

选型指南

简单点位展示(< 100 个点)

优先使用 Marker,而非 PointLayer:

javascript
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 对比:

特性MarkerPointLayer
适用场景< 100 个点位> 100 个点位/大规模数据
性能DOM 渲染,轻量WebGL 渲染,高性能
交互原生 DOM 事件,灵活需绑定图层事件
自定义支持任意 HTML/CSS受限于 L7 样式配置
Popup内置支持需额外配置
大规模数据可视化(> 100 个点)

使用 PointLayer 进行 WebGL 渲染:

javascript
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 最佳实践

核心原则
  1. 单次初始化:地图场景只初始化一次
  2. 图层分离:数据更新时只更新图层,不重建地图
  3. 完整清理:组件卸载时清理所有资源
  4. 错误处理:捕获初始化异常
硬性规则(防止重复初始化)

以下规则为强约束,生成 React + L7 代码时必须遵守:

  1. 初始化 effect 必须空依赖:创建 new Scene() 的 useEffect 依赖必须是 []。
  2. 禁止在初始化 effect 依赖中放业务状态:例如 selectedId、筛选条件、分页参数。
  3. 禁止在初始化 effect 依赖中放易变回调:例如来自父组件的 onSelect、onClick、onChange。
  4. 状态更新走独立 effect:选中态、数据源、样式变化只能更新图层/Marker,不得 destroy + new Scene。
  5. 最新值使用 ref:loaded 回调里若需要最新 props,使用 latestXxxRef.current,不要依赖闭包旧值。
  6. 清理只在卸载时执行:scene.destroy() 只能放在初始化 effect 的 cleanup 中,不能由状态变化触发。
  7. 严格区分初始化与更新职责:初始化负责 Scene/Layer 首建,更新负责 setData、更新 Marker 或样式。
  8. Popup 锚点默认规则:点位/Marker 场景默认使用 anchor: 'bottom',让弹窗显示在点位上方。
  9. Popup 方案必须单一:统一使用 scene.addPopup(...),禁止与 marker.setPopup(...)、popup.addTo(scene) 混用。
  10. Popup 必须单实例:创建新 popup 前先 scene.removePopup(oldPopup),避免页面出现多个弹窗。
  11. Marker 形态优先尖角样式:优先使用“气泡主体 + 尖角(pointer)”图标,尖角必须指向真实经纬度点。
  12. Marker 锚点必须与尖角一致:尖角在元素底部时,anchor 必须使用 'bottom',禁止使用 'center' 导致点位偏移。
  13. Marker 文案对齐规则:文字描述必须在 Marker 主体内水平居中,主体中心与实际点位保持视觉对称。
  14. 多行文案稳定规则:文案允许换行时,主体必须设置 max-width 与 word-break,且尖角保持 margin: 0 auto 居中,防止尖角偏离点位。
  15. 应用 UI 层级规则:地图应用的信息面板、Sidebar、模态框等非地图组件必须设置 z-index >= 1000,确保显示在地图 logo 和其他地图固定元素之上。
  16. Popup 关闭按钮规则:创建 Popup 时必须启用 closeButton: true,允许用户点击关闭按钮关闭弹窗,提升交互体验。
  17. Popup 相对位置规则:Popup 必须显示在 Marker/点位上方,需使用 offset: [0, -40] 向上移动,避免与 Marker 气泡重叠遮挡。

反例(禁止):

typescript
// 会导致 selectedId 变化时反复销毁并重建 Scene
useEffect(() => {
  const scene = new Scene(...);
  return () => scene.destroy();
}, [selectedId, onSelectLocation]);

正例(推荐):

typescript
// 只初始化一次
useEffect(() => {
  const scene = new Scene(...);
  return () => scene.destroy();
}, []);

// 状态变化只更新图层,不重建 Scene
useEffect(() => {
  pointLayerRef.current?.setData(nextData);
}, [nextData]);

说明:React 18 开发环境 StrictMode 会对 mount 做额外检查,可能看到两次初始化日志。只要初始化 effect 为空依赖且职责正确,生产环境不会因此重复重建。

Marker 样式约束(尖角指向点位)

当使用自定义 Marker DOM 时,默认采用“主体 + 尖角”结构:

typescript
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))。
使用 Marker(< 100 个点)
typescript
'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 保存实例数组,用于数据更新时清理旧 marker
  • scene.addMarker(marker) 必须用它,.addTo(scene) 不会注册相机事件,导致 marker 与地图不同步
  • Popup 统一使用 scene.addPopup(...),不要和 marker.setPopup(...) 混用
  • 点位弹窗默认 anchor: 'bottom',确保弹窗显示在 marker 上方
  • 组件卸载时遍历 markersRef.current 逐一 remove()
Show full SKILL.md (168 more words)Show less
使用 PointLayer(> 100 个点)
typescript
'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' }}
    />
  );
}

Core Workflow

L7 的典型开发流程:

1. 场景初始化 (Scene) → 2. 数据准备 → 3. 创建图层 (Layer) → 4. 添加交互 → 5. 优化性能

支持的图层类型

基础图层
图层类型说明适用场景
PointLayer点图层散点、气泡、符号、文本标注
LineLayer线图层路径、弧线、流向线、3D 弧墙
PolygonLayer面图层区域填充、3D 挤出、海面效果
HeatmapLayer热力图密度分布、聚合热力
高级图层
图层类型说明适用场景
RasterLayer栅格图层卫星影像、地形高程
ImageLayer图片图层单张图片叠加
WindLayer风场图层风向、气流可视化
CityBuildingLayer建筑图层3D 城市建筑、扫描光效果
CanvasLayerCanvas 图层自定义 Canvas 绘制
EarthLayer地球图层3D 地球、大气层效果
MarkerDOM 标注少量点位、自定义 DOM
PointLayer shape 类型
typescript
.shape('circle')      // 圆形
.shape('square')      // 方形
.shape('triangle')    // 三角形
.shape('text')        // 文本标注
.shape('image')       // 图片图标
.shape('cylinder')    // 3D 圆柱
LineLayer shape 类型
typescript
.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 }
数据变换 (Transforms)
typescript
.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
    },
  ],
})

常用控件

typescript
// 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 API

地图控制
typescript
// 设置中心点
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();
导出功能
typescript
// 导出为 PNG
const png = await scene.exportPng('png');

// 导出地图(含底图)
const mapImage = await scene.exportMap('png');
交互方法
typescript
// 高亮
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

Files

Just SKILL.md in skills/l7-single of antvis/L7.

Open the folder on GitHubat commit 6e3dbfe

Compare with similar skills

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.

Antv L7 compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Antv L7 this skillantvis/L74.1k—~4.4kAutomated safety check: PassMIT
Cesium Mapgaopengbin/cesium-mcp140—~964Automated safety check: PassMIT
Blockbench Pluginsjasonjgardner/blockbench-mcp-plugin495—~2.8kAutomated safety check: PassGPL-3.0
Polycsslayoutit/polycss761—~2.4kAutomated safety check: PassMIT
Cesium Quickstartgaopengbin/cesium-mcp140—~354Automated safety check: PassMIT
Game Enginegithub/awesome-copilot40k1 repos~1.6kAutomated safety check: PassMIT

Similar skills

  • 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.

    140 GitHub stars~964 tokensUpdated yesterday
    Data & AnalyticsAuto-check passed
  • Blockbench Plugins

    jasonjgardner/blockbench-mcp-plugin

    Blockbench plugin/extension development for the 3D modeling tool.

    495 GitHub stars~2.8k tokensUpdated 8 days ago
    Game DevelopmentAuto-check passed
  • Polycss

    layoutit/polycss

    Build PolyCSS scenes that render 3D meshes, primitive shapes, or custom polygons as DOM/CSS polygon elements.

    761 GitHub stars~2.4k tokensUpdated 1 mo ago
    Game DevelopmentAuto-check passed
  • Cesium Quickstart

    gaopengbin/cesium-mcp

    Guide users through their first interaction with the Cesium 3D globe via MCP tools

    140 GitHub stars~354 tokensUpdated yesterday
    Agent WorkflowsAuto-check passed
  • Game Engine

    github/awesome-copilot

    Official

    Expert skill for building web-based game engines and games using HTML5, Canvas, WebGL, and JavaScript.

    40k GitHub starsUsed in 1 repo~1.6k tokens
    Game DevelopmentAuto-check passed
  • Scenario Kinetic Music Video

    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…

    931 GitHub stars~3.5k tokensUpdated yesterday
    Game DevelopmentAuto-check passed

More from antvis/L7

  • Antv L7

    antvis/L7

    Comprehensive guide for AntV L7 geospatial visualization library.

    4.1k GitHub stars~1.4k tokensUpdated 1 mo ago
    Auto-check passed

Questions about Antv L7

What does Antv L7 do?

基于 WebGL 的大规模地理空间数据可视化引擎。适用于: (1) 创建交互式 WebGL 地图应用 (2) 可视化地理空间数据(点、线、面、热力图) (3) 构建位置数据驾驶舱 (4) 添加地图图层、交互和动画效果 (5) 处理并展示 GeoJSON、CSV 等空间数据. Antv L7 is an agent skill from antvis/L7.

When should I use Antv 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.

How do I install Antv L7 in Claude Code?

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.

How do I install Antv L7 in Codex?

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.

Can I use Antv L7 in Cursor, Gemini CLI or GitHub Copilot?

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.

What does Antv L7 need to run?

SKILL.md names no scripts, command-line tools or credentials: Antv L7 is instructions for the agent only.

Does Antv L7 access the network?

SKILL.md names 1 domain. As links in the text: l7.antv.antgroup.com. This is read from the text; nothing was executed.

Is Antv L7 safe to install?

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.

What licence does Antv L7 use?

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.

How many tokens does Antv L7 use?

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.

What are the alternatives to Antv L7?

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.

Who maintains Antv L7?

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.