前言
介紹地圖之前我們首先了解它的基本組成。相信大家都了解拼圖游戲的原理霞怀,把一張大圖切割成若干小塊晃跺,然后按照一定的規(guī)則拼接起來(lái)。地圖的原理也是一樣巡验。我搜羅的目前移動(dòng)端比較常見(jiàn)的繪制地圖的方法际插,與大家分享碘耳。
背景
互聯(lián)網(wǎng)地圖服務(wù)商的在線地圖都通過(guò)瓦片的方式提供显设,稱為瓦片地圖服務(wù)。最常見(jiàn)的地圖瓦片是圖片格式的辛辨,現(xiàn)在有的地圖服務(wù)商也提供了矢量的瓦片數(shù)據(jù)捕捂,然后在用戶端使用Canvas渲染成圖片,如node-canvas實(shí)現(xiàn)百度地圖個(gè)性化底圖繪制斗搞。
在進(jìn)行地圖開發(fā)時(shí)指攒,為獲取特定經(jīng)緯度所在區(qū)域的瓦片和獲取瓦片上像素點(diǎn)對(duì)應(yīng)的經(jīng)緯度,經(jīng)常需要進(jìn)行經(jīng)緯度坐標(biāo)與瓦片坐標(biāo)僻焚、像素坐標(biāo)的相互轉(zhuǎn)換允悦。
主要經(jīng)緯度坐標(biāo)系
國(guó)際標(biāo)準(zhǔn)的經(jīng)緯度坐標(biāo)是WGS84,Open Street Map虑啤、外國(guó)版的Google Map都是采用WGS84隙弛;高德地圖使用的坐標(biāo)系是GCJ-02;百度地圖使用的坐標(biāo)系是BD-09狞山。高德地圖和百度地圖都提供了在線的單向坐標(biāo)轉(zhuǎn)換接口全闷,將其他坐標(biāo)系換化到自己的坐標(biāo)系,但這種轉(zhuǎn)換受限于http url請(qǐng)求字段長(zhǎng)度和網(wǎng)絡(luò)請(qǐng)求延遲萍启,批量處理并不實(shí)用总珠。離線相互轉(zhuǎn)換可以通過(guò)開源JavaScript庫(kù)coordtransform實(shí)現(xiàn)屏鳍,誤差在10米左右。
雖然各地圖服務(wù)商經(jīng)緯度坐標(biāo)系不同局服,但某一互聯(lián)網(wǎng)地圖的經(jīng)緯度坐標(biāo)與瓦片坐標(biāo)相互轉(zhuǎn)換只與該地圖商的墨卡托投影和瓦片編號(hào)的定義有關(guān)钓瞭,跟地圖商采用的大地坐標(biāo)系標(biāo)準(zhǔn)無(wú)關(guān)。
瓦片切割和瓦片坐標(biāo)
地圖瓦片具有以下特點(diǎn):
- 具有唯一的瓦片等級(jí)(Level)和瓦片坐標(biāo)編號(hào)(tileX, tileY)淫奔。
- 瓦片分辨率為256
256降淮。
- 瓦片分辨率為256
- 最小的地圖等級(jí)是0,此時(shí)世界地圖只由一張瓦片組成搏讶。
- 瓦片等級(jí)越高佳鳖,組成世界地圖的瓦片數(shù)越多,可以展示的地圖越詳細(xì)媒惕。
- 某一瓦片等級(jí)地圖的瓦片是由低一級(jí)的各瓦片切割成的4個(gè)瓦片組成系吩,形成了瓦片金字塔。
瓦片坐標(biāo)和經(jīng)緯度坐標(biāo)之間存在關(guān)系妒蔚,而這層關(guān)系是通過(guò)后端接口加密處理并且一一映射后的穿挨,有自己的計(jì)算公式
- 坐標(biāo)轉(zhuǎn)換圖解
[圖片上傳失敗...(image-5b8538-1618472263075)]
瓦片地圖等級(jí)范圍
瓦片地圖等級(jí)范圍反映了地圖可縮放的程度。
雖然最小的瓦片等級(jí)是0肴盏,但是部分地圖并不提供0級(jí)或其他較小瓦片等級(jí)的地圖科盛,因?yàn)榇藭r(shí)的世界地圖將會(huì)很小,不能鋪滿用戶設(shè)備窗口菜皂。
經(jīng)過(guò)實(shí)際測(cè)試贞绵,各地圖服務(wù)商的瓦片等級(jí)和測(cè)試鏈接如下:
百度圖片瓦片的層級(jí)是[3~18] http://online1.map.bdimg.com/onlinelabel/?qt=tile&x=49310&y=10242&z=18
百度主頁(yè)的層級(jí)是[3~19] http://map.baidu.com/
高德圖片瓦片的層級(jí)是[1~19] http://wprd03.is.autonavi.com/appmaptile?style=7&x=427289&y=227618&z=19
高德地圖官網(wǎng)介紹的高德地圖層級(jí):
獲取當(dāng)前地圖縮放級(jí)別,在PC上,默認(rèn)取值范圍為[3,18]恍飘;在移動(dòng)設(shè)備上榨崩,默認(rèn)取值范圍為[3-19]
谷歌地圖瓦片層級(jí)是[0~21] http://mt2.google.cn/vt/lyrs=m@167000000&hl=zh-CN&gl=cn&x=1709157&y=910472&z=21&s=Galil
下圖是百度地圖的一個(gè)瓦片圖片展示:
[圖片上傳失敗...(image-ce75b9-1618472263075)]
- 瓦片等級(jí)由2的次方來(lái)劃分的,即1到4章母,4到16母蛛,16到
如圖示意:
[圖片上傳失敗...(image-fb329e-1618472263075)]
需要注意的問(wèn)題
- 瓦片像素坐標(biāo)的起始點(diǎn)
- 高德地圖、谷歌地圖的瓦片坐標(biāo)起點(diǎn)在左上角乳怎,像素坐標(biāo)(pixelX, pixelY)在瓦片中的起點(diǎn)為左上角彩郊。
- 百度地圖中,像素坐標(biāo)(pixelX, pixelY)的起點(diǎn)為左下角蚪缀。
百度地圖技術(shù)介紹
簡(jiǎn)單介紹一個(gè)地圖的底圖的相關(guān)知識(shí)吧秫逝,我們眼中看到的豐富的地圖信息,其中組成地圖的主要元素椿胯,莫過(guò)于地圖的一張張底圖瓦片了筷登。如下圖所示,
一般我們打開了一個(gè)地圖哩盲,其實(shí)際上可能會(huì)像上圖一樣前方,由一堆瓦片組成狈醉。1,2惠险,3苗傅,4表示不同的瓦片。 而某一張瓦片如下圖所示
在線地址:http://developer.baidu.com/map/custom/
百度地圖底圖繪制技術(shù)現(xiàn)狀
要想繪制上面所示的底圖班巩,目前現(xiàn)在主要有兩類技術(shù)
柵格: 也就是傳意義的圖片技術(shù)渣慕,在server端把圖片畫好。瀏覽器使用node-canvas實(shí)現(xiàn)百度地圖個(gè)性化底圖繪制標(biāo)簽拼出來(lái)
矢量:在瀏覽器使用canvas技術(shù)抱慌,將矢量的數(shù)據(jù)逊桦,在瀏覽器完成渲染。它最大的問(wèn)題在于:只支持高端瀏覽器
百度地圖抑进,目前兩種技術(shù)都已經(jīng)實(shí)現(xiàn)强经,如果大家使用的是mapapi,在高端瀏覽器下打開,你會(huì)發(fā)現(xiàn)寺渗,他是使用canvas繪制的匿情。
其中的地圖底圖在IE678等瀏覽器下,就是使用node-canvas在后端繪制出來(lái)的,獲取當(dāng)前繪制經(jīng)緯度信殊,之后通過(guò)接口調(diào)用瓦片炬称,
經(jīng)緯度坐標(biāo)與瓦片坐標(biāo)、像素坐標(biāo)的相互轉(zhuǎn)換涡拘,以平面坐標(biāo)為中間量進(jìn)行轉(zhuǎn)換玲躯。主要代碼為
// Bmap為百度JavaScript API V2.0的地圖對(duì)象
lnglatToPoint(longitude, latitude) {
let projection = new BMap.MercatorProjection();
let lnglat = new BMap.Point(longitude, latitude);
let point = projection.lngLatToPoint(lnglat);
return {
pointX: point.x,
pointY: point.y
};
}
pointToLnglat(pointX, pointY) {
let projection = new BMap.MercatorProjection();
let point = new BMap.Pixel(pointX, pointY);
let lnglat = projection.pointToLngLat(point);
return {
lng: lnglat.lng,
lat: lnglat.lat
};
}
http://developer.baidu.com/map/jsdemo.htm#a1_2
有興趣可以使用不同的瀏覽器打開看看就可以看出來(lái)。
如圖所示
[圖片上傳失敗...(image-809df1-1618472263075)]
canvas繪制圖片的優(yōu)點(diǎn)
- 1.它允許我們使用canvas的語(yǔ)法和接口寫成的js代碼鲸伴,放在server跑府蔗。
- 2.減少大量的DOM操作可以大大提升性能晋控。
如介紹
var Canvas = require('canvas')
, canvas = new Canvas(200,200)
, ctx = canvas.getContext('2d');
ctx.font = '30px Impact';
ctx.rotate(.1);
ctx.fillText("Awesome!", 50, 100);
var te = ctx.measureText('Awesome!');
ctx.strokeStyle = 'rgba(0,0,0,0.5)';
ctx.beginPath();
ctx.lineTo(50, 102);
ctx.lineTo(50 + te.width, 102);
ctx.stroke();
console.log('node-canvas實(shí)現(xiàn)百度地圖個(gè)性化底圖繪制');
目前使用canvas的原因有以下幾點(diǎn):
- 百度地圖已經(jīng)很好的實(shí)現(xiàn)使用canvas技術(shù)在瀏覽器完成渲染汞窗。
并有不錯(cuò)的展現(xiàn)效果和性能,在移動(dòng)端體驗(yàn)更好赡译。因?yàn)槭噶康臄?shù)據(jù)比請(qǐng)求圖片的體積要小的多
- 在canvas的方案下仲吏,已經(jīng)實(shí)現(xiàn)個(gè)性化底圖的繪制效果
底圖繪制由樣式+矢量數(shù)據(jù)組成。只要修改替換樣式文件蝌焚,就可以實(shí)現(xiàn)個(gè)性化地圖的渲染裹唆。
- 低端瀏覽器如IE6-8等瀏覽器,是不支持canvas功能的只洒。
展現(xiàn)地圖底圖许帐,必須使用柵格圖實(shí)現(xiàn)。需要有后端技術(shù)來(lái)生成底圖
- 由于不樣的樣式要求得到不同的底圖毕谴。就需要圖片是實(shí)時(shí)繪制的成畦,而且要求性能必須好
在線地址:http://api.map.baidu.com/customimage/tile?x=788&y=293&z=12&customid=midnight
可以看的出來(lái)距芬,速度是很快的。
[圖片上傳失敗...(image-b5a7e5-1618472263075)]
(9個(gè)瓦片生成的大圖)
參考資料
- 瓦片地圖服務(wù)
- node-canvas實(shí)現(xiàn)百度地圖個(gè)性化底圖繪制
- 地圖投影的N種姿勢(shì)
- 百度地圖API詳解之地圖坐標(biāo)系統(tǒng)
- 高德地圖層級(jí)
https://yolkpie.net/2021/03/30/%E7%A7%BB%E5%8A%A8%E7%AB%AF%E5%9C%B0%E5%9B%BE%E6%8A%80%E6%9C%AF/