首頁 >web前端 >js教程 >OpenLayer怎麼實現小車按路徑運動

OpenLayer怎麼實現小車按路徑運動

little bottle
little bottle轉載
2019-04-30 11:53:333645瀏覽

 這篇文章主要講述的是在openlayer上實現路徑運動,下面和小編一起去看看具體都是如何實現的吧,有興趣的朋友可以看看。

一、需求分析

     客戶需要的功能就是能在一張Gis圖上實現小車根據路徑進行移動,為什麼一定要Gis呢(這是客戶指定需求,無語一該)。而客戶也說底圖要很容易更換,但他想要用Gis表現的卻是室內的地理訊息,我也沒辦法用baidu, 高德等現成的Gis介面。

針對上述需求,我沒有去了解過多的web gis框架。因為客戶對Gis的概念就是能放大,縮小,可以做路徑規劃等。所以我就選擇ol,利用他的靜態圖片(選擇這個是為滿足客戶靈活更新底圖的需求)做Gis底圖的功能來解決此問題。

相關教學:js影片教學

二、效果展示

三、偽程式碼實作

由於是技術驗證程式碼, 有些雜亂,現只給予關鍵性程式碼。如有業務需要歡迎共同討論。

3.1 實作路徑的繪製

此步驟還是相對簡單的,主要用到Ol的Draw對象,程式碼哪下:


draw(type){
        this.stopdraw();
        this._draw = new Draw({
            source: this.layer.getSource(),
            type: type == 'Icon' ? 'Point' : type
        });
        this._draw.on('drawend', (event)=>{
            if(type == 'LineString'){
                this.traceLine = event.feature;
            }
            if(type != 'Icon') return;
            let f = event.feature;
            f.setStyle(new Style({
                image: new Icon({
                    src: '/content/battery.gif'
                }),
                text: new Text({
                    text: 'new item',
                    fill: new Fill({
                        color: "red"
                    })
                })
            }));
            f.type = 'battery';
        });
        this.map.addInteraction(this._draw);
        this._snap = new Snap({source: this.layer.getSource()});
        this.map.addInteraction(this._snap);
    }

關鍵程式碼在於drawend事件的監聽,如果是LineString情況,就將此feature放在共公變量,方便路徑執行時使用。

3.2 分解路徑資料

     此部分就是取得3.1步驟的路徑路徑,然後解析,因為3.1上的linestring是多個線段的集合,但運動其本質就是改變圖標的座標,使其快速且連續的變化就形成了移動效果。所以這裡有一個方法可以進行路徑細分,程式碼如下:

cutTrace(){
        let traceCroods = this.traceLine.getGeometry().getCoordinates(); 
        let len = traceCroods.length;
        let destCroods = [];
        for(let i = 0; i < len - 1; ++i){
            let bPoint = traceCroods[i];
            let ePoint = traceCroods[i+1];
            let bevelling = Math.sqrt(Math.pow(ePoint[0] - bPoint[0], 2)
            + Math.pow(ePoint[1] - bPoint[1], 2) );
            let cosA = (ePoint[0] - bPoint[0]) / bevelling;
            let sinA = (ePoint[1] - bPoint[1]) / bevelling;
            
            let curStep = 0;
            let step = 5;
            destCroods.push(new Point([bPoint[0], bPoint[1]]));
            do{
                curStep++;
                let nextPoint;
                if(curStep * step >= bevelling){
                    nextPoint = new Point([ePoint[0], ePoint[1]]);
                }else{
                    nextPoint = new Point([
                        cosA * curStep * step + bPoint[0]
                        ,
                        sinA * curStep * step + bPoint[1]
                    ]);
                }
                destCroods.push(nextPoint);
            }while(curStep * step < bevelling);
        }
        return destCroods;
    }

其中用到了一些數學上的三角函數和計算方法。此方法最終選一個根據步長計算後的座標集合。

3.3 利用postcompose實現運動效果

#程式碼如下:


tracerun(){
        if(!this.traceLine) return;
        this.traceCroods = this.cutTrace();
        this.now = new Date().getTime();
        this.map.on(&#39;postcompose&#39;, this.moveFeature.bind(this));
        this.map.render();
    }
    moveFeature(event){
        let vCxt = event.vectorContext;
        let fState = event.frameState;
        let elapsedTime = fState.time - this.now;
        let index = Math.round(300 * elapsedTime / 1000);
        let len = this.traceCroods.length;
        if(index >= len){
            //stop
            this.map.un(&#39;postcompose&#39;, this.moveFeature);
            return;
        }
        let dx, dy, rotation;
        if(this.traceCroods[index] && this.traceCroods[index + 1]){
            let isRigth = false;
            let bCrood = this.traceCroods[index].getCoordinates();
            let eCrood = this.traceCroods[index + 1].getCoordinates();
            if(bCrood[0] < eCrood[0]){
                //左->右
                isRigth = true
            }
            dx = bCrood[0] - eCrood[0];
            dy = bCrood[1] - eCrood[1];

            rotation = Math.atan2(dy,dx);
            if(rotation > (Math.PI / 2)){
                //修正
                rotation =  Math.PI - rotation;
            }else if(rotation < -1 * (Math.PI / 2)){
                rotation = -1 * Math.PI - rotation;
            }else{
                rotation = -rotation;
            }
            console.log(dx + &#39;  &#39; + dy + &#39;  &#39; + rotation);
            let curPoint = this.traceCroods[index];
            var anchor = new Feature(curPoint);
            let style = new Style({
                image: new Icon({
                    img: isRigth ? this.carRight : this.carImg,
                    imgSize: [32,32],
                    rotateWithView: false,
                    rotation: rotation
                }),
                text: new Text({
                    text: &#39;Car&#39;,
                    fill: new Fill({
                        color: &#39;red&#39;
                    }),
                    offsetY: -20
                })
            });  
            vCxt.drawFeature(anchor, style);
            //this.map.getView().setCenter(bCrood);
        }
        this.map.render();
    }

    此移動程式碼的是用ol的postcompose事件進行實現的,因為render方法執行完成後會觸發postcompose事件,所以就取代了計時器的實作方案。其中rotation根據兩點座標計算出移動圖示的斜度、以及移動的方向等,更為影響的展示。

以上是OpenLayer怎麼實現小車按路徑運動的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除