當前位置:首頁 » 網頁前端 » web室內地圖開源
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

web室內地圖開源

發布時間: 2022-12-09 16:49:16

❶ supermap iclient3d for webgl是開源的嗎

是基於Cesium進行的擴展開發,目前超圖沒有開源,Cesium是開源的

❷ 什麼是開源的webgis平台

簡單的說就是基於網路的WebGIS分布式系統
使用者可以在單一的環境和單一的工作系統中使用分布於網路上的任何地理數據和地理信息,其目的是建立一個無邊界、分布式、基於構件的地理數據互操作環境。
希望有用!

❸ 如何自己搭建openlayers地圖伺服器

OpenLayers只是WebGIS前端。搭建地圖伺服器需要使用
MapServer,
GeoServer
(開源WebGIS),
或者商業的
ArcGIS
Server,然後用
OpenLayers
在前端調用。

❹ 如何構建REST風格的WEB地圖服務

讓我們構建一個簡單的EmployeeManager Web服務,我們將使用它來演示與MongoDB連接的HATEOAS。為了引導我們的應用程序,我們將使用Spring Initializr。我們將使用Spring HATEOAS和Spring Data MongoDB作為依賴項。你應該看到類似下圖2所示的內容。圖2 :引導應用程序配置完成後,下載zip並將其作為Maven項目導入你喜歡的IDE中。首先,讓我們配置application.properties。

spring.data.mongodb.host=//Mongoserverhost

spring.data.mongodb.port=//Mongoserverport
spring.data.mongodb.username=//Loginuser
spring.data.mongodb.password=//Password
spring.data.mongodb.database=//Databasename

一般來說,如果所有內容都是全新安裝的,並且你沒有更改或修改任何Mongo屬性,則只需提供一個資料庫名稱(已經通過GUI創建了一個資料庫名稱)。

spring.data.mongodb.database=EmployeeManager


