Mapbox知识总结

一、基本概述

Mapbox 提供了一系列的工具和服务,用于构建各种与地图相关的应用,从简单的地图展示到复杂的地理信息系统(GIS)应用都可以实现。它支持多种编程语言和开发环境,包括 JavaScript、Python 等,并且提供了丰富的 SDK 和 API,方便开发者集成到自己的项目中。

二、初始化地图

pnpm install  mapbox-gl

首先,需要引入 Mapbox GL JS 的库文件,并设置一个容器来显示地图。

import mapboxgl from "mapbox-gl";
import "mapbox-gl/dist/mapbox-gl.css";

mapboxgl.accessToken = "YOUR_ACCESS_TOKEN";

// 基础初始化
const map = new mapboxgl.Map({
  container: 'map',        // DOM容器ID
  style: 'mapbox://styles/mapbox/streets-v12', // 地图样式
  center: [114.29, 30.59], // 初始中心点 [经度, 纬度]
  zoom: 10,                // 缩放级别(0-22)
  pitch: 45,               // 倾斜角度(3D视图)
  bearing: -17,            // 旋转角度
  projection: 'globe'      // 使用球体投影
});

关键参数说明

  • container: 必须提前在HTML中创建对应id的div容器

  • style: 支持内置样式或自定义样式URL

  • projection: 设为'globe'启用3D地球效果

 三、地图样式

Mapbox 提供了多种内置地图样式,可以通过map.setStyle方法来切换。在 HTML 中通过一个<select>元素来选择不同的样式。

<select id="select">
    <option value="standard">standard</option>
    <option value="standard-satellite">standard-satellite</option>
    <option value="streets-v12">streets-v12</option>
    <option value="outdoors-v12">outdoors-v12</option>
    <option value="light-v11">light-v11</option>
    <option value="dark-v11">dark-v11</option>
    <option value="satellite-v9">satellite-v9</option>
    <option value="satellite-streets-v12">satellite-streets-v12</option>
    <option value="navigation-day-v1">navigation-day-v1</option>
    <option value="navigation-night-v1">navigation-night-v1</option>
</select>
const select = document.getElementById("select");
select.onchange = function () {
    let value = this.value;
    map.setStyle("mapbox://styles/mapbox/" + value);
};

常用内置样式

  • streets-v12(街道图)

  • satellite-v9(卫星图)

  • light-v11(浅色主题)

  • dark-v11(深色主题)

四、加载高德底图

除了 Mapbox 提供的样式,还可以加载其他地图源,如高德地图。通过自定义地图样式的sourceslayers来实现。

// 创建一个 Mapbox 地图实例
const map = new mapboxgl.Map({
    container: "map",
    zoom: 2,
    center: [0, 0],
    projection: "globe",
    // 自定义地图样式
    style: {
        // 指定样式的版本为 8
        version: 8,
        // 定义地图数据源
        sources: {
            tiles: {
                // 数据源类型为栅格数据
                type: "raster",
                // 数据源的瓦片地址,这里使用高德地图的瓦片服务
                tiles: [
                    "http://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}"
                ],
                // 瓦片的尺寸为 256x256 像素
                tileSize: 256
            }
        },
        // 定义地图图层
        layers: [
            {
                // 图层的唯一标识
                id: "my-tiles",
                // 图层使用的数据源
                source: "tiles",
                // 图层类型为栅格图层
                type: "raster"
            }
        ]
    }
});

 五、地球自转效果

 通过不断改变地图中心点的经度,实现地球自转的动画效果。利用requestAnimationFrame来持续更新地图状态。

// 定义一个函数来实现地球自转效果
function spinGlobe() {
    // 获取当前地图的中心点
    let center = map.getCenter();
    // 将中心点的经度- 5,实现地球自西向东转动的效果
    center.lng -= 5;
    // 使用 easeTo 方法平滑地移动地图到新的中心点,动画持续时间为 500 毫秒
    map.easeTo({ center: center, duration: 500 });
    // 使用 requestAnimationFrame 方法在下一帧继续调用 spinGlobe 函数,实现连续的动画效果
    requestAnimationFrame(spinGlobe);
}
// 调用 spinGlobe 函数,开始地球自转动画
spinGlobe();

 六、视图动画

 可以通过操作相机来实现地图的视图动画,如改变俯仰角、方位角,以及平移、旋转等操作。

    <div id="map"></div>
    <div class="btns">
      <button>改变俯仰角</button>
      <button>改变方位角</button>
      <button>北京</button>
    </div>
