Mapbox gl HTML经纬度点渲染,动态轨迹播放,自定义图形以及轨迹上显示箭头方向

Mapbox gl HTML经纬度点渲染,动态轨迹播放,自定义图形以及轨迹上显示箭头方向

今天要排查个问题,需要显示多个经纬度点连接成线段的方向,于是尝试下展示。

1. mapbox渲染经纬度点,线,多线,面
2. 运动轨迹增加箭头方向
3. 增加一个图像(如小车等)本文用的tomcat小猫图标,实行运动轨迹可控制,开始,播放,停止

1. 效果图

线渲染:

在这里插入图片描述

点、线渲染:

在这里插入图片描述

增加箭头显示方向,以及tomcat小猫播放:

在这里插入图片描述
轨迹播放中截图:

在这里插入图片描述

在这里插入图片描述

增加轨迹方向箭头及小猫播放中截图如下:
在这里插入图片描述
修改地图背景色,实时轨迹线颜色,播放中截图如下:
在这里插入图片描述

2. 源码

2.1 line.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Add a GeoJSON line</title>
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <link href="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.css" rel="stylesheet">
    <script src="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.js"></script>
    <style>
        body {
            margin: 0;
            padding: 0;
        }

        #map {
            position: absolute;
            top: 0;
            bottom: 0;
            width: 100%;
        }
    </style>
</head>
<body>
<div id="map"></div>
<script>
    // TO MAKE THE MAP APPEAR YOU MUST
    // ADD YOUR ACCESS TOKEN FROM
    // https://account.mapbox.com
    mapboxgl.accessToken = 'pk.eyJ1******************Lc99g';
    var map = new mapboxgl.Map({
        container: 'map',
        style: 'mapbox://styles/mapbox/streets-v11',
// center: [-122.486052, 37.830348],
// center: [116.239749,40.0717456],
// center: [117.85448020099696,35.96263648233899],
        center: [116.25456103528076, 40.07649758667226],
        zoom: 14
    });

    map.on('load', function () {
        map.addSource('route', {
            'type': 'geojson',
            'data': {
                'type': 'FeatureCollection',
                'features': [
                    {
                        'type': 'Feature',
                        'properties': {},
                        'geometry': {
                            'type': 'LineString',
                            'coordinates': [[116.25456103528076, 40.07649758667226, 32.60466429684311],
                                [116.25459033603693, 40.076511383622965, 32.46827581245452],
                                [116.25455860845449, 40.07650334314173, 32.52390295546502],
                                [116.25460283054188, 40.07651455000795, 32.44636987615377]]
                        }
                    },
                    {
                        'type': 'Feature',
                        'geometry': {
                            'type': 'Point',
                            'coordinates': [116.25456103528076, 40.07649758667226, 32.60466429684311]
                        }
                    },
                    {
                        'type': 'Feature',
                        'geometry': {
                            'type': 'Point',
                            'coordinates': [116.25459033603693, 40.076511383622965, 32.46827581245452]
                        }
                    },
                    {
                        'type': 'Feature',
                        'geometry': {
                            'type': 'Point',
                            'coordinates': [116.25455860845449, 40.07650334314173, 32.52390295546502]
                        }
                    },
                    {
                        'type': 'Feature',
                        'geometry': {
                            'type': 'Point',
                            'coordinates': [116.25460283054188, 40.07651455000795, 32.44636987615377]
                        }
                    }
                ]
            }
        });
        map.addLayer({
            'id': 'route',
            'type': 'line',
            'source': 'route',
            'layout': {
                'line-join': 'round',
                'line-cap': 'round'
            },
            'paint': {
                'line-color': '#DC143C',
                'line-width': 5
            }
        });

        map.addLayer({
            'id': 'routePoint',
            'type': 'circle',
            'source': 'route',
            'paint': {
                'circle-radius': 6,
                'circle-color': '#0000FF'
            },
            'filter': ['==', '$type', 'Point']
        });
    });
</script>

</body>
</html>

