openlayer创建各种Feature
设置标注点
js
/**
* 标注点样式
*/
const pointCircleStyle = new Style({
image: new CircleStyle({
radius: 5,
fill: new Fill({
color: '#f49d41'
}),
stroke: new Stroke({
color: '#836365',
width: 1
})
}),
})
const pointIconleStyle = (src) => {
return new Style({
image: new Icon({
src,
// image: new CircleStyle({
// anchor: [0.5, 0.5],//图标的锚点,经纬度点所对应的图标的位置,默认是[0.5, 0.5],即为标注图标的中心点位置
anchorOrigin: 'top-right',//锚点的偏移位置,默认是top-left,
anchorXUnits: 'fraction',//锚点X的单位,默认为百分比,也可以使用px
anchorYUnits: 'pixels',//锚点Y的单位,默认为百分比,也可以使用px
offsetOrigin: 'top-right',//原点偏移bottom-left, bottom-right, top-left, top-right,默认 top-left
// offset:[0,10],
//图标缩放比例
// scale:0.5,//可以设置该比例实现,图标跟随地图层级缩放
//透明度
opacity: 0.75,//如果想隐藏某个图标,可以单独设置该值,透明度为0时,即可隐藏,此为隐藏元素的方法之一。
}),
})
}
/**
* 标注点样式
*/
const pointCircleStyle = new Style({
image: new CircleStyle({
radius: 5,
fill: new Fill({
color: '#f49d41'
}),
stroke: new Stroke({
color: '#836365',
width: 1
})
}),
})
const pointIconleStyle = (src) => {
return new Style({
image: new Icon({
src,
// image: new CircleStyle({
// anchor: [0.5, 0.5],//图标的锚点,经纬度点所对应的图标的位置,默认是[0.5, 0.5],即为标注图标的中心点位置
anchorOrigin: 'top-right',//锚点的偏移位置,默认是top-left,
anchorXUnits: 'fraction',//锚点X的单位,默认为百分比,也可以使用px
anchorYUnits: 'pixels',//锚点Y的单位,默认为百分比,也可以使用px
offsetOrigin: 'top-right',//原点偏移bottom-left, bottom-right, top-left, top-right,默认 top-left
// offset:[0,10],
//图标缩放比例
// scale:0.5,//可以设置该比例实现,图标跟随地图层级缩放
//透明度
opacity: 0.75,//如果想隐藏某个图标,可以单独设置该值,透明度为0时,即可隐藏,此为隐藏元素的方法之一。
}),
})
}
js
// 设置标注点
export const addPoint = (olMap, pointDataList, isIcon = false, src = '/') => {
// mapUtils.setPointTest(olMap)
// 创建点的数据源
const vectorSource = new VectorSource({
features: [],
});
// 创建点图层
const vectorLayer = new VectorLayer({
source: vectorSource,
zIndex: 1,
style: !isIcon ? pointCircleStyle : pointIconleStyle(src)
});
olMap.addLayer(vectorLayer);
pointDataList.forEach((item) => {
const point = new Point(fromLonLat(item.lonlat));
const feature = new Feature({
geometry: point,
type: 'Marker',
pointData: item.pointData
});
vectorSource.addFeature(feature);
});
}
// 设置标注点
export const addPoint = (olMap, pointDataList, isIcon = false, src = '/') => {
// mapUtils.setPointTest(olMap)
// 创建点的数据源
const vectorSource = new VectorSource({
features: [],
});
// 创建点图层
const vectorLayer = new VectorLayer({
source: vectorSource,
zIndex: 1,
style: !isIcon ? pointCircleStyle : pointIconleStyle(src)
});
olMap.addLayer(vectorLayer);
pointDataList.forEach((item) => {
const point = new Point(fromLonLat(item.lonlat));
const feature = new Feature({
geometry: point,
type: 'Marker',
pointData: item.pointData
});
vectorSource.addFeature(feature);
});
}
绘制圆
js
// 绘制圆
export const addCircle = (olMap, circleItem, isFlicker) => {
let features = []
const fillStyle = new Fill({
color: 'rgba(32, 157, 230, 0.2)'
})
let feature = new Feature({
type: "Circle",
circleData: circleItem,
// 圆心 - 半径
geometry: new Circle(fromLonLat([circleItem.longitude, circleItem.latitude]), 550),
})
feature.setStyle(
new Style({
fill: fillStyle,
})
)
features.push(feature)
let source = new VectorSource()
source.addFeatures(features)
let layer = new VectorLayer({
// opacity: 0.2,
})
layer.setSource(source)
olMap.addLayer(layer)
// 需要闪烁时调用
if (isFlicker) {
let radius = 0
layer.on('postrender', evt => {
if (radius >= 20) radius = 0;
var opacity = (20 - radius) * (1 / 20); //不透明度
var pointStyle = new Style({
radius: radius,
stroke: new Stroke({
color: "rgba(255,0,0" + opacity + ")",
width: 5 - radius / 6, //设置宽度
}),
});
// 获取矢量要素上下文
let vectorContext = getVectorContext(evt);
vectorContext.setStyle(pointStyle);
vectorContext.drawGeometry(feature.getGeometry());
radius = radius + 0.3; //调整闪烁速度
//请求地图渲染(在下一个动画帧处)
olMap.render();
})
}
}
// 绘制圆
export const addCircle = (olMap, circleItem, isFlicker) => {
let features = []
const fillStyle = new Fill({
color: 'rgba(32, 157, 230, 0.2)'
})
let feature = new Feature({
type: "Circle",
circleData: circleItem,
// 圆心 - 半径
geometry: new Circle(fromLonLat([circleItem.longitude, circleItem.latitude]), 550),
})
feature.setStyle(
new Style({
fill: fillStyle,
})
)
features.push(feature)
let source = new VectorSource()
source.addFeatures(features)
let layer = new VectorLayer({
// opacity: 0.2,
})
layer.setSource(source)
olMap.addLayer(layer)
// 需要闪烁时调用
if (isFlicker) {
let radius = 0
layer.on('postrender', evt => {
if (radius >= 20) radius = 0;
var opacity = (20 - radius) * (1 / 20); //不透明度
var pointStyle = new Style({
radius: radius,
stroke: new Stroke({
color: "rgba(255,0,0" + opacity + ")",
width: 5 - radius / 6, //设置宽度
}),
});
// 获取矢量要素上下文
let vectorContext = getVectorContext(evt);
vectorContext.setStyle(pointStyle);
vectorContext.drawGeometry(feature.getGeometry());
radius = radius + 0.3; //调整闪烁速度
//请求地图渲染(在下一个动画帧处)
olMap.render();
})
}
}
添加线
js
// 添加线
export const addLine = (olMap, position, lineConfig = {}, style) => {
// 创建线要素并添加到地图上
const lineFeature = new Feature({
// geometry: new LineString([[13538079.386677982, 3488521.2319548605], [13540229.178098504, 3488093.6623278903]]),
geometry: new LineString(position),
...lineConfig
});
if (!style) {
style = setFeaturesStyle('rgba(255, 255, 255, 0.2)', 'rgba(0, 0, 0, 0.5)', false, 3)
}
lineFeature.setStyle(style);
// lineFeature.setStyle(styleFunction);
const vectorSource = new VectorSource({
features: [lineFeature],
});
const vectorLayer = new VectorLayer({
source: vectorSource,
zIndex: 9
});
olMap.addLayer(vectorLayer);
}
// 添加线
export const addLine = (olMap, position, lineConfig = {}, style) => {
// 创建线要素并添加到地图上
const lineFeature = new Feature({
// geometry: new LineString([[13538079.386677982, 3488521.2319548605], [13540229.178098504, 3488093.6623278903]]),
geometry: new LineString(position),
...lineConfig
});
if (!style) {
style = setFeaturesStyle('rgba(255, 255, 255, 0.2)', 'rgba(0, 0, 0, 0.5)', false, 3)
}
lineFeature.setStyle(style);
// lineFeature.setStyle(styleFunction);
const vectorSource = new VectorSource({
features: [lineFeature],
});
const vectorLayer = new VectorLayer({
source: vectorSource,
zIndex: 9
});
olMap.addLayer(vectorLayer);
}
创建文字图层
js
// 创建文字图层
export const addTextOverlay = (olMap, text, position, textOverlayConfig = {}, isRemove) => {
// console.log('创建文字图层Overlay', olMap, gridData)
// 创建文本样式
const textStyle = new Style({
text: new Text({
text,
fill: new Fill({ color: '#333333' }),
// stroke: new Stroke({ color: '#fff', width: 2 }),
font: '18px pingfang',
textAlign: 'center', // 文本对齐
textBaseline: 'bottom', // 文本基线
padding: [5, 10, 5, 10], // 文本周围的填充
overflow: true, // 允许文本溢出
rotateWithView: false, // 不随地图旋转
rotation: 0, // 文本旋转角度
}),
});
if (isRemove) {
// 清除某类图层
removeLayer(olMap, layerItem => {
// olMap.removeLayer(layerItem)
let currentFeature = layerItem.getSource().getFeatures()[0]
isRemove(layerItem, currentFeature)
})
}
// 创建文本特征
const feature = new Feature({
geometry: new Point(fromLonLat(position)),
...textOverlayConfig
});
// 设置特征的样式
feature.setStyle(textStyle);
// 创建文本图层
const vectorLayer = new VectorLayer({
source: new VectorSource({
features: [feature],
}),
zIndex: 9
});
// 将文本图层添加到地图
olMap.addLayer(vectorLayer);
}
// 创建文字图层
export const addTextOverlay = (olMap, text, position, textOverlayConfig = {}, isRemove) => {
// console.log('创建文字图层Overlay', olMap, gridData)
// 创建文本样式
const textStyle = new Style({
text: new Text({
text,
fill: new Fill({ color: '#333333' }),
// stroke: new Stroke({ color: '#fff', width: 2 }),
font: '18px pingfang',
textAlign: 'center', // 文本对齐
textBaseline: 'bottom', // 文本基线
padding: [5, 10, 5, 10], // 文本周围的填充
overflow: true, // 允许文本溢出
rotateWithView: false, // 不随地图旋转
rotation: 0, // 文本旋转角度
}),
});
if (isRemove) {
// 清除某类图层
removeLayer(olMap, layerItem => {
// olMap.removeLayer(layerItem)
let currentFeature = layerItem.getSource().getFeatures()[0]
isRemove(layerItem, currentFeature)
})
}
// 创建文本特征
const feature = new Feature({
geometry: new Point(fromLonLat(position)),
...textOverlayConfig
});
// 设置特征的样式
feature.setStyle(textStyle);
// 创建文本图层
const vectorLayer = new VectorLayer({
source: new VectorSource({
features: [feature],
}),
zIndex: 9
});
// 将文本图层添加到地图
olMap.addLayer(vectorLayer);
}
绘制多边形
js
/**
* 绘制多边形
*
* @param {*} olMap
* @param {*} coords 多边形的坐标数组
*/
export const createPolygon = (olMap, { coords, lonlat, polygonData }, next, polygonStyle = setFeaturesStyle("rgba(0, 255, 0, 0.4)", "rgba(0, 255, 0, 1)")) => {
// console.log(olMap, coords, lonlat)
// 创建多边形
let polygon = new Feature({
geometry: new Polygon([coords]),
type: 'Polygon',
polygonData: {
coords,
lonlat,
...polygonData
}
});
// 设置多边形样式
polygon.setStyle(polygonStyle)
// 创建矢量图层并添加多边形
let vectorLayer = new VectorLayer({
source: new VectorSource({
features: [polygon]
})
});
olMap.addLayer(vectorLayer);
if (next) {
next(polygon)
}
}
/**
* 绘制多边形
*
* @param {*} olMap
* @param {*} coords 多边形的坐标数组
*/
export const createPolygon = (olMap, { coords, lonlat, polygonData }, next, polygonStyle = setFeaturesStyle("rgba(0, 255, 0, 0.4)", "rgba(0, 255, 0, 1)")) => {
// console.log(olMap, coords, lonlat)
// 创建多边形
let polygon = new Feature({
geometry: new Polygon([coords]),
type: 'Polygon',
polygonData: {
coords,
lonlat,
...polygonData
}
});
// 设置多边形样式
polygon.setStyle(polygonStyle)
// 创建矢量图层并添加多边形
let vectorLayer = new VectorLayer({
source: new VectorSource({
features: [polygon]
})
});
olMap.addLayer(vectorLayer);
if (next) {
next(polygon)
}
}
使用draw创建多边形
js
// 创建多边形(选区)
export const drawPolygon = (olMap) => {
// console.log('创建多边形(选区)', olMap)
olMap.addInteraction(new Draw({
source: new VectorSource(),
type: 'Polygon',
}));
// 获取绘制完成的多边形
olMap.getInteractions().getArray().forEach(interaction => {
if (interaction instanceof Draw) {
interaction.on('drawend', (event) => {
const { feature } = event
const geometry = feature.getGeometry();
const coords = geometry.getCoordinates()[0]
const lonlat = geometry.transform('EPSG:3857', 'EPSG:4326').getCoordinates()[0]
// console.log(lonlat, coords)
if (geometry instanceof Polygon) {
// console.log("所选点位坐标", geometry.getCoordinates());
createPolygon(olMap, { coords, lonlat })
olMap.removeInteraction(interaction); // 从地图中移除交互
}
});
}
});
}
// 创建多边形(选区)
export const drawPolygon = (olMap) => {
// console.log('创建多边形(选区)', olMap)
olMap.addInteraction(new Draw({
source: new VectorSource(),
type: 'Polygon',
}));
// 获取绘制完成的多边形
olMap.getInteractions().getArray().forEach(interaction => {
if (interaction instanceof Draw) {
interaction.on('drawend', (event) => {
const { feature } = event
const geometry = feature.getGeometry();
const coords = geometry.getCoordinates()[0]
const lonlat = geometry.transform('EPSG:3857', 'EPSG:4326').getCoordinates()[0]
// console.log(lonlat, coords)
if (geometry instanceof Polygon) {
// console.log("所选点位坐标", geometry.getCoordinates());
createPolygon(olMap, { coords, lonlat })
olMap.removeInteraction(interaction); // 从地图中移除交互
}
});
}
});
}
使用draw实现测距
js
// 测距
export const testDistance = (olMap, next) => {
// console.log("测距", olMap)
let measure = new Draw({
source: new VectorSource(),
type: 'LineString',
/* style: new Style({
fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)' }),
stroke: new Stroke({ color: 'rgba(0, 0, 0, 0.5)', width: 2 })
}) */
})
olMap.addInteraction(measure);
measure.on('drawend', (event) => {
const { feature } = event
const line = feature.getGeometry();
let length = getLength(line);
length = length.toFixed(2)
const coords = line.getCoordinates()
const lonlat = line.transform('EPSG:3857', 'EPSG:4326').getCoordinates()
// console.log('Line length: ' + length + ' meters');
// 如果需要外部提供数据
if (next) {
next(length)
}
// 创建线要素并添加到地图上
addLine(olMap, coords, { tempType: 'testDistanceTemp' })
// 创建文本要素以显示距离
addTextOverlay(olMap, length + '米', lonlat[0], { tempType: 'testDistanceTemp' })
});
}
// 测距
export const testDistance = (olMap, next) => {
// console.log("测距", olMap)
let measure = new Draw({
source: new VectorSource(),
type: 'LineString',
/* style: new Style({
fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)' }),
stroke: new Stroke({ color: 'rgba(0, 0, 0, 0.5)', width: 2 })
}) */
})
olMap.addInteraction(measure);
measure.on('drawend', (event) => {
const { feature } = event
const line = feature.getGeometry();
let length = getLength(line);
length = length.toFixed(2)
const coords = line.getCoordinates()
const lonlat = line.transform('EPSG:3857', 'EPSG:4326').getCoordinates()
// console.log('Line length: ' + length + ' meters');
// 如果需要外部提供数据
if (next) {
next(length)
}
// 创建线要素并添加到地图上
addLine(olMap, coords, { tempType: 'testDistanceTemp' })
// 创建文本要素以显示距离
addTextOverlay(olMap, length + '米', lonlat[0], { tempType: 'testDistanceTemp' })
});
}
添加带箭头的线
js
// 添加带箭头的线
export const addArrowLine = (olMap, position, src = '../src/components/OpenlayerBaseMap/icon/arrow.svg', businessType = 'arrowLine') => {
// console.log('添加带箭头的线', olMap)
function stylefunction(feature) {
const geometry = feature.getGeometry()
// 轨迹地理长度
const totalLength = geometry.getLength()
// 像素间隔步长
let step = 50
// 将像素步长转实际地理距离步长
let StepLength = step * olMap.getView().getResolution()
// 箭头总数
let arrowNum = Math.floor(totalLength / StepLength)
const styles = [
// linestring
new Style({
stroke: new Stroke({
// color: 'rgb(164 164 162 / 88%)',
color: '#42b983',
width: 5,
}),
}),
];
const rotations = [];
const distances = [0];
geometry.forEachSegment(function (start, end) {
let dx = end[0] - start[0];
let dy = end[1] - start[1];
let rotation = Math.atan2(dy, dx);
distances.unshift(Math.sqrt(dx ** 2 + dy ** 2) + distances[0]);
rotations.push(rotation);
});
for (let i = 1; i < arrowNum; i++) {
let arrow_coor = geometry.getCoordinateAt(i * 1.0 / arrowNum)
const d = i * StepLength;
const grid = distances.findIndex((x) => x <= d);
styles.push(
new Style({
geometry: new Point(arrow_coor),
image: new Icon({
src,
opacity: 1,
anchor: [0.5, 0.5],
rotateWithView: true,
rotation: - rotations[distances.length - grid - 1],
scale: 0.8
})
})
)
}
return styles
}
/* const styleFunction = function (feature) {
const geometry = feature.getGeometry();
const styles = [
// linestring
new Style({
stroke: new Stroke({
color: 'rgb(164 164 162 / 88%)',
width: 5,
}),
}),
];
geometry.forEachSegment(function (start, end) {
const dx = end[0] - start[0];
const dy = end[1] - start[1];
const rotation = Math.atan2(dy, dx);
const coord = [start[0] + dx / 2, start[1] + dy / 2]
// arrows
styles.push(
new Style({
geometry: new Point(coord),
image: new Icon({
src,
anchor: [0.75, 0.5],
rotateWithView: true,
rotation: -rotation,
scale: 0.03
}),
})
);
});
return styles;
}; */
addLine(olMap, position, { businessType }, stylefunction)
// addLine(olMap, position, { businessType }, styleFunction)
}
// 添加带箭头的线
export const addArrowLine = (olMap, position, src = '../src/components/OpenlayerBaseMap/icon/arrow.svg', businessType = 'arrowLine') => {
// console.log('添加带箭头的线', olMap)
function stylefunction(feature) {
const geometry = feature.getGeometry()
// 轨迹地理长度
const totalLength = geometry.getLength()
// 像素间隔步长
let step = 50
// 将像素步长转实际地理距离步长
let StepLength = step * olMap.getView().getResolution()
// 箭头总数
let arrowNum = Math.floor(totalLength / StepLength)
const styles = [
// linestring
new Style({
stroke: new Stroke({
// color: 'rgb(164 164 162 / 88%)',
color: '#42b983',
width: 5,
}),
}),
];
const rotations = [];
const distances = [0];
geometry.forEachSegment(function (start, end) {
let dx = end[0] - start[0];
let dy = end[1] - start[1];
let rotation = Math.atan2(dy, dx);
distances.unshift(Math.sqrt(dx ** 2 + dy ** 2) + distances[0]);
rotations.push(rotation);
});
for (let i = 1; i < arrowNum; i++) {
let arrow_coor = geometry.getCoordinateAt(i * 1.0 / arrowNum)
const d = i * StepLength;
const grid = distances.findIndex((x) => x <= d);
styles.push(
new Style({
geometry: new Point(arrow_coor),
image: new Icon({
src,
opacity: 1,
anchor: [0.5, 0.5],
rotateWithView: true,
rotation: - rotations[distances.length - grid - 1],
scale: 0.8
})
})
)
}
return styles
}
/* const styleFunction = function (feature) {
const geometry = feature.getGeometry();
const styles = [
// linestring
new Style({
stroke: new Stroke({
color: 'rgb(164 164 162 / 88%)',
width: 5,
}),
}),
];
geometry.forEachSegment(function (start, end) {
const dx = end[0] - start[0];
const dy = end[1] - start[1];
const rotation = Math.atan2(dy, dx);
const coord = [start[0] + dx / 2, start[1] + dy / 2]
// arrows
styles.push(
new Style({
geometry: new Point(coord),
image: new Icon({
src,
anchor: [0.75, 0.5],
rotateWithView: true,
rotation: -rotation,
scale: 0.03
}),
})
);
});
return styles;
}; */
addLine(olMap, position, { businessType }, stylefunction)
// addLine(olMap, position, { businessType }, styleFunction)
}