Openlayers+Vue的集成和使用,持续更新...

本人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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值