另外,為了啟動Mongo實例,作者創建了一個.bat,它指向安裝文件夾和數據文件夾。它是這樣的:"C:ProgramFilesMongoDBServer3.6inmongod"--dbpathD:-datadb
現在,我們來快速創建模型。這里有兩個模型,員工模型和部門模型。檢查它們,確保有沒有參數、getter、setter、equals方法和hashCode生成的構造函數。(不用擔心,所有代碼都在GitHub上,你可以稍後查看它:https://github.com/theFaustus/EmployeeManager。)

publicclassEmployee{
privateStringemployeeId;
privateStringfirstName;
privateStringlastName;
privateintage;
}
publicclassDepartment{
privateStringdepartment;
privateStringname;
privateStringdescription;
privateList<Employee>employees;
}

現在我們已經完成了模型的製作,讓我們來創建存儲庫,以便來測試持久性。存儲庫如下所示:


extendsMongoRepository<Employee,String>{
}

extendsMongoRepository<Department,String>{
}

如上所示,這里沒有方法,因為大家都知道Spring Data中的中心介面被命名為Repository,在其之上是CrudRepository,它提供了處理模型的基本操作。在CrudRepository之上,我們有PagingAndSortingRepository,它為我們提供了一些擴展功能,來簡化分頁和排序訪問。在我們的案例中,最重要的是MongoRepository,它用於嚴格處理我們的Mongo實例。因此,對於我們的案例來說,除了那些現成的方法外,我們不需要任何其他方法,但是僅出於學習目的,作者在這里要提到的是你可以添加其他查詢方法的兩種方法:

  • 「惰性」(查詢創建):此策略將嘗試通過分析查詢方法的名稱並推斷關鍵字(例如findByLastnameAndFirstname)來構建查詢。
  • 編寫查詢:這里沒有什麼特別的。例如,只用@Query注釋你的方法,然後自己編寫查詢。你也可以在MongoDB中編寫查詢。下面是基於JSON的查詢方法的示例:
  • @Query("{'firstname':?0}")
    List<Employee>findByTheEmployeesFirstname(Stringfirstname);

  • 至此,我們已經可以測試我們持久性如何工作。我們只需要對模型進行一些調整即可。通過調整,作者的意思是我們需要注釋一些東西。Spring Data MongoDB使用MappingMongoConverter將對象映射到文檔,下面是我們將要使用的一些注釋:
  • @Id :欄位級別注釋,指出你的哪個欄位是身份標識。
  • @Document :類級別的注釋,用於表示該類將被持久化到資料庫中。
  • @DBRef :描述參考性的欄位級別注釋。
  • 注釋完成後,我們可以使用CommandLineRunner獲取資料庫中的一些數據,CommandLineRunner是一個介面,用於在應用程序完全啟動時(即在run()方法之前)運行代碼段。
  • 我們已經創建了一些模型,並對它們進行了持久化。現在,我們需要一種與他們交互的方式。如上所說,所有代碼都可以在GitHub上找到,因此作者在這里將僅向我們展示一個域服務(介面和實現)。
  • 介面的實現如下:
  • @{
    @Autowired
    ;
    @Override
    publicEmployeesaveEmployee(Employeee){
    returnemployeeRepository.save(e);
    }
    @Override
    (StringemployeeId){
    returnemployeeRepository.findOne(employeeId);
    }
    @Override
    publicvoiddeleteByEmployeeId(StringemployeeId){
    employeeRepository.delete(employeeId);
    }
    @Override
    publicvoipdateEmployee(Employeee){
    employeeRepository.save(e);
    }
    @Override
    publicbooleanemployeeExists(Employeee){
    returnemployeeRepository.exists(Example.of(e));
    }
    @Override
    publicList<Employee>findAll(){
    returnemployeeRepository.findAll();
    }
    @Override
    publicvoiddeleteAll(){
    employeeRepository.deleteAll();
    }
    }

  • 這里沒有什麼特別的要注意的,下面我們將繼續討論最後一個難題——控制器!
  • 因此,對於上面實現的所有方法,我們將自己定位在Richardson成熟度模型的第二級,因為我們使用了HTTP動詞並實現了CRUD操作。現在,我們有了與數據進行交互的方法,並且可以使用Postman,我們可以如下圖3所示檢索資源,或者可以如下圖4所示添加新資源。
  • 圖3 :檢索JSON中的部門列表
  • 圖4:JSON中添加新員工

❺ 蜂鳥視圖的室內三維地圖引擎是如何實現跨平台的展現的

【蜂鳥視圖】FENGMAP室內三維地圖引擎底層使用C++技術,保證引擎的高效、穩定性。基於OpenGL及相應的WebGL、OpenGL ES 技術進行定製裁剪。應用層使用C#、Java、JavaScript語言對於不同系統平台進行封裝,最大程度上保證外部介面的統一性,並使其可運行在電腦端、網頁端、手機端、以及HTML5的公眾號內。所採用的GLTF三維數據格式是國際最新標准格式。已滿足VR及室內定位技術的對接展現。

❻ 有哪些開源的地圖引擎

圖形處理器開發環境 CUDA,C++視覺庫 VXL,Google三維API O3D,三維圖形渲染引擎 OGRE,SoftArt,beostudy-imagelib,計算機圖形渲染庫 Voreen,C語言的JPEG操作庫 OpenJPEG,2D,Magick++,Equalizer,Python圖像處理 Mahotas,GLFW
人臉識別 faceservice.cgi,libpng,繪圖引擎 RRDtool,計算機視覺庫 OpenCV,圖像處理類庫 CImg,2D圖形庫 AGG,Google 圖形處理引擎 skia,JPEG 圖像壓縮庫 LibJPEG,圖像處理庫 GD,C++圖像處理庫 ExactImage,太多了,開源圖形庫 FreeImage,C++向量圖生成庫 CreEPS,醫學影像轉換工具 XMedCon,3移動設備上的OpenGL OpenGL ES,Apache圖像處理模塊 mod_gfx,LibRaw,OpenGL圖形介面 glew,OpenGL的C++封裝 D;Enfent Engine
NVIDIA Scene Graph,C語言的EXIF庫 libexif,Exiv2,Symbian繪圖庫 Cairo for Symbian OS,數據可視化庫 Tulip,高質量圖形圖表庫 MathGL,圖像識別類庫 Tesseract OCR,開源圖形API OpenGL,開源圖形庫 CxImage,C++ PNG類庫 PNGwriter,圖形布局引擎 GLE,OpenCSG,圖像處理和分析 Leptonica,QTeXEngine……;3D 圖形開發庫 Visualization Library,BMP圖像處理庫 bmplib,向量圖形庫 Picasso,攝像頭圖像捕捉 QuickCapture,2D 圖形引擎 Quad-Ren,Symbian圖像處理擴展庫 NokiaCV,
libQGLViewer,OpenGL工具包 Freeglut,大圖像處理工具 VIPS,OCR識別 OCRopus,C 圖像操作庫 Jhead,圖形處理包 DevIL,OpenGL應用工具包 GLUT多了去了

❼ Egret Wing

Egret Wing是一款開源免費的HTML5游戲開發工具,Egret Wing支持目前市面主流的開發語言和技術,作為一款可視化編輯器,它可以幫你提高開發效率。這款工具還支持 Node.js 開發擴展插件,可以讓你更好的定製化自有內容。

渲染模式:dom,cavase,webGL

不同的地圖、不同的元素,好玩的道具(充值付費獲得道具、融合形成新的道具)

創建項目->資源(json/png)resDepot->模塊game

地圖、步數、道具、消除

1.地圖:元素按照地圖排列

最大寬高格子數為8

形狀可配置

包含自己的背景圖

不同關卡背景圖不同

無論地圖形狀如何改變,尺寸不變

2.步數:

不同關卡步數不同

步數為0時,游戲結束

3.道具

一共五種道具,道具功能不同,使用道具時候不消耗步數,來源於游戲獎勵

4.消除:

三個及以上相同元素可消除

元素隨機出現

初局開始時,不可有消除元素

沒有可消除元素時,自動亂序

數據:地圖數據、基礎數據、關卡數據、道具數據

視圖:元素、背景、關卡、道具

邏輯:主邏輯控制器、數據解析器、地圖數據控制器、演算法控制器、視圖控制器

mapData:

一維數組:數據整理方便,下標

二維數組:空間表示方便,獲取位置方便

index = row * 8 + column

json數據描述

地圖配置信息如何描述

{"map": [0,1,8,9,6,7,14,15]} 一維數組記錄不展示以及不可放置元素的方格

游戲元素數據設計

元素:type、ID(唯一)、location

eg:

mapData[3][6] = element.ID  

elements[mapData[3][6]] 元素對象池 訪問想要的數據

ID:45

location:30

public static unmapnum: number = 0;//空白地圖塊數量

public static mapData: number[][]; //游戲地圖,-1表示塊地圖不能使用,-2表示,此地圖沒有元素

public static stepNum: number = 0;//玩家剩餘步數

public static levelStepNum: number = 0;//當前關卡步數

public static elementTypes: number[];//當前關卡出現的元素類型

public static unusedElements: number[];//游戲中未使用得元素,僅記錄元素ID

public static levelBackgroundImageName = ""; //當前關卡背景圖資源名

public static MaxRow: number = 8;//最大的行

public static MaxColumn: number = 8;//最大的列

public static currentElementNum: number = 0;//當前關卡游戲中地圖可用元素數量

public static levelReq: LevelRequire;//當前關卡過關條件

public static elements: GameElement[];//游戲中出現得元素數據池,最多為64個,因為8*8

//舞台寬高,此封裝為了方便調用

public static stageW: number = 0;

public static stageH: number = 0;

DisplayObjectContainer

public constructor() {

        super();

        this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);

    }