2.2 line_arrow.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Add a GeoJSON line,with Arrow</title>
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <link href="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.css" rel="stylesheet">
    <script src="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.js"></script>
    <script src="https://unpkg.com/@turf/turf@6.3.0/turf.min.js"></script>
    <style>
        body {
            margin: 0;
            padding: 0;
        }

        .menuBar {
            position: relative;
            top: 10px;
            margin: 0 50px;
            padding: 5px;
            border-radius: 3px;
            z-index: 999;
            background-color: rgba(0, 168, 0, 0.7);
        }

        input[type=button] {
            font-size: 16px;
        }

        #map {
            position: absolute;
            top: 0;
            bottom: 0;
            width: 100%;
        }

        /* 删除mapbox logo */
        .mapboxgl-ctrl {
            display: none !important;
        }
    </style>
</head>

<body>
<div id="map"></div>
<div class="menuBar">
    <input type="button" value="开始" onclick="startClick()"/>
    <input type="button" value="暂停" onclick="pauseClick()"/>
    <input type="button" value="停止" onclick="stopClick()"/>
    <div id="canvas"></div>
</div>
<script>
    // TO MAKE THE MAP APPEAR YOU MUST ADD YOUR ACCESS TOKEN FROM
    // https://account.mapbox.com
    mapboxgl.accessToken = 'pk.eyJ********';
    var map = new mapboxgl.Map({
        container: 'map',
        style: 'mapbox://styles/mapbox/streets-v11',
        // center: [116.25456103528076, 40.07649758667226],
        // zoom: 24
        center: [116.390619, 39.924317], // starting position [lng, lat]
        zoom: 13 // starting zoom
    });
    // 背景色
    // map.setStyle('mapbox://styles/mapbox/dark-v9');

    // 箭头-右
    var svgXML =
        `<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
                <path d="M529.6128 512L239.9232 222.4128 384.7168 77.5168 819.2 512 384.7168 946.4832 239.9232 801.5872z" p-id="9085" fill="#ff00ff"></path>
            </svg>
            `
    //给图片对象写入base64编码的svg流
    var svgBase64 = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svgXML)));

    map.on('load', function () {
        let arrowIcon = new Image(20, 20)
        arrowIcon.src = svgBase64
        arrowIcon.onload = function () {
            map.addImage('arrowIcon', arrowIcon)
            console.log("----------1 " + arrowIcon)
            map.loadImage('img/arrowR.png', function (error, arrowIcon2) {
                if (arrowIcon2) {
                    map.addImage('arrowIcon2', arrowIcon2);
                }
            })
            map.loadImage('img/car.png', function (error, carIcon) {
                if (carIcon) {
                    console.log("----------2 " + arrowIcon)
                    map.addImage('carIcon', carIcon);
                    setRouteData()
                }
                console.log("----------3 " + arrowIcon)
            });
        }
    })

    var isPlay = false
    var counter = 0
    var steps = 0
    let aLength = 0;
    var routeGeoJson = {
        'type': 'FeatureCollection',
        'features': [{
            'type': 'Feature',
            'geometry': {
                'type': 'LineString',
                'coordinates': [
                    [116.391844, 39.898457],
                    [116.377947, 39.898595],
                    [116.368001, 39.898341],
                    [116.357144, 39.898063],
                    [116.351934, 39.899095],
                    [116.35067, 39.905871],
                    [116.3498, 39.922329],
                    [116.349671, 39.931017],
                    [116.349225, 39.939104],
                    [116.34991, 39.942233],
                    [116.366892, 39.947263],
                    [116.387537, 39.947568],
                    [116.401988, 39.947764],
                    [116.410824, 39.947929],
                    [116.42674, 39.947558],
                    [116.427338, 39.9397],
                    [116.427919, 39.932404],
                    [116.428377, 39.923109],
                    [116.429583, 39.907094],
                    [116.41404, 39.906858],
                    [116.405321, 39.906622],
                    [116.394954, 39.906324],
                    [116.391264, 39.906308],
                    [116.390748, 39.916611]
                ]
                /*[
                    [116.25456103528076, 40.07649758667226, 32.60466429684311],
                    [116.25459033603693, 40.076511383622965, 32.46827581245452],
                    [116.25455860845449, 40.07650334314173, 32.52390295546502],
                    [116.25460283054188, 40.07651455000795, 32.44636987615377]
                ]*/
            }
        }]
    }

    var realRouteGeoJson = {
        'type': 'FeatureCollection',
        'features': [{
            'type': 'Feature',
            'geometry': {
                'type': 'LineString',
                'coordinates': []
            }
        }]
    }

    var animatePointGeoJson = {
        'type': 'FeatureCollection',
        'features': [{
            'type': 'Feature',
            'properties': {},
            'geometry': {
                'type': 'Point',
                'coordinates': []
            }
        }]
    }

    // 获取轨迹数据
    function setRouteData() {
        animatePointGeoJson.features[0].geometry.coordinates = routeGeoJson.features[0].geometry.coordinates[0]
        aLength = routeGeoJson.features[0].geometry.coordinates.length;
        newRouteGeoJson = resetRoute(routeGeoJson.features[0], 1000, 'kilometers')
        steps = newRouteGeoJson.geometry.coordinates.length

        addRoutelayer() // 添加轨迹线图层
        addRealRouteSource() // 添加实时轨迹线图层
        addArrowlayer() // 添加箭头图层
        addAnimatePointSource() // 添加动态点图层
    }

    // 添加轨迹线图层
    function addRoutelayer() {
        map.addLayer({
            'id': 'routeLayer',
            'type': 'line',
            'source': {
                'type': 'geojson',
                'lineMetrics': true,
                'data': routeGeoJson
            },
            'paint': {
                'line-width': 10,
                'line-opacity': 1,
                'line-color': '#009EFF',
            }
        });
    }

    // 添加实时轨迹线
    function addRealRouteSource() {
        map.addLayer({
            'id': 'realRouteLayer',
            'type': 'line',
            'source': {
                'type': 'geojson',
                'lineMetrics': true,
                'data': realRouteGeoJson
            },
            'paint': {
                'line-width': 3,
                'line-opacity': 1,
                'line-color': '#FF0000',
            }
        });
    }

    // 添加箭头图层
    function addArrowlayer() {
        console.log("-------addArrowlayer")
        map.addLayer({
            'id': 'arrowLayer',
            'type': 'symbol',
            'source': {
                'type': 'geojson',
                'data': routeGeoJson //轨迹geojson格式数据
            },
            'layout': {
                'symbol-placement': 'line',
                'symbol-spacing': 50, // 图标间隔,默认为250
                'icon-image': 'arrowIcon2', //箭头图标
                'icon-size': 0.5,
                'icon-rotate': ['get', 'bearing'],
                'icon-rotation-alignment': 'map',
                'icon-allow-overlap': true,
                'icon-ignore-placement': true
            }
        });
        console.log("-------addArrowlayer end...")
    }

    // 添加动态点图层
    function addAnimatePointSource() {
        map.addLayer({
            'id': 'animatePointLayer',
            'type': 'symbol',
            'source': {
                'type': 'geojson',
                'data': animatePointGeoJson
            },
            'layout': {
                'icon-image': 'carIcon',
                'icon-size': 0.5,
                'icon-rotate': ['get', 'bearing'],
                'icon-rotation-alignment': 'map',
                'icon-allow-overlap': true,
                'icon-ignore-placement': true
            }
        });

        animate()
    }

    function animate() {
        if (counter >= steps) {
            return
        }
        var startPnt, endPnt
        if (counter == 0) {
            realRouteGeoJson.features[0].geometry.coordinates = []
            startPnt = newRouteGeoJson.geometry.coordinates[counter]
            endPnt = newRouteGeoJson.geometry.coordinates[counter + 1]
        } else if (counter !== 0) {
            startPnt = newRouteGeoJson.geometry.coordinates[counter - 1]
            endPnt = newRouteGeoJson.geometry.coordinates[counter]
        }

        animatePointGeoJson.features[0].properties.bearing = turf.bearing(
            turf.point(startPnt),
            turf.point(endPnt)
        ) - 90;
        animatePointGeoJson.features[0].geometry.coordinates = newRouteGeoJson.geometry.coordinates[counter];
        realRouteGeoJson.features[0].geometry.coordinates.push(animatePointGeoJson.features[0].geometry.coordinates)

        map.getSource('animatePointLayer').setData(animatePointGeoJson);
        map.getSource('realRouteLayer').setData(realRouteGeoJson);
        if (isPlay) {
            requestAnimationFrame(animate);
        }
        counter = counter + 1;
    }

    function resetRoute(route, nstep, units) {
        var newroute = {
            'type': 'Feature',
            'geometry': {
                'type': 'LineString',
                'coordinates': []
            }
        }
        var lineDistance = turf.lineDistance(route);
        var nDistance = lineDistance / nstep;
        for (let i = 0; i < aLength - 1; i++) {
            var from = turf.point(route.geometry.coordinates[i]);
            var to = turf.point(route.geometry.coordinates[i + 1]);
            let lDistance = turf.distance(from, to, {
                units: units
            });
            if (i == 0) {
                newroute.geometry.coordinates.push(route.geometry.coordinates[0])
            }
            if (lDistance > nDistance) {
                let rings = lineMore(from, to, lDistance, nDistance, units)
                newroute.geometry.coordinates = newroute.geometry.coordinates.concat(rings)
            } else {
                newroute.geometry.coordinates.push(route.geometry.coordinates[i + 1])
            }
        }
        return newroute
    }

    function lineMore(from, to, distance, splitLength, units) {
        var step = parseInt(distance / splitLength)
        var leftLength = distance - step * splitLength
        var rings = []
        var route = turf.lineString([from.geometry.coordinates, to.geometry.coordinates])
        for (let i = 1; i <= step; i++) {
            let nlength = i * splitLength
            let pnt = turf.along(route, nlength, {
                units: units
            });
            rings.push(pnt.geometry.coordinates)
        }
        if (leftLength > 0) {
            rings.push(to.geometry.coordinates)
        }
        return rings
    }

    function startClick() {
        if (!isPlay) {
            isPlay = true
            animate()
        }
    }

    function pauseClick() {
        isPlay = false
        animate()
    }

    function stopClick() {
        isPlay = false
        counter = 0
        animate()
    }
