軌跡回放

根據業務場景結合vue+iview在百度lushu的prototype中新增一些回調屬性如:_pauseCallback、_endCallback、_sliderPos進行回放進度、回放速度的控制
涉及到的交互及限制:vue

  1. 回放進度(暫停時拖動,播放中沒法控制)
  2. 回放速度(移動中須要到下一個座標點,若距離太長兩點之間沒法變動速度)

圖片描述
tip:算法

  • 測試數據中相鄰座標點的間隔不勻會致使進度條的快慢不等
  • 進度條位置_sliderPos的算法不太精確須要再作優化可自行修改

代碼

<template>
    <div>
        <div id="allmap"></div>
        <div class="slideBar track">
            <Row type="flex" justify="center" align="middle">
                <Col span='6'>回放進度</Col>
                <Col span='15'>
                    <Slider v-model="progressVal" :disabled='sliderStatus' @on-input='progressChange'></Slider>
                </Col>
            </Row>
            <Row type="flex" justify="center" align="middle">
                <Col span='6'>回放速度</Col>
                <Col span='15'>
                    <Slider v-model="speedVal" :min='1' :max='10' :disabled='sliderStatus' @on-input='speedChange'></Slider>
                </Col>
            </Row>
            <Row type="flex" justify="center">
                <Col span='10'>
                    <Button  class='btn' size="large" @click='pause' :disabled='pauseStatus'>暫停</Button>
                </Col>
                <Col span='8'>
                    <Button type='primary' size="large" @click='run' :disabled='playStatus'>播放</Button>
                </Col>
            </Row>
        </div>
    </div>
</template>
<script>
export default {
    methods:{
        init(){
             this.map = new BMap.Map('allmap',{enableMapClick:false});
             this.map.enableScrollWheelZoom(true)
             this.map.centerAndZoom('杭州', 12);
             this.iconStart = new BMap.Icon(mobike, new BMap.Size(36,39),{anchor : new BMap.Size(18, 39)});
             BMapLib.LuShu.prototype._addMarker=function(callback) {
                if (this._marker) {
                    this.stop();
                    this._map.removeOverlay(this._marker);
                    clearTimeout(this._timeoutFlag);
                }
                //移除以前的overlay
                this._overlay && this._map.removeOverlay(this._overlay);
                var marker = new BMap.Marker(this._path[0].point);
                this._opts.icon && marker.setIcon(this._opts.icon);
                this._map.addOverlay(marker);
                this._marker = marker;
                
            }
            BMapLib.LuShu.prototype._setLabel=(me,pointInfo)=>{
                 me._map.removeOverlay(me._marker.getLabel());
                 me._marker.setLabel(new BMap.Label(this.getContentTemplate(pointInfo,false),{offset:new BMap.Size(40,-10)}))
            }
            BMapLib.LuShu.prototype._move=function(initPos,targetPos,effect,initPosInfo,targetPosInfo) {
                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);
                 
                //若是小於1直接移動到下一點
                if (count < 1) {
                    me._moveNext(++me.i);
                    return;
                }
                me._intervalFlag = setInterval(function() {
                //兩點之間當前幀數大於總幀數的時候,則說明已經完成移動
                    if (currentCount >= count) {
                        me._endCallback(initPosInfo,targetPosInfo)
                        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].point;
                                }
                                if(me._opts.enableRotation == true){
                                     me.setRotation(proPos,initPos,targetPos);
                                }
                                if(me._opts.autoView){
                                    if(!me._map.getBounds().containsPoint(pos)){
                                        me._map.setCenter(pos);
                                    }  
                                }
                            }
                            //設置label
                            me._setLabel(me,initPosInfo)
                            //正在移動
                            me._marker.setPosition(pos,initPos);
                            //設置自定義overlay的位置
                            me._setInfoWin(pos);  
                            me._sliderPos(initPos,targetPos,initPosInfo,targetPosInfo)
                        }
                },timer);
            };
            BMapLib.LuShu.prototype._moveNext= function(index) {
                var me = this;
                if (index < this._path.length - 1) {
                    me._move(me._path[index].point, me._path[index + 1].point, me._tween.linear,me._path[index],me._path[index+1]);
                }
            },
            BMapLib.LuShu.prototype.pause = function() {
                clearInterval(this._intervalFlag);
                //標識是不是按過pause按鈕
                this._fromPause = true;
                this._clearTimeout();
                this._pauseCallback()
            };
            BMapLib.LuShu.prototype._sliderPos=(initPos,targetPos,initPosInfo)=>{
                this.currentPoint = this.pointList.map((item)=>{ return item.locationTime}).indexOf(initPosInfo.locationTime)
                this.progressVal =  Number(((this.currentPoint/this.pointList.length)*100).toFixed(0))
                this.handler = false
            };
            BMapLib.LuShu.prototype._endCallback=(initPosInfo,targetPosInfo)=>{
                if (targetPosInfo.locationTime==this.pointList.slice().pop().locationTime) {
                    this.progressVal=100
                    this.handler = true
                    this.playStatus = false
                    this.pauseStatus =true
                    this.$Message.success('播放完成')
                }
            };
            BMapLib.LuShu.prototype._pauseCallback=()=>{
                this.handler  =true
            };
            BMapLib.LuShu.prototype.removeOverlay=function(){
                this._map.removeOverlay(this._marker)
            }
        
        },
        run(){
            if (this.progressVal==100) {
                this.restart = true
                this.$Message.info({
                    top: 50,
                    duration: 3,
                    render: h => {
                        return h('span', [
                            '播放已完成,是否',
                            h('a', {
                                on:{
                                    'click':()=>{
                                        if (this.restart) {
                                            this.progressVal = 0;
                                            this.restart = false
                                            setTimeout(()=>{
                                                this.pauseStatus = false
                                                this.run()
                                            },400)
                                        }
                                    }
                                }
                            },'從新播放'),'?'
                        ])
                    }
                });
                return
            }else{
                this.pauseStatus = false
                this.playStatus = true
                this.start.hide()
            }
            if (this.type==='pause') {
                this.lushu.start()
                return
            }
            //this.map.clearOverlays(); 
            //this.map.addOverlay(this.polyline);
            this.lushu = new BMapLib.LuShu(this.map,this.pointList.slice(this.cut),{
                //defaultContent:"粵A30780",//"從天安門到百度大廈"
                autoView:false,//是否開啓自動視野調整,若是開啓那麼路書在運動過程當中會根據視野自動調整
                icon  : this.iconStart,
                speed: this.speed,
                enableRotation:false,//是否設置marker隨着道路的走向進行旋轉
                landmarkPois:[]
                    
            }); 
            this.lushu.start()
        },
        pause(){
            this.playStatus = false
            this.type = 'pause'
            this.lushu.pause()
        },
        speedChange(val){
            this.lushu._opts.speed = val*30
            this.speed=val*30
        },
    }
}
</script>
百度lushu源碼參考 http://api.map.baidu.com/libr...
相關文章
相關標籤/搜索