百度路書實現軌跡回放(標準)

K.P發表於2020-10-20

心酸製作歷程

當剛接下這專案時,便開始研究如何實現軌跡回放的功能;而剛開始當然是直接查詢百度的例項百度路書例項,如下圖

在這裡插入圖片描述
但是我們的需求是需要通過進度,速度來進行調整(如下圖),顯然難以達到這個目標。
在這裡插入圖片描述
因此,在檢視了多個文件後,選擇了一個勉強達到需求的辦法,就跟canvas的方式一樣,每秒清除地圖上的所有覆蓋物,然後車重新定位地圖中心點,畫出執行到的軌跡,雖然可行,但是整個車執行的過程中,就宛如地圖在移動,車一直釘在地圖中心。

直到一位大佬把這問題迎刃而解(我打輔助,多多學習)

查詢路書的原始碼

在找到一篇大佬的文件後,發現,需要從路書的原始碼下手,路書原始碼,推薦直接已CDN形式放在index.html中。

    <script type="text/javascript" src="http://api.map.baidu.com/library/LuShu/1.2/src/LuShu_min.js"></script>

推薦看下路書原始碼, 你會了解很多東西,這樣上手容易些。

下面直接進入我們的程式碼,廢話不多說。

<!-- 地圖容器開始 -->
        <div id="mymap" style="width:100%;height:100%"></div>