Sprite 類是基本顯示列表構造塊:一個可包含所有子項的顯示列表節點

Sprite() 實例化一個容器

1.背景

var gbg:GameBackGround = new GameBackGround();

this._gameStage.addChild(gbg);

gbg.changeBackground();

2.地圖

this.mapc = new MapControl();

this.mapc.createElementAllMap();

3.過關條件

let lec:egret.Sprite = new egret.Sprite();

this._gameStage.addChild(lec);

this.levm = new LevelReqViewManage(lec);

this.levm.createCurrentLevelReq();

4.元素

let cc:egret.Sprite = new egret.Sprite();

this._gameStage.addChild(cc);

this.evm = new ElementViewManage(cc);

this.evm.showAllElements();

1.尋找可消除元素

2.預檢索可消除元素演算法設計與實現

3.是否可以互相交換

交換後是否可以消除

❽ 如何在網頁中嵌入自己製作的小區域矢量地圖

如果想實現一個完整的web地圖,具備基礎的地圖功能,那麼需要一個前端地圖js框架與後端地圖引擎,我不建議使用ArcGIS等商業組件,商業組件一般都包裝得比較嚴實,不利於學習。推薦使用各種開源組件自己搭建獨立地圖服務,容易學習到本質的技術。
1、前端框架有openlayers,google map js離線版本等,近兩年流行leaflet,支持HTML 5前端矢量渲染,支持TileJson。
2、後端地圖引擎主要實現地圖渲染、空間檢索、投影演算法,也就是許多商業軟體的GeoServer類產品。但是,如果想實現自有地圖,可使用開源的Postgresql+postgis構建空間資料庫,它可導入shapefile文件,支持常見的空間幾何演算法,也可使用mysql+空間擴展;在地圖渲染方面,建議嘗試自己編寫瓦片渲染演算法,可以體會一下幾何圖形與標注的壓蓋演算法;投影方面,可參考proj4;另外,GeoTools也有很多用處。

