本人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)
})
// 给点位设置id
if (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)
// 构造一个线条的Feature
const 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),
});
//此处可以通过一个闭包将一些外部参数传入 如:defaultIndex
lineFeature.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以找到矩形区域内的所有features
const features = vectorLayer.getSource().getFeaturesInExtent(extent);
// 过滤掉原始feature(如果需要)
return filterCondition ? features.filter(filterCondition) : features;
}