当前位置: 首页 > news >正文

Mapbox GL初探

一、准备工作

1. 注册Mapbox账号并获取Token
  • 访问 Mapbox官网 注册账号。

  • 在Dashboard中创建新项目,生成Access Token(用于地图初始化)

2.安装Mapbox GL JS

在HTML中引入Mapbox库:

<script src='https://api.mapbox.com/mapbox-gl-js/v3.2.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v3.2.0/mapbox-gl.css' rel='stylesheet' />

二、基础地图展示

1. 初始化地图
<div id="map" style="width: 100%; height: 600px;"></div> <!-- 地图容器 --><script>mapboxgl.accessToken = 'YOUR_ACCESS_TOKEN'; const map = new mapboxgl.Map({container: 'map',          // 容器IDstyle: 'mapbox://styles/mapbox/streets-v12', // 地图样式center: [116.4, 39.9],     // 初始中心点 [经度, 纬度]zoom: 10,                  // 缩放级别pitch: 45,                 // 倾斜角度(3D效果)bearing: -17.6             // 旋转角度});
</script>
2. 添加控件
map.addControl(new mapboxgl.NavigationControl(), 'top-left'); // 缩放/旋转控件
map.addControl(new mapboxgl.ScaleControl()); // 比例尺

三、图层管理:数据展示核心

Mapbox通过数据源(Source) 和 图层(Layer) 分离机制管理地图内容。

1. 数据源类型

2.添加栅格图像 
map.on('load', () => {map.addSource('radar', {'type': 'image','url': 'https://docs.mapbox.com/mapbox-gl-js/assets/radar.gif','coordinates': [[-80.425, 46.437],[-71.516, 46.437],[-71.516, 37.936],[-80.425, 37.936]]});map.addLayer({id: 'radar-layer','type': 'raster','source': 'radar','paint': {'raster-fade-duration': 0,'raster-emissive-strength': 1}});
});
3.自定义编辑

基于Mapbox GL Draw实现绘图组件,支持地图绘制、测量、标签显示功能。同时实现UI和逻辑分离的设计,使用return暴露必要方法给组件。

import { ref } from 'vue';
import MapboxDraw from '@mapbox/mapbox-gl-draw';
import * as turf from '@turf/turf';
import type { FeaturesMeta, MapLabelMeta } from '@/types/map-features';
import type {AllGeoJSON,Feature,FeatureCollection,Geometry,GeometryCollection,LineString
} from '@turf/turf';export const useMapToolBarHook = () => {// 定义 map 和 drawTool 的引用const mapRef = ref<mapboxgl.Map | null>(null);const drawToolRef = ref<MapboxDraw | null>(null);// 清除地图上的测量标签图层与数据源const clearMeasure = (id?: string) => {try {mapRef.value?.removeLayer(id!);mapRef.value?.removeSource(id!);} catch (error) {console.error(error);}};// 初始化地图并绑定绘制事件const initMap = (map: mapboxgl.Map, drawTool: MapboxDraw) => {mapRef.value = map;drawToolRef.value = drawTool;map.addControl(drawTool);map.on('draw.create', createMeasure);map.on('draw.update', updateMeasure);map.on('draw.changeMode', clearMeasure);};// 计算线的中点坐标const getCenterOfLine = (coords: Feature<any> | FeatureCollection<any> | GeometryCollection) => {const totalLength = turf.length(coords, { units: 'kilometers' });const midPoint = turf.along(coords as Feature<LineString>, totalLength / 2);return midPoint.geometry.coordinates;};// 创建地图文本标签const createLabel = (text: string,coords: any,feature: FeaturesMeta) => {const _id = `label-${feature.id}`;const label = {type: 'FeatureCollection',features: [{type: 'Feature',geometry: {type: 'Point',coordinates: coords},properties: { text }}]};mapRef.value?.addSource(_id, { type: 'geojson', data: label });mapRef.value?.addLayer({id: _id,source: _id,type: 'symbol',layout: {'text-field': ['get', 'text'],'text-size': 16,'text-offset': [0, -1]},paint: {'text-color': '#ffffff'}});return label;};// 添加长度标签(单位:km)const addLengthLabel = (length: number,coords: any,feature: FeaturesMeta) => {const label = `${length.toFixed(2)} km`;createLabel(label, coords, feature);};// 添加面积标签(单位:km²)const addAreaLabel = (area: number,coords: any,feature: FeaturesMeta) => {const label = `${area.toFixed(2)} km²`;createLabel(label, coords, feature);};// 创建测量逻辑封装:直接调用 updateMeasureconst createMeasure = (e: any) => {updateMeasure(e, true);};// 更新测量:根据类型计算长度/面积,并添加标签const updateMeasure = (e: any, iscreate = false) => {const features: FeaturesMeta = e.features[0];if (!features) return;// 不是创建行为时,清除旧标签if (!iscreate) clearMeasure(`label-${features.id}`);const handlerMap = {LineString: (feature: FeaturesMeta) => {const length = turf.length(feature, { units: 'kilometers' });const coords = getCenterOfLine(feature);addLengthLabel(length, coords, feature);},Polygon: (feature: FeaturesMeta) => {const area = turf.area(feature as AllGeoJSON) / 1000000;const coords = turf.centroid(feature as AllGeoJSON).geometry.coordinates;addAreaLabel(area, coords, feature);}};const geometryType = features.geometry.type;const handler = (handlerMap as any)[geometryType];if (handler) handler(features);};// 启用绘制多边形模式const drawPolygon = () => {drawToolRef.value?.changeMode('draw_polygon');};// 启用绘制线模式const drawLine = () => {drawToolRef.value?.changeMode('draw_line_string');};// 启用绘制点模式const drawPoint = () => {drawToolRef.value?.changeMode('draw_point');};// 删除选中的绘制元素并清除对应标签const deleteDraw = () => {const ids = drawToolRef.value?.getSelectedIds();if (!ids || ids.length === 0) return;const selection = drawToolRef.value?.getSelected() as MapLabelMeta;if (selection?.features?.length > 0 &&selection.features[0].geometry.type !== 'Point') {clearMeasure(`label-${ids[0]}`);}drawToolRef.value?.delete(ids);};// 将函数暴露给组件外部使用return({initMap,drawPolygon,drawLine,drawPoint,deleteDraw});
}

http://www.dtcms.com/a/278067.html

相关文章:

  • 【unitrix】 5.0 第二套类型级二进制数基本结构体(types2.rs)
  • 16.使用ResNet网络进行Fashion-Mnist分类
  • css如何同时给元素设置背景和背景图?
  • 每日算法刷题Day47:7.13:leetcode 复习完滑动窗口一章,用时2h30min
  • 说实话,统计分析用Python这5个第三方库就够了
  • AutoLabor-ROS-Python 学习记录——第一章 ROS概述与环境搭建
  • PortsSwiggerLab: SSRF with blacklist-based input filter
  • JS进阶-day1 作用域解构箭头函数
  • Spring AI 项目实战(十六):Spring Boot + AI + 通义万相图像生成工具全栈项目实战(附完整源码)
  • NO.5数据结构串和KMP算法|字符串匹配|主串与模式串|KMP|失配分析|next表
  • pthread_mutex_unlock函数的概念和用法
  • 大规模电商系统分库分表实战经验分享
  • NFSV4锁机制(三)
  • 编程技术杂谈2.0
  • DVWA靶场通关笔记-XSS DOM(High级别)
  • 垃圾收集器-Serial Old
  • CVE-2022-0609
  • vue2入门(1)vue核心语法详解复习笔记
  • 【开源项目】网络诊断告别命令行!NetSonar:开源多协议网络诊断利器
  • 1.1.1+1.1.3 操作系统的概念、功能
  • c++无锁队列moodycamel::ConcurrentQueue测试结果
  • 在高并发场景下,仅依赖数据库机制(如行锁、版本控制)无法完全避免数据异常的问题
  • Sping AI Alibaba
  • 第11章 AB实验评估指标体系
  • Soul方程式:Z世代背景下兴趣社交平台的商业模式解析
  • Java行业前景如何?零基础又该如何去学Java?
  • 深入理解 RocketMQ:生产者详解
  • 并行并发丨C++ 协程、现场池 学习笔记
  • 闲庭信步使用图像验证平台加速FPGA的开发:第十三课——图像浮雕效果的FPGA实现
  • 语言模型常用的激活函数(Sigmoid ,GeLU ,SwiGLU,GLU,SiLU,Swish)