❾ 做室內地圖導航有什麼開源的平台可以使用

網路地圖、騰訊地圖可以導航。 網路地圖是網路提供的一項網路地圖搜索服務,覆蓋了國內近400個城市、數千個區縣。在網路地圖里,用戶可以查詢街道、商嘗樓盤的地理位置,也可以找到離您最近的所有餐館、學校、銀行、公園等等。

❿ 從零打造一個Web地圖引擎

說到地圖,大家一定很熟悉,平時應該都使用過網路地圖、高德地圖、騰訊地圖等,如果涉及到地圖相關的開發需求,也有很多選擇,比如前面的幾個地圖都會提供一套 js API ,此外也有一些開源地圖框架可以使用,比如 OpenLayers 、 Leaflet 等。

那麼大家有沒有想過這些地圖是怎麼渲染出來的呢,為什麼根據一個經緯度就能顯示對應的地圖呢,不知道沒關系,本文會帶各位從零實現一個簡單的地圖引擎,來幫助大家了解 GIS 基礎知識及 Web 地圖的實現原理。

首先我們去高德地圖上選個經緯度,作為我們後期的地圖中心點,打開 高德坐標拾取 工具,隨便選擇一個點:

筆者選擇了杭州的雷峰塔,經緯度為: [120.148732,30.231006] 。

地圖瓦片我們使用高德的在線瓦片,地址如下:

目前各大地圖廠商的瓦片服務遵循的規則是有不同的:

谷歌和 TMS 的瓦片區別可以通過該地址可視化的查看: 地圖瓦片 。

雖然規范不同,但原理基本是一致的,都是把地球投影成一個巨大的正方形世界平面圖,然後按照四叉樹進行分層切割,比如第一層,只有一張瓦片,顯示整個世界的信息,所以基本只能看到洲和海的名稱和邊界線,第二層,切割成四張瓦片,顯示信息稍微多了一點,以此類推,就像一個金字塔一樣,底層解析度最高,顯示的細節最多,瓦片數也最多,頂層解析度最低,顯示的信息很少,瓦片數量相對也最少:

每一層的瓦片數量計算公式:

十八層就需要 68719476736 張瓦片,所以一套地圖瓦片整體數量是非常龐大的。

瓦片切好以後,通過行列號和縮放層級來保存,所以可以看到瓦片地址中有三個變數: x 、 y 、 z

通過這三個變數就可以定位到一張瓦片,比如下面這個地址,行號為 109280 ,列號為 53979 ,縮放層級為 17 :

對應的瓦片為:

關於瓦片的更多信息可以閱讀 瓦片地圖原理 。

