• 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 linetitle>
        <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116

    2.2 line_arrow.html

    DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Add a GeoJSON line,with Arrowtitle>
        <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 =
            `
                    
                
                `
        //给图片对象写入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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359

    参考

  • 相关阅读:
    在gitlab中指定自定义 CI/CD 配置文件
    判断js中变量的类型的方法
    批量在文件名中的特定文字的左边或右边位置添加文字
    注解和反射
    vue-i18n安装配置使用示例,并介绍在模版文本、组件方法、js,f方法里的使用
    Azure 机器学习 - 如何使用模板创建安全工作区
    XILINX XC7A200T-2FBG676C PLC可编程逻辑控制器
    线程状态
    江科大STM32 终
    用Python和开源NLP工具库开发一个小型聊天机器人原型
  • 原文地址:https://blog.csdn.net/qq_40985985/article/details/132805417