MapboxGL基础

1. 概述

Mapbox GL 是一套开源库,用于在 Web、移动和桌面应用程序中嵌入可自定义且响应迅速的客户端地图。Mapbox GL 贴图以高帧速率呈现。缩写“GL”来自行业标准的Open Graphics Library (OpenGL)。

Mapbox官网:Mapbox GL JS

Mapbox中文站点:Mapbox

Mapbox GitHub地址:mapbox/mapbox-gl-js: Interactive, thoroughly customizable maps in the browser, powered by vector tiles and WebGL (github.com)

中文站点的官方示例:www.mapbox.cn/mapbox-gl-js/examples/

中文站点的API文档:www.mapbox.cn/mapbox-gl-js/api/

2. 初始化

使用CDN加载MapboxGL :

<link href="https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.js"></script>

使用Mapbox的资源需要申请Token,可以参考:access token | Help | Mapbox

设置Token:

mapboxgl.accessToken = 'pk.eyJ1IjoieWFuZ2ppYW4iLCJhIjoiY2phaG1neno0MXFkNDMzbWhwNWw0bWM4aiJ9.CFmrh0LVWAbmVeed-Xr7wA';

初始化一个地图:

const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [-73.935242, 40.730610],
zoom: 2,
projection: 'globe'
});

具体参数参考:Map | Mapbox GL JS | Mapbox

3. 地图漫游

这里的地图漫游是使用flyTo函数实现:

map.flyTo({
    center: [112.92850, 28.18],
    zoom: 14,
    speed: 0.4,
    pitch: 60,
})

具体参数参考:Map | Mapbox GL JS | Mapbox

4. 地图样式

这里的地图样式是使用·setStyle·函数进行切换:

map.setStyle('mapbox://styles/mapbox/dark-v10')

具体参数参考:Map | Mapbox GL JS | Mapbox

5. 加载地形

参考官方示例:Add 3D terrain to a map | Mapbox GL JS | Mapbox

map.on('load', () => {
map.addSource('mapbox-dem', {
'type': 'raster-dem',
'url': 'mapbox://mapbox.mapbox-terrain-dem-v1',
'tileSize': 512,
'maxzoom': 14
});
// add the DEM source as a terrain layer with exaggerated height
map.setTerrain({ 'source': 'mapbox-dem', 'exaggeration': 1.5 });
})

具体参数参考:Map | Mapbox GL JS | Mapbox

6. 自动旋转

这里的旋转是指按照经纬度进行移动:

function rotate() {
    let center = map.getCenter();
    map.easeTo({
        center: [center.lng + 40, center.lat],
        zoom: 2,
        speed: 0.5
    })
    requestAnimationFrame(rotate);
}

具体参数参考:Map | Mapbox GL JS | Mapbox

7. 地图控件

这里加载有全屏控件、定位控件、比例尺控件、地理搜索控件和导航控件,其中地理搜索控件作为插件需要额外添加CDN:

<!-- Load the `mapbox-gl-geocoder` plugin. -->
<script
        src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
<link rel="stylesheet"
      href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css"
      type="text/css">

添加控件:

map.addControl(new mapboxgl.FullscreenControl());
map.addControl(new mapboxgl.GeolocateControl({
    positionOptions: {
        enableHighAccuracy: true
    },
    trackUserLocation: true
}));
map.addControl(new mapboxgl.ScaleControl({
    maxWidth: 200,
    unit: 'metric'
}), 'bottom-left');
map.addControl(new MapboxGeocoder({
    accessToken: mapboxgl.accessToken,
    mapboxgl: mapboxgl
}), 'top-left');
map.addControl(new mapboxgl.NavigationControl(), 'top-left');

具体参数参考:Map | Mapbox GL JS | Mapbox

8. 相机转动

这里的相机转动是一种视角的转动,使用rotateTo函数实现:

function rotateCamera(timestrip) {
    map.rotateTo(timestrip / 100 % 360, { duration: 0 });
    rotateFlag = requestAnimationFrame(rotateCamera);
}

具体参数参考:Map | Mapbox GL JS | Mapbox

9. 代码小结