高德地圖使用的是 GCJ-02坐標系 ,也稱火星坐標系,由中國國家測繪局在02年發布,是在GPS坐標( WGS-84 坐標系)基礎上經加密後而來,也就是增加了非線性的偏移,讓你摸不準真實位置,為了國家安全,國內地圖服務商都需要使用 GCJ-02坐標系 。

WGS-84 坐標系是國際通用的標准, EPSG 編號為 EPSG:4326 ,通常GPS設備獲取到的原始經緯度和國外的地圖廠商使用的都是 WGS-84 坐標系。

這兩種坐標系都是地理坐標系,球面坐標,單位為 度 ,這種坐標方便在地球上定位,但是不方便展示和進行面積距離計算,我們印象中的地圖都是平面的,所以就有了另外一種平面坐標系,平面坐標系是通過投影的方式從地理坐標系中轉換過來,所以也稱為投影坐標系,通常單位為 米 ,投影坐標系根據投影方式的不同存在多種,在 Web 開發的場景里通常使用的是 Web墨卡托投影 ,編號為 EPSG:3857 ,它基於 墨卡托投影 ,把 WGS-84 坐標系投影成正方形:

這是通過舍棄了南北 85.051129緯度 以上的地區實現的,因為它是正方形,所以一個大的正方形可以很方便的被分割為更小的正方形。

坐標系更詳細的信息可參考 GIS之坐標系統 , EPSG:3857 的詳細信息可參考 EPSG:3857 。

上一節里我們簡單介紹了一下坐標系,按照 Web 地圖的標准,我們的地圖引擎也選擇支持 EPSG:3857 投影,但是我們通過高德工具獲取到的是火星坐標系的經緯度坐標,所以第一步要把經緯度坐標轉換為 Web墨卡托 投影坐標,這里為了簡單,先直接把火星坐標當做 WGS-84 坐標,後面再來看這個問題。

轉換方法網上一搜就有:

3857 坐標有了,它的單位是 米 ,那麼怎麼轉換成瓦片的行列號呢,這就涉及到 解析度 的概念了,即地圖上一像素代表實際多少米,解析度如果能從地圖廠商的文檔里獲取是最好的,如果找不到,也可以簡單計算一下(如果使用計算出來的也不行,那就只能求助搜索引擎了),我們知道地球半徑是 6378137 米, 3857 坐標系把地球當做正圓球體來處理,所以可以算出地球周長,投影是貼著地球赤道的:

所以投影成正方形的世界平面圖後的邊長代表的就是地球的周長,前面我們也知道了每一層級的瓦片數量的計算方式,而一張瓦片的大小一般是 256*256 像素,所以用地球周長除以展開後的世界平面圖的邊長就知道了地圖上每像素代表實際多少米:

地球周長算出來是 40075016.68557849 ,可以看到 OpenLayers 就是這么計算的:

3857 坐標的單位是 米 ,那麼把坐標除以解析度就可以得到對應的像素坐標,再除以 256 ,就可以得到瓦片的行列號:

函數如下:

接下來我們把層級固定為 17 ,那麼解析度 resolution 就是 1.194328566955879 ,雷峰塔的經緯度轉成 3857 的坐標為: [13374895.665697495, 3533278.205310311] ,使用上面的函數計算出來行列號為: [43744, 11556] ,我們把這幾個數據代入瓦片的地址里進行訪問:

一片空白,這是為啥呢,其實是因為原點不一樣, 4326 和 3857 坐標系的原點在赤道和本初子午線相交點,非洲邊上的海里,而瓦片的原點在左上角:

再來看下圖會更容易理解:

3857 坐標系的原點相當於在世界平面圖的中間,向右為 x 軸正方向,向上為 y 軸正方向,而瓦片地圖的原點在左上角,所以我們需要根據圖上【綠色虛線】的距離計算出【橙色實線】的距離,這也很簡單,水平坐標就是水平綠色虛線的長度加上世界平面圖的一半,垂直坐標就是世界平面圖的一半減去垂直綠色虛線的長度,世界平面圖的一半也就是地球周長的一半,修改 getTileRowAndCol 函數:

這次計算出來的瓦片行列號為 [109280, 53979] ,代入瓦片地址:

