本人openlayer为6.x,可能有些api在新的版本已经过时,需要根据版本进行调整
顺便贴上6.x的api地址:https://openlayers.org/en/v6.15.1/apidoc/
1.创建map对象,通过new Map()创建,如:
//创建地图
function _initMap(map,mapUrl = url,mapCenter = center,type = false,){const client = new Map({target: map, // 对应地图容器view: new View(viewConfig),controls: defaultControls({zoom: false, // 隐藏放大/缩小控件attribution: false, // 隐藏超图版权控件}),});
//此处极为view的一些常用配置项 mapCenter为地图中心坐标 project为坐标系 如EPSG:4326
// zoom为默认的缩放级别
//viewConfig = { center: mapCenter, zoom, projection, minZoom, maxZoom };// 添加自定义图层
// 此处soure可以为其他的数据源,本项目采用超图的数据源故特此用法
// 其他如XYZ,可以替换成new XYZ({url: ''}) 根据个人需要进行调整const layer = new TileLayer({source: new TileSuperMapRest({ url: mapUrl, wrapX }),projection: type ? null : projection,id: "TileSuperMapRest",});client.addLayer(layer); // 添加图层到地图
}
其中view主要是视图层面的东西,比如控制视图的center,缩放最大最小等控制
2.添加图层到地图中以及加入markerd到地图中
//其中VectorSource为ol/source/Vector
//VectorLayer为ol/layer/Vector
this.markerLayer = new VectorLayer({// 标记点图层source: new VectorSource(),zIndex: 997,});
//创建完layer后即可以调用此函数在地图中加入图标
function createdPoint({ layer, center, option, data = {}, type = 'point' }) {const config = {image: new Icon({anchor: [0.5, 0.5], // 锚点opacity: 1,scale: 0.4,cursor: 'pointer'})}const point = new Feature({type,data,id: data.id,geometry: new Point(center)})// 给点位设置idif (data.id) {point.setId(data.id)}point.setStyle(new Style(config))layer.getSource().addFeature(point)
}
3.地图中创建线条以及给线条绘制方向(线条也是一种feature)
//创建基本的线条即可通过此种方式创建
function createdLine({ layer, pointsData, option, type = 'line' }) {option = Object.assign({}, defaultLineOption, option)// 构造一个线条的Featureconst line = new Feature({type,geometry: new LineString(pointsData)})// 设置线条样式line.setStyle(new Style({stroke: new Stroke(option)}))// 将线条添加到数据源中layer.getSource().addFeature(line)
}
很多时候需要创建复杂一点的线条比如给线条填充箭头方向:
// 创建带箭头的线条
function _createdLineWithArrow(coordDrawLineArr, layer, defaultIndex, data) {//coordDrawLineArr为线条做坐标数组 必须是一个二维数组,如:[[经度,纬度],[经度,维度],...]这样const lineFeature = new Feature({type: "line",data,id: data.id,geometry: new LineString(coordDrawLineArr),});//此处可以通过一个闭包将一些外部参数传入 如:defaultIndexlineFeature.setStyle((feature, res) =>_lineArrowStyles(feature, res, defaultIndex),);layer.getSource().addFeature(lineFeature);if (data.id) {layer.set("data_id", data.id);lineFeature.setId(data.id);}
}
// 绘制箭头样式
function _lineArrowStyles(feature, res, defaultColorIndex) {const geometry = feature.getGeometry();const styles = [new Style({stroke: new Stroke({color: isNaN(defaultColorIndex)? defaultColorIndex: outerColors[defaultColorIndex],width: 8,}),}),new Style({stroke: new Stroke({color: isNaN(defaultColorIndex)? defaultColorIndex: innerColors[defaultColorIndex],width: 4,}),}),];// 如果几何体不是线条,这返回默认样式if (!(geometry instanceof LineString)) return styles;// 得到线条长度const length = geometry.getLength();// 内部箭头间隔距离(像素)const step = 50;// 将间隔像素距离转换成地图的真实距离// res 是 OL 自动传入的地图比例系数const geoStep = step * res;// console.log("KKK", res);// 得到一共需要绘制多少个 箭头const arrowNum = Math.floor(length / geoStep);const rotations = [];const distances = [0];// 分割线条,将折线根据坐标进行分割,并遍历// 回调函数将传入开始坐标和结束坐标// 利用开始距离和结束距离,得到每段线条的距离和方向信息geometry.forEachSegment(function (start, end) {const dx = end[0] - start[0];const dy = end[1] - start[1];const 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) {const arrowCoord = geometry.getCoordinateAt(i / arrowNum);const d = i * geoStep;const grid = distances.findIndex((x) => x <= d);styles.push(new Style({geometry: new Point(arrowCoord),image: new Icon({src: require("@/assets/images/arrow-right-1.png"),opacity: 1,anchor: [0.5, 0.5],rotateWithView: true,// 读取 rotations 中计算存放的方向信息rotation: -rotations[distances.length - grid - 1],scale: 0.16,}),}),);}return styles;
}
4. 绘制点位聚合功能,即图中坐标点位太多将距离很近的点位聚合成一个
// 这里聚合图层 判定逻辑为,当缩放到某个级别后,feature下面仅有一个子feature时,即不进行缩放
function _createClusterPoint(map, arr, clusterLayer, cluster) {// 聚合图层数据源if (!cluster) {const clusterSource = new VectorSource();cluster = new Cluster({source: clusterSource,distance: 100,});}for (let i = 0; i < arr.length; i++) {const item = arr[i];const feature = _createdFeature(item.position, null, { ...item });// clusterSource.addFeature(feature);cluster.getSource().addFeature(feature);}// 聚合图层if (!clusterLayer) {clusterLayer = new Vector({source: clusterSourceForLayer,style: _setClusterStyle,});map.addLayer(clusterLayer);} else {clusterLayer.setStyle(_setClusterStyle);}// clusterSource.refresh();
}function _setClusterStyle(feature, resolution) {const size = feature.get("features").length;const data = feature.get("features")?.[0]?.values_?.data || {};if (size === 1) {let option = null;if (data.isDrawText) {option = {image: {scale: "0.2",src: getDeviceIcon(data),},text: {text: data.name,font: "bold 16px 黑体", // 文字样式textAlign: "center", // 文字对其方式,居中fill: new Fill({color: "#fff", // 设置文字颜色}),},};} else {option = _createConfigOption(data);}const config = _createFeatureConfig(option);return new Style(config);} else {return new Style({image: new Icon({scale: "0.2",src: getDeviceIcon(data),}),text: new Text({offsetY: -25,text: size.toString(),font: "bold 16px 黑体", // 文字样式textAlign: "center", // 文字对其方式,居中fill: new Fill({color: "#fff",}),}),});}
}
调用处代码
this.cluster = new Cluster({source: new VectorSource(),distance: 100,});this.clusterLayer = new VectorLayer({source: this.cluster,zIndex: 996,style: _setClusterStyle,});
//mapClient为地图Map对象
this.mapClient.addLayer(this.clusterLayer);
5.获取指定半径(米)指定坐标周围的要素features,如:
// 获取米为单位的半径 map为地图map对象 radius为需要指定的半径
const getRadius = (map, radius) => {let metersPerUnit = map.getView().getProjection().getMetersPerUnit();let circleRadius = radius / metersPerUnit;return circleRadius;
};
/*** 获取指定范围内的feature*/
export function _getFeaturesInRadius(map,vectorLayer,coordinates,radius,filterCondition,
) {radius = getRadius(map, radius);const polygon = fromCircle(new GeomCircle(coordinates, radius));const extent = polygon.getExtent();// 查询vectorLayer以找到矩形区域内的所有featuresconst features = vectorLayer.getSource().getFeaturesInExtent(extent);// 过滤掉原始feature(如果需要)return filterCondition ? features.filter(filterCondition) : features;
}