gis-mapping

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GIS Mapping (Leaflet-First)

GIS地图开发(以Leaflet为核心)

Quick Summary

快速概览

  • Leaflet-first mapping for web apps (default engine)
  • Optional OpenStreetMap tiles or other providers
  • Location selection (marker, polygon, rectangle) + map UI patterns
  • Geofencing enforcement with client + server validation (see geofencing.md)
  • Performance, clustering, and safe storage of spatial data
  • 面向Web应用的以Leaflet为核心的地图开发(默认引擎)
  • 可选OpenStreetMap瓦片或其他服务提供商
  • 位置选择(标记点、多边形、矩形)+ 地图UI模式
  • 结合客户端与服务端验证的地理围栏实施(详见geofencing.md)
  • 空间数据的性能优化、聚类及安全存储

Capability Index (Leaflet-First)

功能索引(以Leaflet为核心)

Use this index to load only the section you need. Details live in skills/gis-mapping/references/leaflet-capabilities.md.
  1. Basic Mapping & Visualization (core Leaflet)
  2. Spatial Queries (Turf.js)
  3. Geocoding (Nominatim or Leaflet Control Geocoder)
  4. Buffering & Zone Analysis (Turf.js)
  5. Heatmaps & Density (leaflet.heat)
  6. Routing & Network Analysis (OSRM / GraphHopper + leaflet-routing-machine)
  7. Drawing & Editing (leaflet.draw / Geoman)
  8. Measurement Tools (leaflet-measure or custom)
  9. Clustering & Aggregation (leaflet.markercluster)
  10. Spatial Analysis (Turf.js)
  11. Time-Based Analysis (custom + heat)
  12. Export & Printing (html2canvas/jsPDF + GeoJSON export)
使用此索引仅加载你需要的模块。详细内容请查看 skills/gis-mapping/references/leaflet-capabilities.md
  1. 基础地图与可视化(核心Leaflet功能)
  2. 空间查询(Turf.js)
  3. 地理编码(Nominatim或Leaflet Control Geocoder)
  4. 缓冲区与区域分析(Turf.js)
  5. 热力图与密度分析(leaflet.heat)
  6. 路径规划与网络分析(OSRM / GraphHopper + leaflet-routing-machine)
  7. 绘图与编辑(leaflet.draw / Geoman)
  8. 测量工具(leaflet-measure或自定义实现)
  9. 聚类与聚合(leaflet.markercluster)
  10. 空间分析(Turf.js)
  11. 基于时间的分析(自定义实现+热力图)
  12. 导出与打印(html2canvas/jsPDF + GeoJSON导出)

When to Use

适用场景

  • You need interactive maps for customers, assets, farms, or delivery zones
  • Users must select or edit locations on a map
  • You must enforce geo-fencing or boundary validation
  • You need GIS data display with filters, legends, and clustering
  • 需为客户、资产、农场或配送区域提供交互式地图
  • 用户需要在地图上选择或编辑位置
  • 必须实施地理围栏或边界验证
  • 需要结合筛选器、图例和聚类功能展示GIS数据

Key Patterns

核心模式

  • Leaflet is the default mapping engine.
  • Always include attribution for the chosen tile provider.
  • Capture geometry in GeoJSON and validate server-side.
  • Use bounding-box checks before deeper polygon math.
  • Cluster markers when data is large or dense.
  • Store optional tile provider API keys in system settings (e.g.,
    osm_api_key
    ) and load them at runtime.
  • Default to terrain tiles (OpenTopoMap) for administrative borders.
  • Leaflet为默认地图引擎
  • 必须为所选瓦片服务提供商添加版权声明
  • 以GeoJSON格式捕获几何数据并在服务端验证
  • 在进行深度多边形计算前先使用边界框检查
  • 当数据量大或密集时使用标记聚类
  • 将可选瓦片服务提供商的API密钥存储在系统设置中(如
    osm_api_key
    )并在运行时加载
  • 默认使用地形瓦片(OpenTopoMap)展示行政边界

Leaflet Standardization (BIRDC)