.btns{
  position: fixed;
  top: 10px;
  right: 10px;
}
// 获取 HTML 中类名为 "btns" 的按钮组中的第一个按钮
const btn1 = document.querySelectorAll(".btns button")[0];
// 获取 HTML 中类名为 "btns" 的按钮组中的第二个按钮
const btn2 = document.querySelectorAll(".btns button")[1];
// 获取 HTML 中类名为 "btns" 的按钮组中的第三个按钮
const btn3 = document.querySelectorAll(".btns button")[2];

// 为第一个按钮的点击事件添加监听器
btn1.onclick = function () {
    // 获取当前地图的俯仰角
    let pitch = map.getPitch();
    // 将俯仰角增加 2 度
    pitch += 2;
    // 使用 setPitch 方法设置地图的新俯仰角
    map.setPitch(pitch);
};

// 为第二个按钮的点击事件添加监听器
btn2.onclick = function () {
    // 获取当前地图的方位角
    let bearing = map.getBearing();
    // 将方位角增加 2 度
    bearing += 2;
    // 使用 setBearing 方法设置地图的新方位角
    map.setBearing(bearing);
};

// 为第三个按钮的点击事件添加监听器
btn3.onclick = function () {
    // 使用 panTo 方法将地图平移到指定的经纬度位置,动画持续时间为 1000 毫秒
    map.panTo([116.46, 39.92], { duration: 1000 });
};

七、GeoJSON数据加载

 可以从网络接口获取 GeoJSON 数据,并将其添加到地图上。通常用于加载矢量数据,如省份边界、城市等。

// 使用 fetch 函数从指定的 URL 获取 GeoJSON 数据
fetch("https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=100000")
    // 将响应数据转换为 JSON 格式
   .then((res) => res.json())
    // 处理转换后的 JSON 数据
   .then((data) => {
        // 向地图中添加一个新的数据源,名为 "china",类型为 GeoJSON,数据为获取到的 GeoJSON 数据
        map.addSource("china", {
            type: "geojson",
            data: data
        });
        // 向地图中添加一个新的图层,名为 "china-layer"
        map.addLayer({
            // 图层的唯一标识
            id: "china-layer",
            // 图层类型为填充图层,用于显示面状要素
            type: "fill",
            // 图层使用的数据源
            source: "china",
            // 图层的绘制样式,这里设置填充颜色为半透明的红色
            paint: {
                "fill-color": "rgba(255,0,0,0.5)"
            }
        });
    });

 八、加载点要素

 在地图上添加点要素,可以是自定义的图标或文本。需要先加载图片,然后通过map.addImage方法将图片添加到地图,再通过map.addLayer添加点要素图层。

// 加载指定路径的图片
map.loadImage("/logo.png", (e, image) => {
    // 如果加载图片过程中出现错误,抛出错误
    if (e) throw e;
    // 将加载好的图片添加到地图中,命名为 "logo"
    map.addImage("logo", image);

    // 定义一个 GeoJSON 格式的点要素集合,包含一个武汉的点要素
    const wuhan = {
        type: "FeatureCollection",
        features: [
            {
                type: "Feature",
                properties: {
                    // 点要素的属性,这里设置名称为 "武汉"
                    name: "武汉"
                },
                geometry: {
                    type: "Point",
                    // 点要素的经纬度坐标
                    coordinates: [114.30246, 30.544783]
                }
            }
        ]
    };

    // 向地图中添加一个新的数据源,名为 "wuhan-logo",类型为 GeoJSON,数据为定义好的点要素集合
    map.addSource("wuhan-logo", {
        type: "geojson",
        data: wuhan
    });

    // 向地图中添加一个新的图层,名为 "wuhan-layer"
    map.addLayer({
        id: "wuhan-layer",
        // 图层类型为符号图层,用于显示点要素
        type: "symbol",
        source: "wuhan-logo",
        layout: {
            // 使用之前添加的图片作为图标
            "icon-image": "logo",
            // 显示点要素的名称属性
            "text-field": ["get", "name"],
            // 文本的大小为 20 像素
            "text-size": 20,
            // 文本相对于图标的偏移量
            "text-offset": [0, 1.5]
        }
    });
});

