需求
使用openlayer展示酒店房間平面圖,需要覆蓋房間的圖層時需要獲取到每個房間塊的座標,故需要一個工具將地圖背景圖片進行座標收集並生成文件
思路
- 首先是獲取座標的方式,openlayer例子裏有可以通過map的點擊事件獲取點擊位置的座標
- 其次明確openlayer添加layer所需的數據,我選擇的是使用GeoJSON轉換,故在寫進文件之前要將GeoJSON轉換成feature所需的數據都拼齊,最後轉成json保存
- 保存文件,這裏借用了FileSaver插件
實現及源碼
使用的插件
ol和FileSaver
下載方式
如果是vue項目:
npm install ol -D
npm install file-saver --save
如果是html:
我是去git上下了FileSaver的源碼
ol就是引用了外部鏈接
頁面元素
<template>
<div>
<div id="map"></div><!--地圖組件-->
<input id="roomnumber"
name="roomnumber"
placeholder="請輸入房間號"
class="input-style">
<div>
<button @click="confirm"
class="btn-style">確定</button>
<button @click="render"
class="btn-style">渲染</button>
<button @click="exportFile"
class="btn-style">導出文件</button>
</div>
</div>
</template>
主要就是地圖展示和三個功能按鈕以下分別說明(地圖展示忽略,可在另一篇文章裏看)
先定義幾個全局變量
data () {
return {
map: {},//地圖對象
list: {//存放進文件的數據
features: [],//對應多個圖層
},
renderlist: {//渲染的對象
type: 'FeatureCollection',
crs: {
type: 'name',
properties: {
name: 'EPSG:3857',
},
},
features: [],
},
coordinates: [[]],//收集的座標集合,根據openlayer裏圖層的集合的數據類型來定義的
roomnumber: '',
};
}
存放進文件的數據和渲染數據分開是因爲二者數據內容不一致,保存的數據不需要初始定義的部分類型數據。
map添加點擊事件
this.map.on('click', (evt) => {
this.coordinates[0].push(evt.coordinate);//收集座標
});
確定
就是用來將每個圖層塊區分開來,點擊一次就代表一個圖層塊的座標及相關數據獲取完成了
confirm () {
const id = Math.uuidFast();//獲取uuid作爲圖層的唯一標識
const value = {
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: this.coordinates,
},
id,
properties: { modelId: document.getElementById('roomnumber').value, id, type: 'room' },
};
this.renderlist.features.push(value);
this.list.features.push(value);
console.log(value);
this.coordinates = [[]];//要將座標集合清空,以免多個圖層的數據疊加
},
渲染
這個功能也是方便收集完座標之後能立刻看到根據收集的座標畫出的圖層的效果
render () {
const getStyles = (param) => {
console.log(param);
const style = new Style({
stroke: new Stroke({
color: '#2d9fd8',
width: 0,
}),
fill: new Fill({
color: '#2d9fd8',
opacity: 0.8,
}),
text: new Text({ // 文本樣式
className: 'map-font',
font: '14px Microsoft YaHei',
fill: new Fill({
color: 'black',
}),
}),
});
return style;
};
const styleFunction = (feature) => getStyles(feature.values_.modelId);//根據feature裏的數據進行樣式區分,這裏由於只是看效果,所以沒做渲染
const vectorSource = new VectorSource({
features: (new GeoJSON()).readFeatures(this.renderlist),//使用GeoJSON的readFeatures可將json數據轉換成feature對象
});
console.log(this.map.getLayers());
this.map.addLayer(new VectorLayer({
source: vectorSource,
style: styleFunction,
title: '',
type: 'room',
}));
},
導出
exportFile () {
const content = JSON.stringify(this.list);
const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
FileSaver.saveAs(blob, 'A-10.roomlayer');//這個是默認名稱,保存之後會有彈出框的,默認是下到C://user/dowload/,在彈出框裏可更改路徑和文件名稱
},
效果
深藍色區塊就是收集的座標畫出來的圖層