功能实现
画线并编辑 api:draw, modify
添加绘制功能 draw
- 注意事项: 在添加绘制功能之前,应提前先在地图渲染时,为绘制功能添加一个矢量图层
import VectorLayer from 'ol/layer/Vector'
import VectorSource from "ol/source/Vector"
let drawsource = new VectorSource()
let drawvector = new VectorLayer({
source: drawsource,
});
map.addLayer(drawvector)
- 添加绘制功能
import {Draw, Snap} from 'ol/interaction'
let draw = new Draw({
source: drawsource, //之前预先创建的图层的 `drawsource`
}
map.addInteraction(draw)
let snap = new Snap({source: drawsource}) //snap 捕捉并处理绘制以及修改时的矢量元素
map.addInteraction(snap)
绘制中设置动态样式
- 绘制中动态样式,是在用户绘制过程中显示的样式,并非绘制结束最终的样式
- openlayers 中 Draw 对象有一个 Style 属性, Style 可以是一个样式数组,也可以是一个函数(返回一个样式数组; 这个函数有两个参数 分别是: fearture(绘制中的), resolution(视图的分辨率))
- 这里我们的思路就是: 通过style 函数的fearture 参数来获取绘制点,并为之添加样式
是在添加绘制功能的时候添加样式
import {Draw, Snap} from 'ol/interaction'
let draw = new Draw({
source: drawsource, //之前预先创建的图层的 `drawsource`
style(feature, r){
// **重点: 此处的 feature 是跟随鼠标的变化实时的数据,不是你绘制的点的数据 **
// ** 指定绘制点添加样式** :用到 Style 的一个可以指定 geometry 来添加样式
let coords = feature.getGeometry().getCoordinates()
let styles = []
for(let i in coords){
styles.push(new Style({
geometry: new Point(coords[i]) //指定点
... //此处写你的样式
}))
}
return styles
}
}
map.addInteraction(draw)
绘制结束事件监听
添加修改功能 modify
修改中的动态样式
坐标转换
- openlayers 默认坐标系是同谷歌地图一样的
EPSG:3857
, 国内常用的坐标系是84坐标系EPSG:4326
,此时坐标系转换功能就是必需的了
参数名 |
参数描述 |
coordinate |
坐标 |
source |
坐标的坐标系 |
destination |
目标坐标系 |
import { transform } from 'ol/proj'
let oldCoord = [13031076.441730658, 4735129.733960388] //EPSG:3857
let oldCoord84 = [117.16932799710696, 39.088029694977024] //EPSG:4326
let coordinate84 = new transform(oldCoord, "EPSG:3857", "EPSG:4326"); //转换为84坐标系
let coordinate = new transform(oldCoord84, "EPSG:3857", "EPSG:4326"); //转换为Google Web 墨卡托坐标系
坐标比较
- 在做绘制和修改功能时,不免需要进行前后坐标的对比,而坐标是一个数组模式的数据,这就涉及到数组的对比方式了。
let oldCoordinate = [13031076.441730658, 4735129.733960388]
let newCoordinate = [13031152.878758943, 4733983.178536111]
oldCoordinate.toString() === newCoordinate.toString() //此处使用转换为字符串进行比较,数组的顺序与值同时相同才能代表坐标的相同
地图实现蒙层
单击地图事件监听
- openlayers 中的 map对象有一个
singleclick
事件,回调函数参数:
MapBrowserEvent {type: "singleclick", target: Map, map: Map, frameState: {…}, originalEvent: PointerEvent, pixel_: Array(2), target: Map, type: "singleclick", coordinate: Array(2), pixel: Array(2)}
map.on('singleclick', (e)=>{
//需要获取到矢量图层可以使用: map.forEachLayerAtPixel(pixel, callback, opt_options), 获取坐标: map.getCoordinateFromPixel(pixel)
map.forEachFeatureAtPixel(e.pixel, (feature)=>{
//...数据处理 此处为你点击的 feature
}, {
//options: layerFilter | hitTolerance | checkWrapped})
})
地图可视范围监听
- 此处是在地图的可视范围发生变化时,通过监听地图的
moveend
事件进而获取当前的可视范围
import {getTopLeft, getTopRight, getBottomLeft, getBottomRight} from 'ol/extent'
map.on('moveend', (event)=>{
//获取可视化区域得范围
let coods = event.map.getView().calculateExtent( event.map.getSize()),
postcooders = [getTopLeft(coods), getTopRight(coods), getBottomRight(coods) ,getBottomLeft(coods), getTopLeft(coods)]; //可视区域为一个多边形,需是闭合的
})
串线多样式编辑
- openlayers
Style
对象可以接收一个数组,对于同一条串线可以有多种不同的样式,只需按照你的样式顺序添加即可
import Feature from 'ol/Feature';
import LineString from 'ol/geom/LineString';
import Style from 'ol/style/Style';
let lineFeature = new Feature(new LineString([coordinates]))
let yourStyle1 = new Style({...}), yourStyle2 = new Style({...});
let yourStyles = [yourStyle1, yourStyle2, ...] //依次添加要用 Array.prototype.push(), 解构语言是不支持的
lineFeature.setStyle(yourStyles)
带箭头的串线样式编辑
- 大概思路: 获取串线的最后两个点=>计算出串线的走向=>为最终点添加箭头图标(含串线走向的属性)
import {Point} from 'ol/geom'
//start 串线走向计算第一个点, end 串线最终点, iconImg 串线最终的箭头图标
arrowIcon(start, end, iconImg){
let feature = new Feature({
geometry: new Point(end),
});
let rotation = Math.atan2(end[0] - start[0], end[1] - start[1]); //计算串线走向
feature.setStyle(
new Style({
image: new Icon({
anchor: [0.5, 0.5],
src: iconImg,
rotateWithView: true, // 图标旋转到串线走向
rotation: rotation, //图标旋转到串线走向
...
}),
})
);
return feature
},
绘制多边形 (闭合的形状)
- 多边形是一个闭合的形状,所以坐标组第一和最后一个坐标一样
import { Polygon } from 'ol/geom'
// coords = [[long, lat],[long, lat],[long, lat], ...]
let yourPolygon = new Polygon([coords])
//...更多api请查看官网
覆盖物的实时位置监听
- openlayers overlay 有一个
setPosition
的方法, 只需接收到数据,使用此方法即可修改覆盖物的位置
`<div id="overlayEl" ><img src="..."></div>`
import { Overlay } from "ol"
let yourOverlay = new Overlay(
{
id: "realair",
element: document.getElementById("realAir"),
position: this.coordTransform(realFeatures),
positioning: "center-center",
offset: [3, 10]
})
map.addOverlay(yourOverlay);
yourOverlay.setPosition(newCoordinate) //newCoordinate 覆盖物的新坐标