九、加载线要素

1.Turf.js

Turf.js 是一个强大的用于地理数据计算、处理、统计和分析的 JavaScript 库。

 使用@turf/turf库来创建线要素的 GeoJSON,然后添加到地图上显示。

# get all of turf
npm install @turf/turf

# or get individual packages
npm install @turf/helpers
npm install @turf/buffer
// 引入 @turf/turf 库中的 lineString 函数,用于创建线要素
import { lineString } from "@turf/turf";

// 使用 lineString 函数创建一个从武汉到上海的线要素
const wuhan_shanghai = lineString(
    [
        [114.29, 30.59],
        [121.47, 31.22]
    ],
    { name: "武汉上海线" }
);

// 向地图中添加一个新的数据源,名为 "wuhan_shanghai_line",类型为 GeoJSON,数据为创建好的线要素
map.addSource("wuhan_shanghai_line", {
    type: "geojson",
    data: wuhan_shanghai
});

// 向地图中添加一个新的图层,名为 "line-layer"
map.addLayer({
    id: "line-layer",
    // 图层类型为线图层,用于显示线要素
    type: "line",
    source: "wuhan_shanghai_line",
    paint: {
        // 线的颜色为红色
        "line-color": "red",
        // 线的宽度为 10 像素
        "line-width": 10
    },
    layout: {
        // 线的端点样式为圆形
        "line-cap": "round"
    }
});

2.paint 属性

paint 属性主要用于定义图层的绘制样式,比如颜色、透明度、宽度等视觉效果相关的参数。不同类型的图层(如 filllinesymbol 等)支持不同的 paint 属性。

 填充图层(fill 类型)

map.addLayer({
    id: "area-layer",
    type: "fill",
    source: "area",
    paint: {
        // 设置填充颜色为红色
        "fill-color": "red", 
        // 设置填充的透明度为 0.5
        "fill-opacity": 0.5 
    }
});

 在上述代码中,对于一个填充图层(用于显示面要素),paint 属性中的 "fill-color" 定义了面的填充颜色,"fill-opacity" 定义了填充的透明度。

 线图层(line 类型)

map.addLayer({
    id: "line-layer",
    type: "line",
    source: "wuhan_shanghai_line",
    paint: {
        // 设置线的颜色为红色
        "line-color": "red", 
        // 设置线的宽度为 10 像素
        "line-width": 10, 
        // 设置线的透明度为 0.8
        "line-opacity": 0.8 
    }
});

 对于线图层,paint 属性中的 "line-color" 定义了线的颜色,"line-width" 定义了线的宽度,"line-opacity" 定义了线的透明度。

3.layout 属性

layout 属性主要用于控制图层的布局和排列方式,比如图标、文本的显示位置、大小、方向等。同样,不同类型的图层支持不同的 layout 属性。

 符号图层(symbol 类型)

map.addLayer({
    id: "wuhan-layer",
    type: "symbol",
    source: "wuhan-logo",
    layout: {
        // 使用名为 "logo" 的图标
        "icon-image": "logo", 
        // 显示点要素的 "name" 属性作为文本
        "text-field": ["get", "name"], 
        // 设置文本的字体大小为 20 像素
        "text-size": 20, 
        // 设置文本相对于图标的偏移量,[0, 1] 表示在图标下方
        "text-offset": [0, 1], 
        // 设置文本的旋转角度为 0 度,即不旋转
        "text-rotate": 0 
    }
});

 在符号图层中,layout 属性中的 "icon-image" 定义了要使用的图标,"text-field" 定义了要显示的文本内容,"text-size" 定义了文本的大小,"text-offset" 定义了文本相对于图标的偏移位置,"text-rotate" 定义了文本的旋转角度。

4.总结

  • paint:侧重于图层的视觉绘制效果,控制颜色、透明度、宽度等与外观表现相关的属性。
  • layout:侧重于图层元素的布局和排列,控制图标、文本的显示位置、大小、方向等与布局相关的属性。

十、加载面要素

同样使用@turf/turf库创建面要素的 GeoJSON,并添加到地图。面要素通常使用fill类型的图层。

