<template>
|
<div>
|
<div id='map' :style="{height:isDetail?'85vh':'40vh',width:'100%'}">
|
<div style="position: absolute;right:40%;top:-1%;z-index: 999999">
|
<p style="margin-top: 10px" v-if="!isDetail">
|
<el-button type="primary" size="small" @click="point()">绘制路线</el-button>
|
<el-button type="danger" size="small" @click="clearDraw()">重置</el-button>
|
</p>
|
</div>
|
<!--画线后的提示-->
|
<div class="mapTip" v-if="showTip" :style="{ top: tipPosition.h + 'px', left: tipPosition.w + 'px' }">
|
{{ tipTitle }}
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
import 'ol/ol.css'
|
import {Map, View, Feature} from 'ol'
|
import VectorSource from 'ol/source/Vector'
|
import Cluster from 'ol/source/Cluster'
|
import {Vector as VectorLayer, Tile as TileLayer} from 'ol/layer'
|
import LineString from "ol/geom/LineString";
|
import Point from 'ol/geom/Point';
|
import Icon from 'ol/style/Icon';
|
import {Style, Fill as StyleFill, Stroke as StyleStroke, Text as StyleText, Circle as StyleCircle} from 'ol/style'
|
import {Circle as GeomCircle, Point as GeomPoint, LineString as GeomLineString, Polygon as GeomPolygon} from 'ol/geom'
|
import Draw from 'ol/interaction/Draw'
|
import XYZ from "ol/source/XYZ";
|
import 'ol/ol.css'
|
|
export default {
|
name: 'OpenLayersMap',
|
props:['routeRange','isDetail',"pointLonLat"],
|
data() {
|
return {
|
map: null,
|
points: [],
|
// 线条点数组
|
linePoints: [],
|
// 多边形数组
|
polygonPoints: [],
|
draw: null,
|
drawLayer: null,
|
lineVector: null,
|
pointVector:null,
|
coordinates: [],// 保存绘画坐标地址 [[115.90490549080435, 28.746101718722358],[115.93151300423209, 28.741123538790717]]
|
toData: null,// 保存数据库格式坐标地址
|
showTip:false,
|
tipPosition: {//提示的位置
|
w: 200,
|
h: 10,
|
},
|
tipTitle:null
|
}
|
},
|
methods: {
|
|
createMap() {
|
let _this = this
|
|
_this.map = new Map({
|
target: 'map',
|
layers: [
|
new TileLayer({
|
source: new XYZ({
|
url: "https://webmap-tile.sf-express.com/MapTileService/rt?fetchtype=static&x={x}&y={y}&z={z}&project=sfmap&pic_size=256&pic_type=png8&data_name=361100&data_format=merged-dat&data_type=normal", // 行政区划
|
})
|
}),
|
|
],
|
view: new View({
|
// 设置中心点,默认南昌,用于规划南昌市的路线
|
center: [115.9032747077233, 28.67433116990186],
|
projection: 'EPSG:4326',
|
// 设置缩放倍数
|
zoom: 13,
|
minZoom: 8,
|
maxZoom: 19
|
})
|
})
|
_this.lineVector = new VectorLayer({
|
//layer所对应的source
|
source: new VectorSource({
|
wrapX: false // 禁止横向无限重复(底图渲染的时候会横向无限重复),设置了这个属性,可以让绘制的图形不跟随底图横向无限重复
|
}),
|
})
|
_this.pointVector = new VectorLayer({
|
//layer所对应的source
|
source: new VectorSource({
|
wrapX: false // 禁止横向无限重复(底图渲染的时候会横向无限重复),设置了这个属性,可以让绘制的图形不跟随底图横向无限重复
|
}),
|
})
|
_this.map.addLayer(_this.lineVector)
|
_this.map.addLayer(_this.pointVector)
|
_this.addLineDraw(_this.routeRange)
|
_this.addPoint(_this.pointLonLat)
|
},
|
// 绘画之后的样式
|
styleFunction() {
|
// 绘画之后的样式
|
let styles = [
|
new Style({
|
fill: new StyleFill({color: "rgba(255, 255, 255, 0.2)"}),
|
stroke: new StyleStroke({
|
color: 'rgb(252, 94, 32)',
|
width: 5
|
})
|
})
|
]
|
return styles
|
},
|
// 添加线路
|
addLineDraw(toData) {
|
// toData = 'LINESTRING(115.90505364627936 28.740342332731327,115.9119724729309 28.74040302419318,115.90766337913915 28.73566909016844)'
|
if (toData) {
|
// 将数据库点坐标数据转换
|
let entityData = "";
|
let entityArr = [];
|
entityData = toData.match(/\(([^)]*)\)/);
|
if (entityData && entityData != "") {
|
entityData = entityData[1].split(",");
|
for (let j = 0; j < entityData.length; j++) {
|
entityArr.push([
|
Number(entityData[j].split(" ")[0]),
|
Number(entityData[j].split(" ")[1]),
|
]);
|
}
|
}
|
// let lineCoords = [[115.90490549080435, 28.746101718722358],[115.93151300423209, 28.741123538790717],[115.90696542732779, 28.73408542233564],[115.90696542732779, 28.73408542233564]]
|
let lineCoords = entityArr
|
let view = this.map.getView();
|
view.setCenter([
|
lineCoords[Math.ceil(lineCoords.length / 2)][0],
|
lineCoords[Math.ceil(lineCoords.length / 2)][1],
|
]);
|
view.setZoom(14.5);
|
|
let feature_LineString = new Feature({
|
geometry: new LineString(lineCoords),
|
});
|
feature_LineString.setStyle(this.styleFunction());// 设置样式
|
this.lineVector.getSource().addFeature(feature_LineString);
|
}
|
},
|
// 添加点
|
addPoint(pointLonLat){
|
if (pointLonLat){
|
//设置点
|
let feature_Point = new Feature({
|
geometry: new Point([Number(pointLonLat.lon), Number(pointLonLat.lat)])
|
})
|
//点样式
|
let style = new Style({
|
image: new Icon({
|
src: "/img/dwicon.jpeg",
|
anchor: [0.48, 0.52],
|
// imgSize: [250,320],
|
scale: 0.2
|
}),
|
});
|
feature_Point.setStyle(style);
|
this.pointVector.getSource().addFeature(feature_Point);
|
let center = [Number(pointLonLat.lon), Number(pointLonLat.lat)];
|
let view = this.map.getView();
|
view.setZoom(16);
|
view.animate({
|
center: center,
|
duration: 5,
|
});
|
}
|
},
|
// 将点坐标集合转换为数据库数据
|
doData(val) {
|
let str = "LINESTRING(";
|
for (let k = 0; k < val.length; k++) {
|
str += `${val[k][0]} ${val[k][1]}`;
|
if (k != val.length - 1) {
|
str += ",";
|
}
|
}
|
str += ")";
|
// console.log(str)
|
return '\''+str+'\'';
|
},
|
// 开始绘制
|
point() {
|
let _this = this
|
_this.coordinates = []
|
_this.map.removeInteraction(_this.draw)
|
_this.lineVector.getSource().clear()
|
//提示
|
if(!_this.showTip){
|
_this.showTip = true
|
}
|
_this.tipTitle = "单击左键或者右键开始绘画"
|
//提示器
|
$("#map").off("mousemove").mousemove(function (e) {
|
_this.setTipPosition(e.offsetX, e.offsetY, 5, 5);
|
})
|
$("#map").off("mousedown").mousedown(function () {
|
_this.tipTitle = "可继续,或选择最终位置双击结束绘画"
|
})
|
|
_this.draw = new Draw({
|
source: _this.lineVector.getSource(),
|
type: 'LineString',
|
style: new Style({
|
stroke: new StyleStroke({
|
color: "red",
|
width: 3,
|
})
|
}),
|
})
|
_this.map.addInteraction(_this.draw)
|
// 点击事件
|
_this.map.on('click', function (e) {
|
// 将点坐标保存集合
|
_this.coordinates.push(e.coordinate)
|
})
|
// 结束事件
|
_this.draw.on('drawend', function () {
|
|
_this.map.removeInteraction(_this.draw);
|
_this.lineVector.setStyle(_this.styleFunction())// 路线画好之后的样式
|
// 将点坐标集合转换为数据库数据
|
let toData = _this.doData(_this.coordinates)
|
// 传值给父组件
|
_this.$emit('toData',toData)
|
//隐藏提示
|
_this.tipTitle = null;
|
_this.showTip = false
|
})
|
},
|
// 设置统一控制点击事件,需要画图方式在此处切换
|
handleClick(point) {
|
// 绘制连线
|
this.drawLineString(point)
|
// 绘制点
|
// this.drawPoint(point)
|
// 绘制圆形
|
// this.drawCircle(point)
|
// 绘制多边形
|
// this.drawPolygon(point)
|
},
|
// 绘制点位
|
drawPoint(center) {
|
let vectorLayer = this.getLayer()
|
|
let point = new GeomPoint(center)
|
let feature = new Feature(point)
|
vectorLayer.getSource().addFeature(feature)
|
this.map.addLayer(vectorLayer)
|
},
|
// 绘制连线
|
drawLineString(point) {
|
this.linePoints.push(point)
|
let featureLine = new Feature({
|
geometry: new GeomLineString(this.linePoints),
|
});
|
|
// 添加线的样式
|
let lineStyle = new Style({
|
fill: new StyleFill({
|
color: 'rgba(1, 210, 241, 0.1)'
|
}),
|
stroke: new StyleStroke({
|
color: 'rgba(255, 0, 0)',
|
width: 4,
|
}),
|
});
|
featureLine.setStyle(lineStyle);
|
|
let source = new VectorSource()
|
source.addFeature(featureLine)
|
let layer = new VectorLayer()
|
layer.setSource(source)
|
this.map.addLayer(layer)
|
},
|
// 绘制区域圆形
|
drawCircle(center) {
|
let vectorLayer = this.getLayer()
|
|
// 设置半径
|
let circle = new GeomCircle(center, 0.003)// 新建圆对象
|
let feature = new Feature(circle)// 新建Feature对象 并将circle传入
|
vectorLayer.getSource().addFeature(feature)// 将Feature对象填入图层源
|
this.map.addLayer(vectorLayer) // 将图层添至地图对象
|
},
|
// 画多边形
|
drawPolygon(point) {
|
this.polygonPoints.push(point)
|
let feature = new Feature({
|
geometry: new GeomPolygon([this.polygonPoints]),
|
attributes: null
|
});
|
// 添加线的样式
|
let lineStyle = new Style({
|
fill: new StyleFill({
|
color: 'rgba(1, 210, 241, 0.1)'
|
}),
|
stroke: new StyleStroke({
|
color: 'rgba(255, 0, 0)',
|
width: 4,
|
}),
|
});
|
feature.setStyle(lineStyle);
|
let source = new VectorSource();
|
source.addFeature(feature)
|
let vectorLayer = new VectorLayer({
|
source: source
|
})
|
this.map.addLayer(vectorLayer)
|
},
|
// 设置聚合点
|
addMarker() {
|
let source = new VectorSource();
|
// 随机创建200个要素,后台点位取出后按此格式处理
|
for (let i = 1; i <= 200; i++) {
|
let coordinates = [115.90 + Math.random() * 0.05, 28.64 + Math.random() * 0.05];
|
let feature = new Feature(new GeomPoint(coordinates));
|
source.addFeature(feature);
|
}
|
|
// 聚合
|
let clusterSource = new Cluster({
|
source: source,
|
distance: 50
|
})
|
|
let clusters = new VectorLayer({
|
source: clusterSource,
|
style: function (feature) {
|
let size = feature.get('features').length;
|
let style = new Style({
|
image: new StyleCircle({
|
radius: 20,
|
stroke: new StyleStroke({
|
color: 'white'
|
}),
|
fill: new StyleFill({
|
color: '#AAD3DF'
|
})
|
}),
|
text: new StyleText({
|
text: size.toString(),
|
fill: new StyleFill({
|
color: 'black'
|
})
|
})
|
})
|
return style;
|
}
|
});
|
|
this.map.addLayer(clusters)
|
},
|
// 重置图层
|
clearDraw(){
|
let _this = this
|
_this.coordinates = []
|
_this.map.removeInteraction(_this.draw)
|
_this.lineVector.getSource().clear()
|
_this.showTip = false
|
_this.tipTitle = null
|
},
|
// 获取新的 layer 图层对象
|
getLayer() {
|
return new VectorLayer({
|
source: new VectorSource({
|
features: ''
|
}),
|
// 设置样式,但不完全兼容
|
// style: function (feature) {
|
// let style = new Style({
|
// stroke: new StyleStroke({
|
// color: '#E80000',
|
// width: 2
|
// }),
|
// fill: new StyleFill({
|
// color: 'rgba(0,0,0,0)'
|
// })
|
// })
|
// return style
|
// }
|
})
|
},
|
// 设置提示位置
|
setTipPosition(x, y, n, m) {
|
let _this = this
|
_this.tipPosition.w = x + n;
|
_this.tipPosition.h = y + m;
|
},
|
},
|
mounted() {
|
this.createMap()
|
}
|
|
}
|
</script>
|
|
<style>
|
.mapTip {
|
background-color: rgb(168, 168, 168);
|
padding: 5px;
|
border: 1px solid #000;
|
position: absolute;
|
z-index: 10 !important;
|
border-radius: 5px;
|
}
|
</style>
|