// 在mounted處 例項化地圖
mounted() {
	var map = new BMap.Map("mymap"); //例項化地圖
        var point = new BMap.Point(116.404, 39.915); // 建立點座標 
        map.centerAndZoom(point, 15); // 初始化地圖,設定中心點座標和地圖級別
        map.enableScrollWheelZoom(true); // 允許縮放
        map.centerAndZoom()
        this.istranslate = true
        this.infoWindow.contents = `<div style="text-align: center;line-height: 30px;font-size: 12px;font-weight:600;">
                                            GSM訊號:<i class="fa fa-signal" style="color:#42AEED"></i><br>
                                            速度:${Number(this.speednum)} KM/H<br>
                                            定位方式:衛星定位
                                        </div>`
},
methods: {
	// 獲取軌跡點
	allTrackData(val, index) {
            const params = {
                mcph: this.mcph,
                datetime: val.time,
                datetime1: val.startime,
            }
            this.path = []  // 軌跡點
            this.temp = 0  // 進度條
            getSlotDetail(params).then(res => {  // 請求車輛軌跡點
                res.data.forEach(item => {
                    this.path.push({
                        lng: item.longitude,
                        lat: item.latitude,
                        heading: item.heading,
                        speed: Number(item.speed)
                    })
                })
                this.initMap()    // 初始化地圖
                this.isPlay = true  // 播放鍵開始
                this.lushu.start()		// 路書開始
                this.maxNum = this.path.length - 2
                // 開啟天窗
                this.infoWindow.show = true
            })
        },
        // 下面的兩個方法 從路書原始碼中摘取 修改
        // 初始化地圖
        initMap() {
            var _this = this
            var map = new BMap.Map("mymap");
            var point = new BMap.Point(116.404, 39.915); // 建立點座標 
            map.centerAndZoom(point, 15); // 初始化地圖,設定中心點座標和地圖級別
            map.enableScrollWheelZoom(true);
            map.centerAndZoom()
            var arrPois = [];
            for (let i = 0; i < this.path.length; i++) {
                var p0 = this.path[i].lng;
                var p1 = this.path[i].lat;
                // var checksum = makerArry[i].checksum;
                var point = new BMap.Point(p0, p1); //118.230272,33.482474
                arrPois.push(point);
            }
            //畫軌跡
            var polyLine = new BMap.Polyline(arrPois, {
                strokeColor: "red", //設定顏色
                strokeWeight: 5, //寬度
                strokeOpacity: 0.5 //透明度
            });
            map.addOverlay(polyLine);
            //畫軌跡結束
            BMapLib.LuShu.prototype._move = function (initPos, targetPos, effect) {
                var pointsArr = [initPos, targetPos]; //點陣列
                var me = this,
                    //當前的幀數
                    currentCount = 0,
                    //步長,米/秒
                    timer = 10,
                    step = this._opts.speed / (1000 / timer),
                    //初始座標
                    init_pos = this._projection.lngLatToPoint(initPos),
                    //獲取結束點的(x,y)座標
                    target_pos = this._projection.lngLatToPoint(targetPos),
                    //總的步長
                    count = Math.round(me._getDistance(init_pos, target_pos) / step);
                //顯示折線 syj201607191107
                //如果想顯示小車走過的痕跡,放開這段程式碼就行
                // this._map.addOverlay(
                //     new BMap.Polyline(pointsArr, {
                //         strokeColor: "#111",
                //         strokeWeight: 5,
                //         strokeOpacity: 0.5
                //     })
                // ); // 畫線
                //如果小於1直接移動到下一點
                if (count < 1) {
                    me._moveNext(++me.i);
                    return;
                }
                this._opts.defaultContent = `<div style="text-align: center;line-height: 30px;font-size: 12px;font-weight:600;">
                                            GSM訊號:<i class="fa fa-signal" style="color:#42AEED"></i><br>
                                            速度:${_this.path[me.i].speed} KM/H<br>
                                            定位方式:衛星定位
                                        </div>`
                _this.speednum = _this.path[me.i].speed
                me._intervalFlag = setInterval(function () {
                    // _this.maxNum = me._path.length
                    _this.temp = me.i
                    //兩點之間當前幀數大於總幀數的時候,則說明已經完成移動
                    if (currentCount >= count) {
                        clearInterval(me._intervalFlag);
                        //移動的點已經超過總的長度
                        if (me.i > me._path.length) {
                            return;
                        }
                        //執行下一個點
                        me._moveNext(++me.i);
                    } else {
                        currentCount++;
                        var x = effect(init_pos.x, target_pos.x, currentCount, count),
                            y = effect(init_pos.y, target_pos.y, currentCount, count),
                            pos = me._projection.pointToLngLat(new BMap.Pixel(x, y));
                        //設定marker
                        if (currentCount == 1) {
                            var proPos = null;
                            if (me.i - 1 >= 0) {
                                proPos = me._path[me.i - 1];
                            }
                            if (me._opts.enableRotation == true) {
                                me.setRotation(proPos, initPos, targetPos);
                            }
                            if (me._opts.autoView) {
                                if (!me._map.getBounds().containsPoint(pos)) {
                                    me._map.setCenter(pos);
                                }
                            }
                        }
                        //正在移動
                        me._marker.setPosition(pos);
                        //設定自定義overlay的位置
                        me._setInfoWin(pos);
                    }
                }, timer);
            };
            this.initLushu(map, arrPois, this.mycaiId);
        },
        initLushu(map, arrPois, mycaiId) {
            this.lushu = new BMapLib.LuShu(map, arrPois, {
                defaultContent: this.infoWindow.contents, //"從天安門到百度大廈"
                autoView: true, //是否開啟自動視野調整,如果開啟那麼路書在運動過程中會根據視野自動調整
                icon: new BMap.Icon(
                    "http://developer.baidu.com/map/jsdemo/img/car.png",
                    new BMap.Size(52, 26), {
                        anchor: new BMap.Size(27, 13)
                    }
                ),
                speed: this.speed,
                enableRotation: true, //是否設定marker隨著道路的走向進行旋轉
                landmarkPois: []
            });
        },
}

至此,我們的車就能移動了,而且當車超出地圖的範圍,自動回到地圖中心,主要改變的就是路書原型鏈上_move的方法。

下面再添上需求的幾個方法

// 改變播放的速度 快進形式
        speedChange() {
            this.lushu._opts.speed = this.speed
        },
        // 回放進度條 向前向後拉進度條
        tempChange() {
            this.lushu.i = this.temp
            if (this.temp >= this.maxNum - 2) {
                this.isPlay = false
            }
        },
        // 開始&暫停
        playChange() {
            if (this.isPlay) {
                this.lushu.pause();
                this.isPlay = false
            } else {
                this.lushu.start();
                this.isPlay = true
            }
        },
        // 重置軌跡
        reset() {
            this.temp = 0
            this.speed = 1000
            this.isPlay = false
            this.lushu.stop()
        },

以上,便是一個滿足需求的路書軌跡回放方法,此文僅為記錄總結,程式碼為黃大佬提供,僅供參考學習。

相關文章