簡介
公司項目需要用到離線GIS應(yīng)用臭觉,因此做了一個詳細的技術(shù)調(diào)研昆雀。時間大概兩天辱志,方案選型確定,到服務(wù)的搭建狞膘,及包含具體應(yīng)用場景需要的換膚功能揩懒。
首先方案大概是有3個。
1.采用拼接地圖資源采用image方式渲染整個地圖挽封,然后在每個層級的圖片上進行點位標(biāo)注已球,和數(shù)據(jù)加載。優(yōu)點辅愿,加載速度快智亮,直接渲染業(yè)務(wù)需要的地圖部分即可,缺點前端工作量大点待,不利于后續(xù)產(chǎn)品化的發(fā)展阔蛉。
2.采用開源的openstreetmap,缺點openstreetmap開源的地圖不夠詳細癞埠,沒有需要展示的詳細資源状原。
3.采用arcgis方式,下載最新地圖的瓦片google苗踪,高德等等颠区,自己搭建離線gis服務(wù)。缺點徒探,項目應(yīng)用需要搭建單獨的gis服務(wù)瓦呼,優(yōu)點利于后續(xù)產(chǎn)品化的發(fā)展,不用單獨再造輪子测暗。一次搭建央串,后續(xù)項目可以直接應(yīng)用。
大體需要的工具及服務(wù)碗啄, geowebcache+全能電子地圖下載器+leaflet
geowebcache為arcgis提供基礎(chǔ)的服務(wù)质和,簡單說就是把所有的地圖資源放到這個服務(wù)里面,供你來調(diào)用加載稚字,渲染饲宿。
全能電子地圖下載器,為你提供基礎(chǔ)的地圖資源(png)圖片胆描。
leaflet是地圖組件瘫想,就是提供地圖內(nèi)的標(biāo)點,范圍等等的一個組件昌讲」梗可以從官網(wǎng)看到,不做過多闡述短绸。
本文只對第三點展開討論车吹。從0開始的搭建筹裕,部署,及展示窄驹,以及產(chǎn)品后續(xù)需要的換膚功能朝卒。服務(wù)搭建參考
1.https://www.cnblogs.com/luxiaoxun/p/5022333.html
2.https://www.cnblogs.com/ChineseMoonGod/p/6934928.html
雖然參考博客園的帖子,但是還會單獨重新寫一遍搭建流程乐埠,方便后面小伙伴整體參考吧抗斤,會比之前更詳細。
服務(wù)搭建(geowebcache):
服務(wù)下載地址:
https://www.geowebcache.org/
這里要說明饮戳,我下載了最新版本豪治,但是地圖服務(wù)一直沒加載出來洞拨,具體就是下載了相應(yīng)的瓦片扯罐,但是整個界面是空白。因為時間倉促烦衣,這里不得不降級歹河,采用了1.8.0,1.9.0版本均可以正常顯示,具體原因未知花吟。后續(xù)采用了1.9.0版本秸歧。具體調(diào)研的版本有:
。
1.運行服務(wù)
geowebcache下載之后是一個war包衅澈,就是我們傳統(tǒng)的web服務(wù)键菱。放在tomcat的webapps目錄下首先運行起來。
服務(wù)運行效果
地址:http://localhost:8080/geowebcache
2.修改配置
打開此文件
配置完之后重啟tomcat今布,會看到
到這里我們暫時停止配置经备,下載我們需要的地圖瓦片。
3.地圖資源下載
地圖資源下載我采用的是部默,全能電子地圖下載器(破解版)侵蒙。
工具操作不做過多闡述,應(yīng)該看看就懂了傅蹂。
下載好瓦片后纷闺,需要進行地圖拼接
選擇此參數(shù)
拼接完成后會生成以下文件
_alllayers內(nèi)存放就是我們地圖的瓦片資源,就是一堆png圖片份蝴。實際地圖渲染的效果就是在服務(wù)資源內(nèi)將png拼在在一起犁功,并且加載web內(nèi)。
每個層級的地圖瓦片資源婚夫。
備注:之前參考浸卦,說conf.cdi,和conf.xml需要打開,然后保存為unt-8無bom格式请敦,我就直接跟著操作了镐躲,具體有bom储玫,和無bom區(qū)別我沒有具體操作過。操作流程就是萤皂,用nodepad++打開兩個文件撒穷,然后再保存一下。
裆熙。
4.繼續(xù)修改配置
打開我們上一步自動生成的端礼,geowebcache.xml文件。
添加如下幾行字符
<arcgisLayer>
<name>ARCGIS-Demo</name>
<tilingScheme>D:\\GisMap\\Layer\\conf.xml</tilingScheme>
<tileCachePath>D:\\GisMap\\Layer\\_alllayers</tileCachePath>
</arcgisLayer>
很明顯conf.xml入录,_alllayers就是我們之前拼接完地圖的絕對路徑蛤奥。
接下來重啟服務(wù),查看效果僚稿。
可以看到我們剛剛配置的服務(wù)凡桥,點擊png即可預(yù)覽效果
5.對外提供服務(wù)
正常應(yīng)用時蚀同,肯定不是預(yù)覽效果就達到了我們的目的缅刽。我們需要調(diào)用類似,百度蠢络,google地圖那種衰猛,在我們項目內(nèi)加載服務(wù),并且根絕第三方的接口進行地圖相關(guān)的操作刹孔,例如標(biāo)點位信息啡省,做一些面積圖處理等等。
服務(wù)調(diào)用腳本如下:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Leaflet - Offline Demo</title>
<link rel="stylesheet" />
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet.js"></script>
</head>
<body>
<div id="map" style="height:100vh;background-color: #033345" ></div>
<script type="text/javascript">
//地圖的中心
var mapCenter = new L.LatLng(28.80748,104.593578);
var map = new L.Map('map', {
center : mapCenter,
zoom:5,//默認(rèn)展開的地圖層級髓霞,注意根據(jù)業(yè)務(wù)需求自己調(diào)整卦睹。
maxZoom:18,//最大層級,注意根據(jù)業(yè)務(wù)需求自己調(diào)整酸茴。
minZoom:15,//最小層級分预,注意根據(jù)業(yè)務(wù)需求自己調(diào)整。
attribution : '高德普通地圖'
});
var wmsLayer = L.tileLayer.wms("http://localhost:8080/geowebcache/service/wms", {
layers: 'ARCGIS-Demo1',//注意這里要和geowebcache.xml內(nèi)的 <name>ARCGIS-Demo</name>對應(yīng)
format: 'image/png'
});
wmsLayer.addTo(map);
//點位標(biāo)記
var marker = new L.Marker([28.80748,104.593578]);
var marker1 = new L.Marker([28.814023,104.571005]);
map.addLayer(marker);
map.addLayer(marker1);
marker.bindPopup("<br>五糧液廠區(qū)!</br><button onclick='alert(1);'>進入</button></p>").openPopup();
marker1.bindPopup("<p>紅若小學(xué)!</br><button onclick='alert(2);'>進入</button></p>").openPopup();
//標(biāo)記面積
var latlngs2 = [[28.812089,104.589441],[28.810779,104.583208],[28.808918,104.579024],[28.808072,104.579432],[28.805609,104.579432],[28.790829,104.591148]
,[28.802412,104.599473]]; //區(qū)域坐標(biāo)組
var areaLayer = L.polygon(latlngs2, {color: 'red',fillColor:'blue',weight:1}).addTo(map); //添加到地圖
</script>
</body>
</html>
這里有兩點要說明
1.name屬性
layers的name必須配置正確薪捍,否則地圖不加載笼痹。
2.地圖中心點
地圖點位中心的坐標(biāo),就是mapcenter節(jié)點的配置酪穿,如果不正確凳干,也會導(dǎo)致看不到地圖。這里我用的高德在線的取點坐標(biāo)進行標(biāo)記被济。
地址:https://lbs.amap.com/console/show/picker
要注意坐標(biāo)不要配置反了救赐,例如
5.查看服務(wù)運行效果
這樣已經(jīng)達到,調(diào)用地圖服務(wù)資源返回到我們的內(nèi)部應(yīng)用中。
6.換膚功能
因為不用應(yīng)用場景下经磅,可能要求地圖的皮膚顏色不同泌绣。這里我調(diào)研,發(fā)現(xiàn)沒有直接可應(yīng)用的地圖換膚資源预厌。因此就得動腦子了阿迈,因為我們_alllayers文件目錄內(nèi)存儲的是默認(rèn)的所有瓦片資源。那我應(yīng)該用腳本轧叽,把每個對應(yīng)png的色值重新調(diào)整苗沧,再保存到目錄內(nèi),然后調(diào)用即可炭晒。腳本內(nèi)容如下:
# *_*coding:utf-8 *_*
from PIL import Image
import os
#
# 遍歷文件夾
def walkFile(file):
for root, dirs, files in os.walk(file):
# root 表示當(dāng)前正在訪問的文件夾路徑
# dirs 表示該文件夾下的子目錄名list
# files 表示該文件夾下的文件list
# 遍歷文件
for f in files:
path = os.path.join(root, str(f));
i = 0
j = 0
# path = path.replace("\\","\\")
img = Image.open(path) # 讀取系統(tǒng)的內(nèi)照片
# img = Image.open("D:\\GisMap\\Layer1\\_alllayers\\L05\\R0000000A\\C0000001A.png") # 讀取系統(tǒng)的內(nèi)照片
print (img.size) # 打印圖片大小
print (img.getpixel((4, 4)))
width = img.size[0] # 長度
height = img.size[1] # 寬度
for i in range(0, width): # 遍歷所有長度的點
for j in range(0, height): # 遍歷所有寬度的點
data = (img.getpixel((i, j))) # 打印該圖片的所有點
if isinstance(data, tuple) and len(data) == 3:
print (data) # 打印每個像素點的顏色RGBA的值(r,g,b,alpha)
print (data[0]) # 打印RGBA的r值
if (data[0] >= 170 and data[1] >= 170 and data[2] >= 170): # RGBA的r值大于170待逞,并且g值大于170,并且b值大于170
img.putpixel((i, j), (3,52,71,255)) # 則這些像素點的顏色改成大紅色
elif (data[0] >= 68 and data[1] >= 68 and data[2] >= 68 and data[0] >= 111 and data[1] >= 111 and data[2] >= 111): # RGBA的r值大于170,并且g值大于170,并且b值大于170
img.putpixel((i, j), (0,94,94,255)) # 則這些像素點的顏色改成大紅色
elif (data[0] >= 0 and data[1] >= 0 and data[2] >= 0 and data[0] <= 68 and data[1]<= 68 and data[2]<= 68): # RGBA的r值大于170网严,并且g值大于170,并且b值大于170
img.putpixel((i, j), (0, 94, 94, 255)) # 則這些像素點的顏色改成大紅色
img = img.convert("RGB") # 把圖片強制轉(zhuǎn)成RGB
img.save(path) # 保存修改像素點后的圖片
def main():
walkFile("D:\\GisMap\\Layer1\\_alllayers")
if __name__ == '__main__':
main()
這里我是隨便在高德的皮膚中识樱,取了幾個顏色進行替換。但是這里有個遺留問題就是屿笼,單線程對每個像素進行替換牺荠,效率還是蠻差的翁巍。這里還是有很大的優(yōu)化空間驴一,多線程,對每個層級不同的瓦片資源進行批量更新灶壶。
高德官方皮膚截圖如下:
腳本處理效果如下:
這里只是粗略的進行幾個大的色值替換肝断,同樣也有很大的優(yōu)化空間。
7換膚資源切換
同理驰凛,因為我們處理好了另一個皮膚的所有文件后胸懈,保存在一個新的_alllayers文件夾內(nèi)。
再次編輯geowebcache.xml恰响,增加新皮膚的節(jié)點信息趣钱,然后重啟服務(wù)。
<arcgisLayer>
<name>ARCGIS-Demo1</name>
<tilingScheme>D:\\GisMap\\Layer1\\conf.xml</tilingScheme>
<tileCachePath>D:\\GisMap\\Layer1\\_alllayers</tileCachePath>
</arcgisLayer>