// 引入 @turf/turf 库中的 polygon 函数,用于创建面要素
import { polygon } from "@turf/turf";

// 使用 polygon 函数创建一个由武汉、上海、北京三个点围成的面要素
const area = polygon(
    [
        [
            [114.29, 30.59],
            [121.47, 31.22],
            [116.46, 40.02],
            [114.29, 30.59]
        ]
    ],
    {
        name: "area"
    }
);

// 向地图中添加一个新的数据源,名为 "area",类型为 GeoJSON,数据为创建好的面要素
map.addSource("area", {
    type: "geojson",
    data: area
});

// 向地图中添加一个新的图层,名为 "area-layer"
map.addLayer({
    id: "area-layer",
    // 图层类型为填充图层,用于显示面要素
    type: "fill",
    source: "area",
    paint: {
        // 面的填充颜色为红色
        "fill-color": "red"
    }
});

 十一、高级功能

1.加载静态图片

可以将静态图片添加到地图上,通过指定图片的 URL 和对应的地理坐标范围。 

map.addSource('satellite-image', {
  type: 'image',
  url: 'image.png',
  coordinates: [
    [113.6545, 31.1774], // 左上
    [115.4234, 31.1774], // 右上
    [115.4234, 29.6061], // 右下
    [113.6545, 29.6061]  // 左下
  ]
});

map.addLayer({
  id: 'overlay-image',
  type: 'raster',
  source: 'satellite-image'
});

 2. 3D地形

// 添加一个地形数据源
map.addSource('mapbox-dem', {  // 'mapbox-dem' 是数据源的唯一标识符
  type: 'raster-dem',          // 数据类型为栅格数字高程模型(DEM)
  url: 'mapbox://mapbox.mapbox-terrain-dem-v1',  // 使用Mapbox提供的地形数据
  tileSize: 512                // 每个瓦片的大小为512x512像素
});

// 设置地图的地形效果
map.setTerrain({
  source: 'mapbox-dem',        // 使用上面定义的 'mapbox-dem' 数据源
  exaggeration: 1.5            // 地形高度夸张系数,1.0为真实高度,1.5表示将地形高度放大1.5倍
});

map.addSource

  • 作用:向地图中添加一个数据源。

  • 参数

    • 'mapbox-dem':数据源的唯一标识符,后续可以通过这个名称引用该数据源。

    • type: 'raster-dem':指定数据类型为栅格数字高程模型(DEM),用于表示地形高度。

    • url: 'mapbox://mapbox.mapbox-terrain-dem-v1':指定数据源的URL,这里是Mapbox提供的地形数据服务。

    • tileSize: 512:每个瓦片的大小为512x512像素,这是Mapbox地形数据的标准瓦片大小。

map.setTerrain

  • 作用:启用地图的地形效果,使地图能够根据地形数据渲染3D地形。

  • 参数

    • source: 'mapbox-dem':指定使用哪个数据源作为地形数据,这里使用上面定义的 mapbox-dem

    • exaggeration: 1.5:地形高度的夸张系数。值为1.0时表示使用真实高度,大于1.0时会放大地形高度,小于1.0时会缩小地形高度。这里设置为1.5,表示地形高度会被放大1.5倍,使地形更加明显。

  • 添加地形数据后,地图会根据地形高度渲染出3D效果,山脉、山谷等地形特征会更加明显。

  • 通过调整 exaggeration 参数,可以控制地形的视觉效果。例如:

    • exaggeration: 1.0:真实地形高度。

    • exaggeration: 2.0:地形高度放大2倍,视觉效果更夸张。

    • exaggeration: 0.5:地形高度缩小为真实高度的一半,视觉效果更平缓。

// 初始化地图
const map = new mapboxgl.Map({
  container: 'map',  // DOM容器ID
  style: 'mapbox://styles/mapbox/streets-v12',  // 地图样式
  center: [-122.42, 37.78],  // 初始中心点(旧金山)
  zoom: 12,  // 缩放级别
  pitch: 60,  // 倾斜角度
  bearing: -17  // 旋转角度
});

