需求
使用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/,在弹出框里可更改路径和文件名称
},
效果
深蓝色区块就是收集的坐标画出来的图层