結果如下:

可以看到雷峰塔出來了。

我們現在能根據一個經緯度找到對應的瓦片,但是這還不夠,我們的目標是要能在瀏覽器上顯示出來,這就需要解決兩個問題,一個是載入多少塊瓦片,二是計算每一塊瓦片的顯示位置。

渲染瓦片我們使用 canvas 畫布,模板如下:

地圖畫布容器 map 的大小我們很容易獲取:

地圖中心點我們設在畫布中間,另外中心點的經緯度 center 和縮放層級 zoom 因為都是我們自己設定的,所以也是已知的,那麼我們可以計算出中心坐標對應的瓦片:

縮放層級還是設為 17 ,中心點還是使用雷峰塔的經緯度,那麼對應的瓦片行列號前面我們已經計算過了,為 [109280, 53979] 。

中心坐標對應的瓦片行列號知道了,那麼該瓦片左上角在世界平面圖中的像素位置我們也就知道了:

計算出來為 [27975680, 13818624] 。這個坐標怎麼轉換到屏幕上呢,請看下圖:

中心經緯度的瓦片我們計算出來了,瓦片左上角的像素坐標也知道了,然後我們再計算出中心經緯度本身對應的像素坐標,那麼和瓦片左上角的差值就可以計算出來,最後我們把畫布的原點移動到畫布中間(畫布默認原點為左上角,x軸正方向向右,y軸正方向向下),也就是把中心經緯度作為坐標原點,那麼中心瓦片的顯示位置就是這個差值。

補充一下將經緯度轉換成像素的方法:

計算中心經緯度對應的像素坐標:

計算差值:

最後通過 canvas 來把中心瓦片渲染出來:

這里先來看看 getTileUrl 方法的實現:

這里隨機了四個子域: webrd01 、 webrd02 、 webrd03 、 webrd04 ,這是因為瀏覽器對於同一域名同時請求的資源是有數量限制的,而當地圖層級變大後需要載入的瓦片數量會比較多,那麼均勻分散到各個子域下去請求可以更快的渲染出所有瓦片,減少排隊等待時間,基本所有地圖廠商的瓦片服務地址都支持多個子域。

為了方便看到中心點的位置,我們再額外渲染兩條中心輔助線,效果如下:

可以看到中心點確實是雷峰塔,當然這只是渲染了中心瓦片,我們要的是瓦片鋪滿整個畫布,對於其他瓦片我們都可以根據中心瓦片計算出來,比如中心瓦片左邊的一塊,它的計算如下:

所以我們只要計算出中心瓦片四個方向各需要幾塊瓦片,然後用一個雙重循環即可計算出畫布需要的所有瓦片,計算需要的瓦片數量很簡單,請看下圖:

畫布寬高的一半減去中心瓦片占據的空間即可得到該方向剩餘的空間,然後除以瓦片的尺寸就知道需要幾塊瓦片了:

我們把中心瓦片作為原點,坐標為 [0, 0] ,來個雙重循環掃描一遍即可渲染出所有瓦片:

效果如下:

很完美。

拖動可以這么考慮,前面已經實現了渲染指定經緯度的瓦片,當我們按住進行拖動時,可以知道滑鼠滑動的距離,然後把該距離,也就是像素轉換成經緯度的數值,最後我們再更新當前中心點的經緯度,並清空畫布,調用之前的方法重新渲染,不停重繪造成是在移動的視覺假象。

監聽滑鼠相關事件:

在 onMousemove 方法里計算拖動後的中心經緯度及重新渲染畫布:

movementX 和 movementY 屬性能獲取本次和上一次滑鼠事件中的移動值,兼容性不是很好,不過自己計算該值也很簡單,詳細請移步 MDN 。乘以當前解析度把 像素 換算成 米 ,然後把當前中心點經緯度也轉成 3857 的 米 坐標,偏移本次移動的距離,最後再轉回 4326 的經緯度坐標作為更新後的中心點即可。