// 地图加载完成后执行
map.on('load', () => {
  // 添加地形数据源
  map.addSource('mapbox-dem', {
    type: 'raster-dem',
    url: 'mapbox://mapbox.mapbox-terrain-dem-v1',
    tileSize: 512
  });

  // 启用地形效果
  map.setTerrain({ source: 'mapbox-dem', exaggeration: 1.5 });

  // 添加等高线图层(可选)
  map.addSource('contours', {
    type: 'vector',
    url: 'mapbox://mapbox.mapbox-terrain-v2'
  });

  map.addLayer({
    id: 'contours',
    type: 'line',
    source: 'contours',
    'source-layer': 'contours',
    paint: {
      'line-color': '#877b59',
      'line-width': 1
    }
  });
});

在这个示例中:

  • 地图加载后会显示旧金山地区的地形效果。

  • 通过 pitch 和 bearing 参数设置地图的倾斜和旋转角度,使地形效果更加明显。

  • 可选地添加了等高线图层,进一步增强地形可视化效果。

 十二、标记和弹窗

 通过监听地图的click事件,在点击位置添加标记(Marker)或弹窗(Popup)。

// 为地图的点击事件添加监听器
map.on("click", function (e) {
    // 创建一个新的弹窗实例,设置关闭按钮不可见
    let popup = new mapboxgl.Popup({
        closeButton: false
    });
    // 设置弹窗的位置为点击的经纬度位置
    popup.setLngLat(e.lngLat)
        // 设置弹窗的 HTML 内容,显示点击位置的经纬度
       .setHTML(`<h1>你点击的位置是:${e.lngLat.toString()}</h1>`)
        // 将弹窗添加到地图上
       .addTo(map);
});
// 创建标记
const marker = new mapboxgl.Marker()
  .setLngLat([114.30246, 30.544783])
  .setPopup(new mapboxgl.Popup().setHTML('<h3>武汉市</h3>'))
  .addTo(map);

// 点击事件弹窗
map.on('click', (e) => {
  new mapboxgl.Popup()
    .setLngLat(e.lngLat)
    .setHTML(`坐标:${e.lngLat.lng.toFixed(4)}, ${e.lngLat.lat.toFixed(4)}`)
    .addTo(map);
});

 十三、常用插件

1. 绘图工具(Mapbox Draw)

Mapbox 提供了各种插件来扩展地图功能,如导航、绘制等。以@mapbox/mapbox-gl-draw插件为例,用于在地图上绘制图形。

npm i @mapbox/mapbox-gl-draw
// 引入 Mapbox Draw 插件
import MapboxDraw from "@mapbox/mapbox-gl-draw";
// 引入 Mapbox Draw 插件的 CSS 样式
import "@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css";

// 创建一个 Mapbox Draw 实例
const draw = new MapboxDraw();
// 将 Mapbox Draw 插件添加到地图的右上角
map.addControl(draw, "top-right");

2. 路线规划(Directions)

<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-directions/v4.3.1/mapbox-gl-directions.js"></script>
<link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-directions/v4.3.1/mapbox-gl-directions.css" type="text/css">
<div id="map"></div>
const direction = new MapboxDirections({
  accessToken: mapboxgl.accessToken,
});
map.addControl(direction, "top-left"); //添加一个导航栏

十四、应用场景

  • Web 应用:可以在网站上嵌入交互式地图,为用户提供地理信息展示和查询功能。例如,房地产网站可以在地图上展示房屋的位置和相关信息。
  • 移动应用:通过 Mapbox 的移动 SDK,可以在 iOS 和 Android 应用中集成地图功能。例如,打车应用可以使用地图来显示司机和乘客的位置,以及规划最佳路线。
  • 地理信息系统(GIS):Mapbox 可以作为 GIS 应用的前端展示工具,与后端的 GIS 数据处理和分析系统相结合,实现更复杂的地理信息处理和分析功能。

十五、优势

  • 易于使用:Mapbox 提供了简洁的 API 和丰富的文档,即使是初学者也能快速上手。
  • 高性能:采用了先进的技术和算法,能够快速加载和渲染地图数据,提供流畅的用户体验。
  • 可定制性强:开发者可以根据自己的需求定制地图的样式、功能和交互方式。
  • 社区支持:拥有庞大的开发者社区,开发者可以在社区中分享经验、获取帮助和贡献代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Super毛毛穗

今天晚饭加什么?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值