Leaflet标准化规范(BIRDC)

  • Use a shared Leaflet configuration for tile URLs, attribution, and defaults.
  • Prefer a shared loader or include pattern so Leaflet CSS/JS is consistent across pages.
  • Use public/farmer-profile.php as the canonical Leaflet UI reference.
  • 为瓦片URL、版权声明和默认配置使用共享的Leaflet配置
  • 优先使用共享加载器或引入模式,确保Leaflet CSS/JS在各页面保持一致
  • public/farmer-profile.php作为Leaflet UI的标准参考实现

Stack Choices (Frontend)

技术栈选择(前端)

  • Leaflet (default): Lightweight, fastest to implement, best for most apps.
  • OpenLayers (optional): Heavyweight GIS controls and projections.
  • MapLibre GL JS (optional): Vector tiles, smoother at scale.
  • Leaflet(默认):轻量、易于实现,适用于大多数应用
  • OpenLayers(可选):提供重量级GIS控件和投影支持
  • MapLibre GL JS(可选):支持矢量瓦片,大规模场景下更流畅

Data Model & Storage

数据模型与存储

  • Point:
    latitude
    +
    longitude
    (DECIMAL(10,7))
  • Polygon/Boundary: Store as GeoJSON (TEXT/JSON)
  • Metadata:
    location_label
    ,
    address
    ,
    last_updated_at
Recommended formats:
  • GeoJSON for portability across JS + backend
  • WKT only if your DB tooling depends on it
  • 点数据
    latitude
    +
    longitude
    (DECIMAL(10,7)类型)
  • 多边形/边界:以GeoJSON格式存储(TEXT/JSON类型)
  • 元数据
    location_label
    address
    last_updated_at
推荐格式:
  • 跨JS与后端的可移植性优先选择GeoJSON
  • 仅当数据库工具依赖时使用WKT格式

Map Initialization (Leaflet)

地图初始化(Leaflet)

html
<link
  rel="stylesheet"
  href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
/>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
javascript
const map = L.map("map").setView([0.3476, 32.5825], 12);
const osmApiKey = window.osmApiKey || "";
const osmTileUrl = osmApiKey
  ? `https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?api_key=${osmApiKey}`
  : "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";

const osm = L.tileLayer(osmTileUrl, {
  attribution: "© OpenStreetMap contributors",
  maxZoom: 19,
});

const terrain = L.tileLayer(
  "https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png",
  {
    attribution: "© OpenTopoMap",
    maxZoom: 17,
  },
);

terrain.addTo(map);
html
<link
  rel="stylesheet"
  href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
/>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
javascript
const map = L.map("map").setView([0.3476, 32.5825], 12);
const osmApiKey = window.osmApiKey || "";
const osmTileUrl = osmApiKey
  ? `https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?api_key=${osmApiKey}`
  : "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";

const osm = L.tileLayer(osmTileUrl, {
  attribution: "© OpenStreetMap contributors",
  maxZoom: 19,
});

const terrain = L.tileLayer(
  "https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png",
  {
    attribution: "© OpenTopoMap",
    maxZoom: 17,
  },
);

terrain.addTo(map);

Location Selection Patterns

位置选择模式

Marker (Point)

标记点(Point)

  • Single click adds/updates a marker
  • Store coordinates in hidden inputs
javascript
let marker;
map.on("click", (e) => {
  if (marker) map.removeLayer(marker);
  marker = L.marker(e.latlng).addTo(map);
  document.querySelector("#latitude").value = e.latlng.lat;
  document.querySelector("#longitude").value = e.latlng.lng;
});
  • 单击添加/更新标记
  • 将坐标存储在隐藏输入框中
javascript
let marker;
map.on("click", (e) => {
  if (marker) map.removeLayer(marker);
  marker = L.marker(e.latlng).addTo(map);
  document.querySelector("#latitude").value = e.latlng.lat;
  document.querySelector("#longitude").value = e.latlng.lng;
});

Polygon / Rectangle (Area)

多边形 / 矩形(区域)