為什麼 x 是減, y 是加呢,很簡單,我們滑鼠向右和向下移動時距離是正的,相應的地圖會向右或向下移動, 4326 坐標系向右和向上為正方向,那麼地圖向右移動時,中心點顯然是相對來說是向左移了,因為向右為正方向,所以中心點經度方向就是減少了,所以是減去移動的距離,而地圖向下移動,中心點相對來說是向上移了,因為向上為正方向,所以中心點緯度方向就是增加了,所以加上移動的距離。

更新完中心經緯度,然後清空畫布重新繪制:

效果如下:

可以看到已經凌亂了,這是為啥呢,其實是因為圖片載入是一個非同步的過程,我們滑鼠移動過程中,會不斷的計算出要載入的瓦片進行載入,但是可能上一批瓦片還沒載入完成,滑鼠已經移動到新的位置了,又計算出一批新的瓦片進行載入,此時上一批瓦片可能載入完成並渲染出來了,但是這些瓦片有些可能已經被移除畫布,不需要顯示,有些可能還在畫布內,但是使用的還是之前的位置,渲染出來也是不對的,同時新的一批瓦片可能也載入完成並渲染出來,自然導致了最終顯示的錯亂。

知道原因就簡單了,首先我們加個緩存對象,因為在拖動過程中,很多瓦片只是位置變了,不需要重新載入,同一個瓦片載入一次,後續只更新它的位置即可;另外再設置一個對象來記錄當前畫布上應該顯示的瓦片,防止不應該出現的瓦片渲染出來:

因為需要記錄瓦片的位置、載入狀態等信息,我們創建一個瓦片類:

然後修改之前的雙重循環渲染瓦片的邏輯:

效果如下:

可以看到,拖動已經正常了,當然,上述實現還是很粗糙的,需要優化的地方很多,比如:

1.一般會先排個序,優先載入中心瓦片

2.緩存的瓦片越來越多肯定也會影響性能,所以還需要一些清除策略

這些問題有興趣的可以自行思考。

拖動是實時更新中心點經緯度,那麼縮放自然更新縮放層級就行了:

效果如下:

功能是有了,不過效果很一般,因為我們平常使用的地圖縮放都是有一個放大或縮小的過渡動畫,而這個是直接空白然後重新渲染,不仔細看都不知道是放大還是縮小。

所以我們不妨加個過渡效果,當我們滑鼠滾動後,先將畫布放大或縮小,動畫結束後再根據最終的縮放值來渲染需要的瓦片。

畫布默認縮放值為 1 ,放大則在此基礎上乘以 2 倍,縮小則除以 2 ,然後動畫到目標值,動畫期間設置畫布的縮放值及清空畫布,重新繪制畫布上的已有瓦片,達到放大或縮小的視覺效果,動畫結束後再調用 renderTiles 重新渲染最終縮放值需要的瓦片。

效果如下:

雖然效果還是一般,不過至少能看出來是在放大還是縮小。

前面還遺留了一個小問題,即我們把高德工具上選出的經緯度直接當做 4326 經緯度,前面也講過,它們之間是存在偏移的,比如手機 GPS 獲取到的經緯度一般都是 84 坐標,直接在高德地圖顯示,會發現和你實際位置不一樣,所以就需要進行一個轉換,有一些工具可以幫你做些事情,比如 Gcoord 、 coordtransform 等。

上述效果看著比較一般,其實只要在上面的基礎上稍微加一點瓦片的淡出動畫,效果就會好很多,目前一般都是使用 canvas 來渲染 2D 地圖,如果自己實現動畫不太方便,也有一些強大的 canvas 庫可以選擇,筆者最後使用 Konva.js 庫重做了一版,加入了瓦片淡出動畫,最終效果如下:

另外只要搞清楚各個地圖的瓦片規則,就能稍加修改支持更多的地圖瓦片:

具體實現限於篇幅不再展開,有興趣的可以閱讀本文源碼。

本文詳細的介紹了一個簡單的 web 地圖開發過程,上述實現原理僅是筆者的個人思路,不代表 openlayers 等框架的原理,因為筆者也是 GIS 的初學者,所以難免會有問題,或更好的實現,歡迎指出。

在線 demo : https://wanglin2.github.io/web_map_demo/

完整源碼: https://github.com/wanglin2/web_map_demo