OpenLayer實現路徑運動

来源:https://www.cnblogs.com/cqhaibin/archive/2019/04/28/10786886.html
-Advertisement-
Play Games

近期由於業務的需求,讓我這從未想過要碰Web Gis的業餘前端開發者,走了Web Gis的開發道路。功能需求很簡單,但卻也是讓自己難為了好幾天。如,應該選擇那個Gis框架,Gis框架的相容性如何,直接Ie哪些版,能不能簡單到只有一張圖片就行解決問題,等等。。。。。。 在如此多的技術盲點,以及不確定的 ...


     近期由於業務的需求,讓我這從未想過要碰Web Gis的業餘前端開發者,走了Web Gis的開發道路。功能需求很簡單,但卻也是讓自己難為了好幾天。如,應該選擇那個Gis框架,Gis框架的相容性如何,直接Ie哪些版,能不能簡單到只有一張圖片就行解決問題,等等。。。。。。

在如此多的技術盲點,以及不確定的因素,我開始了徵程,現將一些心得做些記錄。

一、需求分析

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

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

二、效果展示

三、偽代碼實現

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

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('postcompose', 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('postcompose', 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 + '  ' + dy + '  ' + 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: 'Car',
                    fill: new Fill({
                        color: 'red'
                    }),
                    offsetY: -20
                })
            });  
            vCxt.drawFeature(anchor, style);
            //this.map.getView().setCenter(bCrood);
        }
        this.map.render();
    }

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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Intent:即意圖,一般是用來啟動新的Activity,按照啟動方式分為兩類:顯式Intent 和 隱式Intent 顯示Intent就是直接以“類名稱”來指定要啟動哪一個Activity:Intent intent = new Intent(this , activity.class); 其中a ...
  • 插敘:之前電腦一直遇到VPN登錄不了的問題,試了幾臺電腦都能正常連接,只有我的電腦不可以,VPN大佬建議我直接重裝系統,索性就直接重新裝了系統,結果就能連接了。昨天開始上傳包的時候,發現用Application Loader登錄的時候,填寫了正確的開發者賬號一直登錄不上去,如下圖。 點了圖上的地址 ...
  • 我們的目標:搭建一個本地多用戶的App Inventor 2 伺服器 演示: http://ai2.fsyz.net [舊 win] http://ai2n.fsyz.net [新 Centos] 目的:課堂教學,社團活動,興趣學習 優勢:管理許可權(用戶管理,賬號切換,資源打包),網路鏈接速度快,擁 ...
  • 表單類控制項承載了一個網頁數據的錄入與交互,本章將介紹如何使用指令v-model完成表單的數據雙向綁定。 ...
  • 一、前言 在之前的前端開發中,為了實現我們的需求,通常採用的方案是通過 JS/Jquery 直接操縱頁面的 DOM 元素,得益於 Jquery 對於 DOM 元素優異的操作能力,我們可以很輕易的對獲取到的 DOM 元素進行操作。但是,當我們開始在前端項目中使用 Vue 這類的 MVVM 框架之後,對 ...
  • 學習筆記 1.jQuery動畫的淡入淡出 2.jQuery廣告彈窗 ...
  • Code Splitting是webpack的一個重要特性,他允許你將代碼打包生成多個bundle。對多頁應用來說,它是必須的,因為必須要配置多個入口生成多個bundle;對於單頁應用來說,如果只打包成一個bundle可能體積很大,導致無法利用瀏覽器並行下載的能力,且白屏時間長,也會導致下載很多可能... ...
  • 一、rem佈局基本原理 原理:rem可以理解為一個長度單位,單位rem的值等於網頁font-size的值。如果網頁的字體大小為預設值16px,那麼1rem就等於16px,0.5rem等於8px。 根據這個原理,如果網頁預設的字體大小改變,那麼單位rem的大小也會改變,我們使用rem做單位的HTML元 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...