Use Leaflet Draw or Geoman. Store GeoJSON geometry.
javascript
const drawn = new L.FeatureGroup().addTo(map);
const drawControl = new L.Control.Draw({
  draw: { polygon: true, rectangle: true, marker: false, circle: false },
  edit: { featureGroup: drawn },
});
map.addControl(drawControl);

map.on("draw:created", (e) => {
  drawn.clearLayers();
  drawn.addLayer(e.layer);
  document.querySelector("#boundary_geojson").value = JSON.stringify(
    e.layer.toGeoJSON(),
  );
});
使用Leaflet Draw或Geoman工具。以GeoJSON格式存储几何数据。
javascript
const drawn = new L.FeatureGroup().addTo(map);
const drawControl = new L.Control.Draw({
  draw: { polygon: true, rectangle: true, marker: false, circle: false },
  edit: { featureGroup: drawn },
});
map.addControl(drawControl);

map.on("draw:created", (e) => {
  drawn.clearLayers();
  drawn.addLayer(e.layer);
  document.querySelector("#boundary_geojson").value = JSON.stringify(
    e.layer.toGeoJSON(),
  );
});

Geofencing (Overview)

地理围栏(概述)

Geofencing must be enforced at two levels:
  • UI constraint: prevent invalid selections in the browser
  • Server constraint: verify boundaries in backend validation
See geofencing.md for full patterns, point-in-polygon checks, and multi-geometry rules.
地理围栏必须在两个层面实施:
  • UI约束:在浏览器中阻止无效选择
  • 服务端约束:在后端验证边界
详见geofencing.md获取完整模式、点-in-多边形检查及多几何规则。

UI Patterns

UI模式

  • Filters + stats in a side card, map in a large canvas
  • Legend to toggle categories (customer groups, territories)
  • Clustering when markers exceed ~200
  • 侧边栏卡片展示筛选器和统计数据,地图占据主画布
  • 图例用于切换分类(客户组、区域)
  • 当标记数量超过约200个时使用聚类

Performance & UX

性能与用户体验

  • Debounce search and map redraw
  • Use marker clustering or server-side tiling
  • Lazy load heavy layers
  • Simplify large polygons for UI display
  • 对搜索和地图重绘操作做防抖处理
  • 使用标记聚类或服务端瓦片
  • 懒加载重型图层
  • 简化大型多边形以适配UI显示

Backend Validation

后端验证

Always validate coordinates server-side:
  • Ensure latitude is between -90 and 90
  • Ensure longitude is between -180 and 180
  • Enforce geofence boundaries with the same logic as UI
  • Load optional tile provider keys (for example
    osm_api_key
    ) from system settings when building map pages
务必在服务端验证坐标:
  • 确保纬度在-90到90之间
  • 确保经度在-180到180之间
  • 使用与UI相同的逻辑实施地理围栏边界验证
  • 构建地图页面时从系统设置加载可选瓦片服务密钥(如
    osm_api_key

Privacy & Security

隐私与安全

  • Location data is sensitive: protect with permissions
  • Never trust client-only validation
  • Avoid exposing private coordinates without authorization
  • 位置数据属于敏感信息:需通过权限保护
  • 绝不能仅依赖客户端验证
  • 未经授权避免暴露私有坐标

Recommended Plugins

推荐插件

  • Leaflet Draw or Leaflet Geoman (drawing tools)
  • Leaflet MarkerCluster (performance)
  • Leaflet Control Geocoder (search)
  • Turf.js (geospatial analysis)
  • Leaflet Draw或Leaflet Geoman(绘图工具)
  • Leaflet MarkerCluster(性能优化)
  • Leaflet Control Geocoder(搜索功能)
  • Turf.js(地理空间分析)

References

参考资料

  • geofencing.md (sub-skill)
  • references/leaflet-capabilities.md
  • references/leaflet-arcgis-equivalents.md (index)
  • geofencing.md(子技能)
  • references/leaflet-capabilities.md
  • references/leaflet-arcgis-equivalents.md(索引)