</script>

</body>

</html>

参考

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Mapbox GL JS 中添加球面上的标记与在平面地图上添加标记的方法类似,但需要使用 `turf.js` 库来实现。具体步骤如下: 1. 安装 `turf.js` 库。 ```bash npm install turf ``` 2. 在你的代码中引入 `turf.js` 和 Mapbox GL JS 库。 ```javascript import mapboxgl from 'mapbox-gl'; import turf from '@turf/turf'; ``` 3. 创建一个 `FeatureCollection` 对象,并将标记添加到这个对象中。 ```javascript const markers = [ [-122.414, 37.776], [-122.408, 37.77], [-122.404, 37.774] ]; const featureCollection = turf.featureCollection(markers.map(marker => { return turf.point(turf.toWgs84(marker)); })); ``` 在球面上添加标记需要将坐标转换为 WGS84 坐标系,可以使用 `turf.toWgs84()` 方法来实现。 4. 将 `FeatureCollection` 添加到 Mapbox GL JS 的地图上。 ```javascript map.on('load', function() { map.addSource('markers', { type: 'geojson', data: featureCollection }); map.addLayer({ id: 'markers-layer', type: 'symbol', source: 'markers', layout: { 'icon-image': 'marker-15', // 标记图标 'icon-size': 1.5 } }); }); ``` 这里我们使用了 `symbol` 图层来显示标记,你也可以使用其他类型的图层来显示标记。注意,这种方法只适用于在球面上添加标记,如果你需要在平面地图上添加标记,则可以直接使用 Mapbox GL JS 的 API。 另外,你还可以通过 Mapbox GL JS 提供的 `Marker` 类来添加标记,这种方法不需要使用 `turf.js` 库,示例代码如下: ```javascript const marker = new mapboxgl.Marker() .setLngLat([-122.414, 37.776]) .addTo(map); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序媛一枚~

您的鼓励是我创作的最大动力。

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

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

打赏作者

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

抵扣说明:

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

余额充值