上述代码的实现效果可见:Document (mapboxstudy.netlify.app)
上述的全部代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link href="https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.css" rel="stylesheet">
    <script src="https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.js"></script>
    <!-- Load the `mapbox-gl-geocoder` plugin. -->
    <script
        src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
    <link rel="stylesheet"
        href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css"
        type="text/css">
    <div id="info"></div>
    <style>
        #map {
            position: absolute;
            top: 0;
            left: 0;
            height: 100%;
            width: 100%;
        }

        #select_div {
            position: absolute;
            top: 20px;
            right: 168px;
            width: 20px;
            height: 20px;
            z-index: 100;
            border-radius: 20%;
        }

        #coordinate_div {
            position: absolute;
            bottom: 60px;
            left: 20px;
            color: blue;
            z-index: 100;
        }

        #coordinate_div>p {
            margin: 2px;
        }
    </style>

</head>

<body>
    <div id="select_div">
        <select name="" id="select">
            <option value="Select">--Select--</option>
            <option value="streets-v11">streets-v11</option>
            <option value="dark-v10">dark-v10</option>
            <option value="satellite-streets-v11">satellite-streets-v11</option>
        </select>
    </div>
    <div id="coordinate_div">
        <p>Lng: <span id="longitude"></span></p>
        <p>Lat: <span id="latitude"></span></p>
    </div>
    <div id='map'></div>
    <script>
        mapboxgl.accessToken = 'pk.eyJ1IjoieWFuZ2ppYW4iLCJhIjoiY2phaG1neno0MXFkNDMzbWhwNWw0bWM4aiJ9.CFmrh0LVWAbmVeed-Xr7wA';
        const map = new mapboxgl.Map({
            container: 'map',
            style: 'mapbox://styles/mapbox/streets-v11',
            center: [-73.935242, 40.730610],
            zoom: 2,
            projection: 'globe'
        });
        map.addControl(new mapboxgl.FullscreenControl());
        map.addControl(new mapboxgl.GeolocateControl({
            positionOptions: {
                enableHighAccuracy: true
            },
            trackUserLocation: true
        }));
        map.addControl(new mapboxgl.ScaleControl({
            maxWidth: 200,
            unit: 'metric'
        }), 'bottom-left');
        map.addControl(new MapboxGeocoder({
            accessToken: mapboxgl.accessToken,
            mapboxgl: mapboxgl
        }), 'top-left');
        map.addControl(new mapboxgl.NavigationControl(), 'top-left');


        map.on('load', function () {
            rotate();
        })
        map.on('style.load', function () {
            map.setFog({})
        })
        map.on('mousemove', function (e) {
            document.getElementById('longitude').innerHTML = e.lngLat.lng.toFixed(5);
            document.getElementById('latitude').innerHTML = e.lngLat.lat.toFixed(5);
        });
        map.on('click', function (e) {
            if (!initFlag && rotateFlag) {
                // if (rotateFlag) {
                cancelAnimationFrame(rotateFlag);
                rotateFlag = null;
                // } else {
                //     startTime = Date.now();
                //     rotateCamera(Date.now())
                // }
            }
        })
        map.on('move', function (e) {

        })

        document.querySelector('#select').addEventListener('change', function () {
            map.setStyle('mapbox://styles/mapbox/' + this.value);
        })

        setTimeout(() => {
            cancelAnimationFrame(rotateFlag);
            map.flyTo({
                center: [112.92850, 28.18],
                zoom: 14,
                speed: 0.4,
                pitch: 60,
            })
            map.addSource('mapbox-dem', {
                'type': 'raster-dem',
                'url': 'mapbox://mapbox.mapbox-terrain-dem-v1',
                'tileSize': 512,
                'maxzoom': 14
            });
            map.setTerrain({
                source: 'mapbox-dem',
                exaggeration: 2,
            });
            setTimeout(() => {
                initFlag = false;
                startTime = Date.now();
                rotateCamera(Date.now())
            }, 14000)

        }, 20000);


        let rotateFlag = false;
        let initFlag = true;
        let startTime;

        function rotate() {
            let center = map.getCenter();
            map.easeTo({
                center: [center.lng + 40, center.lat],
                zoom: 2,
                speed: 0.5
            })
            rotateFlag = requestAnimationFrame(rotate);
        }

        function rotateCamera(timestrip) {
            map.rotateTo((Date.now() - startTime) / 100 % 360, { duration: 0 });
            rotateFlag = requestAnimationFrame(rotateCamera);
        }
    </script>

</body>

</html>

10. 参考资料

[1]Map | Mapbox GL JS | Mapbox

[2]Examples | Mapbox GL JS | Mapbox

[3]Mapbox

posted @ 2022-07-19 23:05  当时明月在曾照彩云归  阅读(3365)  评论(2编辑  收藏  举报