openlayers根据半径绘制圆形,多圆连线并标记距离
实现一个什么效果呢,就是在openlayers上面,绘制三个圆形,绘制完成之后,三个圆心连接起来,然后标记出每两个圆心之间的距离。
期望效果:
写在前面
其实这个效果很好实现的,之前有几篇博文呢,关于 openlayers 根据半径绘制圆形,根据经纬度坐标绘制连线啥的都有涉及过,所以说如果要想实现今天想做的功能拼接一下就可以了,做一个快乐的代码裁缝。
绘制圆形
简单的什么安装 openlayers,导入,使用这里就不说了,如果不清楚直接看之前的博客,今天不多废话直接进入正题。
首先第一步,我们先绘制着三个蓝色的圆形。
关键代码如下,特别说一下哈,这是关键代码,之前有人问说你代码跑不起来,我特别无语,这是关键代码,那些基本的创建变量啥的,一看报错就知道没有创建,自己创建就行啦!没有那么难啊!适当的改一下就好了嘛。
// 绘制圆
addPoint() {
// 下面这个经纬度都是写死的哈,一会连线和标签都是一样的数据
let sites = [{
site: [116.400819, 39.916263],
name: '覆盖物1'
}, {
site: [116.450819, 39.917263],
name: '覆盖物2'
}, {
site: [116.350819, 39.857263],
name: '覆盖物3'
}]
let features = []
sites.forEach((item, index) => {
let feature = new Feature({
title: item.name,
geometry: new Circle(fromLonLat(item.site), this.getRadius(2000)),
})
feature.setStyle(
new Style({
fill: new Fill({
color: 'rgba(32, 157, 230, 1)'
}),
})
)
features.push(feature)
})
let source = new VectorSource()
source.addFeatures(features)
let layer = new VectorLayer({
opacity: 0.2
})
layer.setSource(source)
map.addLayer(layer)
},
好的,上面这一步完成之后呢,刷新页面看到的效果应该是下面的样子。
添加圆形标识
好了哈,我们给每个圆形添加一个文字标识,就是 覆盖物1,、覆盖物2、覆盖物3这种。
关键代码:
// 添加标识
addLabel() {
let sites = [{
site: [116.400819, 39.916263],
name: '覆盖物1'
}, {
site: [116.450819, 39.917263],
name: '覆盖物2'
}, {
site: [116.350819, 39.857263],
name: '覆盖物3'
}]
let features = []
sites.forEach((item, index) => {
let feature = new Feature({
title: item.name,
geometry: new Point(fromLonLat(item.site)),
})
feature.setStyle(
new Style({
text: new Text({
textAlign: 'center',
textBaseline: 'middle',
font: 'normal 17px 微软雅黑',
text: item.name,
fill: new Fill({
color: 'red'
}),
})
})
)
features.push(feature)
})
let sourceLabel = new VectorSource()
sourceLabel.addFeatures(features)
let layerLabel = new VectorLayer({
opacity: 1
})
layerLabel.setSource(sourceLabel)
map.addLayer(layerLabel)
},
上面的代码执行完成之后,就得到了下面的效果了。
绘制连线
接下来就是吧圆两两相连,用虚线也好,用实线也好,连接起来,这个也很简单,直接上代码。
// 添加连线
addLink() {
let sites = [{
site: [116.400819, 39.916263],
name: '覆盖物1'
}, {
site: [116.450819, 39.917263],
name: '覆盖物2'
}, {
site: [116.350819, 39.857263],
name: '覆盖物3'
}]
sites.push(sites[0])
let linkData = []
sites.forEach(item => {
linkData.push(fromLonLat(item.site))
})
let features = []
let featureLine = new Feature({
geometry: new LineString(linkData),
});
let lineStyle = new Style({
stroke: new Stroke({
color: '#000',
lineDash: [10, 10, 10, 10], // 重点在这
width: 2,
}),
});
// 添加线的样式
featureLine.setStyle(lineStyle);
features.push(featureLine)
let sourceLink = new VectorSource()
sourceLink.addFeatures(features)
let layerLink = new VectorLayer()
layerLink.setSource(sourceLink)
map.addLayer(layerLink)
},
上面的代码执行完成之后呢,圆就两两相连了。
标注距离
这个有两个步骤,第一个步骤,计算距离,第二个步骤,标注距离。
这个直接使用连线的图层操作就可以了,所以说修改连线代码,继续来计算距离,获取距离后进行标注。
// 添加连线
addLink() {
let sites = [{
site: [116.400819, 39.916263],
name: '覆盖物1'
}, {
site: [116.450819, 39.917263],
name: '覆盖物2'
}, {
site: [116.350819, 39.857263],
name: '覆盖物3'
}]
sites.push(sites[0])
let linkData = []
sites.forEach(item => {
linkData.push(fromLonLat(item.site))
})
let features = []
let featureLine = new Feature({
geometry: new LineString(linkData),
});
let lineStyle = new Style({
stroke: new Stroke({
color: '#000',
lineDash: [10, 10, 10, 10], // 重点在这
width: 2,
}),
});
// 添加线的样式
featureLine.setStyle(lineStyle);
features.push(featureLine)
let distanceList = []
for (let index = 0; index < sites.length - 1; index++) {
let site = fromLonLat([(sites[index].site[0] + sites[index + 1].site[0]) / 2, (sites[index].site[1] + sites[index + 1].site[1]) / 2])
let length = getDistance(sites[index].site, sites[index + 1].site);
distanceList.push({
site,
length,
})
}
distanceList.forEach((item) => {
let feature = new Feature({
title: '这是测试用的',
geometry: new Point(item.site),
})
feature.setStyle(
new Style({
text: new Text({
textAlign: 'center', //位置
textBaseline: 'middle', //基准线
font: 'normal 12px 微软雅黑', //文字样式
text: item.length.toFixed(0) + 'm', //文本内容
padding: [1, 1, 1, 1],
backgroundFill: new Fill({ //文本填充样式(即文字颜色)
color: '#d5e2f9'
}),
fill: new Fill({ //文本填充样式(即文字颜色)
color: 'red'
}),
})
})
)
features.push(feature)
})
let sourceLink = new VectorSource()
sourceLink.addFeatures(features)
let layerLink = new VectorLayer()
layerLink.setSource(sourceLink)
map.addLayer(layerLink)
},
好了,到此为止,最开始想要实现的效果就都出来了。
好了,下面放一下全部代码吧。
<template>
<div style="width:100%;height: 100%;position: relative;">
<div id="map"></div>
</div>
</template>
<script>
import 'ol/ol.css';
import Map from 'ol/Map';
import View from 'ol/View';
import XYZ from 'ol/source/XYZ';
import * as olProj from 'ol/proj';
import Draw from 'ol/interaction/Draw';
import Overlay from 'ol/Overlay';
import { Circle as CircleStyle, Fill, Stroke, Style } from 'ol/style';
import { OSM, Vector as VectorSource } from 'ol/source';
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer';
import Feature from 'ol/Feature';
import { Point, MultiLineString, LineString, Polygon } from "ol/geom";
import { fromLonLat } from 'ol/proj';
import Circle from 'ol/geom/Circle';
import { ScaleLine, defaults as defaultControls } from 'ol/control';
import { circular } from 'ol/geom/Polygon';
import * as olSphere from 'ol/sphere';
import LinearRing from 'ol/geom/LinearRing';
import { getTransform } from 'ol/proj';
import { getArea, getLength, getDistance } from 'ol/sphere';
import { unByKey } from 'ol/Observable';
import WMTS from 'ol/source/WMTS';
import ImageLayer from 'ol/layer/Image';
import ImageWMS from 'ol/source/ImageWMS';
import TileWMS from 'ol/source/TileWMS';
import WMTSTileGrid from 'ol/tilegrid/WMTS';
import * as olExtent from 'ol/extent';
import GeoJSON from 'ol/format/GeoJSON';
import Text from 'ol/style/Text';
var map = null; // /地图实例
var view = null; // 视图实例
export default {
name: "Home",
components: {
},
data() {
return { }
},
mounted() {
this.initMap()
},
methods: {
// 初始化地图
initMap() {
// 实例化Map
map = new Map({ // 创建一个地图
layers: [new TileLayer({
source: new OSM(),
}),],
target: 'map',
view: new View({
center: fromLonLat([116.403218, 39.92372]),
zoom: 15,
constrainResolution: true, // 设置缩放级别为整数
smoothResolutionConstraint: false, // 关闭无级缩放地图
}),
});
view = map.getView()
// 加载圆形
this.addPoint()
},
// 绘制圆
addPoint() {
let sites = [{
site: [116.400819, 39.916263],
name: '覆盖物1'
}, {
site: [116.450819, 39.917263],
name: '覆盖物2'
}, {
site: [116.350819, 39.857263],
name: '覆盖物3'
}]
let features = []
sites.forEach((item, index) => {
let feature = new Feature({
title: item.name,
geometry: new Circle(fromLonLat(item.site), this.getRadius(2000)),
})
feature.setStyle(
new Style({
fill: new Fill({
color: 'rgba(32, 157, 230, 1)'
}),
})
)
features.push(feature)
})
let source = new VectorSource()
source.addFeatures(features)
let layer = new VectorLayer({
opacity: 0.2
})
layer.setSource(source)
map.addLayer(layer)
this.addLabel()
this.addLink()
},
// 添加标识
addLabel() {
let sites = [{
site: [116.400819, 39.916263],
name: '覆盖物1'
}, {
site: [116.450819, 39.917263],
name: '覆盖物2'
}, {
site: [116.350819, 39.857263],
name: '覆盖物3'
}]
let features = []
sites.forEach((item, index) => {
let feature = new Feature({
title: item.name,
geometry: new Point(fromLonLat(item.site)),
})
feature.setStyle(
new Style({
text: new Text({
textAlign: 'center', //位置
textBaseline: 'middle', //基准线
font: 'normal 17px 微软雅黑', //文字样式
text: item.name, //文本内容
fill: new Fill({ //文本填充样式(即文字颜色)
color: 'red'
}),
})
})
)
features.push(feature)
})
let sourceLabel = new VectorSource()
sourceLabel.addFeatures(features)
let layerLabel = new VectorLayer({
opacity: 1
})
layerLabel.setSource(sourceLabel)
map.addLayer(layerLabel)
},
// 添加连线
addLink() {
let sites = [{
site: [116.400819, 39.916263],
name: '覆盖物1'
}, {
site: [116.450819, 39.917263],
name: '覆盖物2'
}, {
site: [116.350819, 39.857263],
name: '覆盖物3'
}]
sites.push(sites[0])
let linkData = []
sites.forEach(item => {
linkData.push(fromLonLat(item.site))
})
let features = []
let featureLine = new Feature({
geometry: new LineString(linkData),
});
let lineStyle = new Style({
stroke: new Stroke({
color: '#000',
lineDash: [10, 10, 10, 10], // 重点在这
width: 2,
}),
});
// 添加线的样式
featureLine.setStyle(lineStyle);
features.push(featureLine)
let distanceList = []
for (let index = 0; index < sites.length - 1; index++) {
let site = fromLonLat([(sites[index].site[0] + sites[index + 1].site[0]) / 2, (sites[index].site[1] + sites[index + 1].site[1]) / 2])
let length = getDistance(sites[index].site, sites[index + 1].site);
distanceList.push({
site,
length,
})
}
distanceList.forEach((item) => {
let feature = new Feature({
title: '这是测试用的',
geometry: new Point(item.site),
})
feature.setStyle(
new Style({
text: new Text({
textAlign: 'center', //位置
textBaseline: 'middle', //基准线
font: 'normal 12px 微软雅黑', //文字样式
text: item.length.toFixed(0) + 'm', //文本内容
padding: [1, 1, 1, 1],
backgroundFill: new Fill({ //文本填充样式(即文字颜色)
color: '#d5e2f9'
}),
fill: new Fill({ //文本填充样式(即文字颜色)
color: 'red'
}),
})
})
)
features.push(feature)
})
let sourceLink = new VectorSource()
sourceLink.addFeatures(features)
let layerLink = new VectorLayer()
layerLink.setSource(sourceLink)
map.addLayer(layerLink)
},
// 半径计算
getRadius(radius) {
let metersPerUnit = map.getView().getProjection().getMetersPerUnit();
let circleRadius = radius / metersPerUnit;
return circleRadius;
},
},
};
</script>
<style scoped>
#map {
width: 100%;
height: 100%;
background-color: azure;
}
</style>
<style scoped>
/deep/.ol-tooltip {
position: relative;
background: rgba(0, 0, 0, 0.7);
border-radius: 4px;
color: white;
padding: 4px 8px;
opacity: 0.7;
white-space: nowrap;
font-size: 12px;
cursor: default;
user-select: none;
}
/deep/.ol-tooltip-measure {
opacity: 1;
font-weight: bold;
}
/deep/.ol-tooltip-static {
background-color: #ffcc33;
color: black;
border: 1px solid white;
}
/deep/.ol-tooltip-measure:before,
/deep/.ol-tooltip-static:before {
border-top: 6px solid rgba(0, 0, 0, 0.5);
border-right: 6px solid transparent;
border-left: 6px solid transparent;
content: "";
position: absolute;
bottom: -6px;
margin-left: -7px;
left: 50%;
}
/deep/.ol-tooltip-static:before {
border-top-color: #ffcc33;
}
</style>
好了,今天就到这里,就是这么简单。
【版权声明】本博文著作权归作者所有,任何形式的转载都请联系作者获取授权并注明出处!
【重要说明】博文仅作为本人的学习记录,论点和观点仅代表个人而不代表技术的真理,目的是自我学习和有幸成为可以向他人分享的经验,因此有错误会虚心接受改正,但不代表此刻博文无误!
【Gitee地址】我是
标签:ol,连线,多圆,site,sites,let,import,new,openlayers From: https://blog.51cto.com/wjw1014/5932038