openlayers文字随线的方向

该代码示例展示了如何在不依赖ol-ext库的情况下,在OpenLayers中创建带有方向箭头的线,并动态计算箭头的旋转角度。代码包括了对MultiLineString和LineString类型的处理,以及文字标签的添加和旋转。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在不使用ol-ext时需要自己计算方向

效果:

 核心代码:

function styleArrow(start, end, title) {
			var arrowLonLat = [(end[0] + start[0]) / 2, (end[1] + start[1]) / 2];
			var dx = end[0] - start[0];
			var dy = end[1] - start[1];
			var rotation = Math.atan2(dy, dx);
			var rotationText = 0
			if(0<rotation && rotation<Math.PI/2 ){
				rotationText = -rotation
			}
			if(Math.PI/2<rotation && rotation<Math.PI){
				rotationText = Math.PI-rotation
			}
			if(-Math.PI/2<rotation && rotation<0 ){
				rotationText = -rotation
			}
			if(-Math.PI<rotation && rotation<-Math.PI/2 ){
				rotationText = Math.PI-rotation
			}
			// arrows
			return new ol.style.Style({
				geometry: new ol.geom.Point(arrowLonLat),
				image: new ol.style.Icon({
					src: './arrow.gif',
					anchor: [0.75, 0.5],
					rotateWithView: true,
					rotation: -rotation,
				}),
				text: new ol.style.Text({
					font: '15px Microsoft YaHei',
					text: title,
					rotation: rotationText,
					textBaseline: 'bottom',
					fill: new ol.style.Fill({
						color: '#369'
					}),
					stroke: new ol.style.Stroke({
						color: "#fff",
						width: 3
					}),
				})
			})
		}

完整代码:

<!DOCTYPE html>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>线上绘制文字及箭头</title>
		<!-- https://openlayers.org/en/v6.15.1/examples/line-arrows.html -->
		<!-- 
		<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/css/ol.css" type="text/css">
		<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script>
		 -->
		<link rel="stylesheet" href="./js/ol.css" />
		<script type="text/javascript" src="./js/ol.js"></script>
		<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

		<style type="text/css">
			html,
			body,
			#map {
				border: 0px;
				margin: 0px;
				padding: 0px;
				width: 100%;
				height: 100%;
				font-size: 13px;
			}
		</style>

	</head>
	<body>
		<div id="map"></div>
	</body>
	<script type="text/javascript">
		var wktformat = new ol.format.WKT();
		var tileLayer = new ol.layer.Tile({
			source: new ol.source.XYZ({
				url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}'
			})
		});
		var vectorSource = new ol.source.Vector({
			features: []
		})

		function vectorStyle(feature) {
			var styles = [
				new ol.style.Style({
					fill: new ol.style.Fill({
						color: 'rgba(255, 0, 0, 0.2)'
					}),
					stroke: new ol.style.Stroke({
						color: '#ffcc33',
						width: 1
					}),
					image: new ol.style.Circle({
						radius: 7,
						fill: new ol.style.Fill({
							color: '#ffcc33'
						})
					}),
					// text: new ol.style.Text({
					// 	font: '13px Microsoft YaHei',
					// 	text: feature.get('name'),
					// 	fill: new ol.style.Fill({
					// 		color: '#666'
					// 	})
					// })
				})
			]
			
			var geometry = feature.getGeometry();
			console.log(geometry.getType())
			
			if (geometry.getType() == "MultiLineString") {
				geometry.getLineString().forEachSegment((start, end) => {
					// arrows
					styles.push(styleArrow(start, end, feature.get('name')))
				});
			} else if (geometry.getType() == "LineString") {
				var start = geometry.getCoordinates()[0]
				var end = geometry.getCoordinates()[1]
				// arrows
				styles.push(styleArrow(start, end, feature.get('name')))
			}
			
			return styles
		}
		function styleArrow(start, end, title) {
			var arrowLonLat = [(end[0] + start[0]) / 2, (end[1] + start[1]) / 2];
			var dx = end[0] - start[0];
			var dy = end[1] - start[1];
			var rotation = Math.atan2(dy, dx);
			var rotationText = 0
			if(0<rotation && rotation<Math.PI/2 ){
				rotationText = -rotation
			}
			if(Math.PI/2<rotation && rotation<Math.PI){
				rotationText = Math.PI-rotation
			}
			if(-Math.PI/2<rotation && rotation<0 ){
				rotationText = -rotation
			}
			if(-Math.PI<rotation && rotation<-Math.PI/2 ){
				rotationText = Math.PI-rotation
			}
			// arrows
			return new ol.style.Style({
				geometry: new ol.geom.Point(arrowLonLat),
				image: new ol.style.Icon({
					src: './arrow.gif',
					anchor: [0.75, 0.5],
					rotateWithView: true,
					rotation: -rotation,
				}),
				text: new ol.style.Text({
					font: '15px Microsoft YaHei',
					text: title,
					rotation: rotationText,
					textBaseline: 'bottom',
					fill: new ol.style.Fill({
						color: '#369'
					}),
					stroke: new ol.style.Stroke({
						color: "#fff",
						width: 3
					}),
				})
			})
		}
		
		var vectorLayer = new ol.layer.Vector({
			source: vectorSource,
			style: vectorStyle
		});
		var map = new ol.Map({
			controls: [],
			target: 'map',
			layers: [tileLayer, vectorLayer],
			view: new ol.View({
				center: transform([103.584297498027, 36.119086450265]),
				zoom: 4,
			})
		});
		// map.getView().fit(features[2].getGeometry());

		function transform(pois) {
			return ol.proj.transform(pois, 'EPSG:4326', 'EPSG:3857')
		}


		// 线
		var lineCoord = [
			[109.6399637062942, 36.10488480328604],
			[119.4837137062942, 42.51651033049882]
		];
		var line = new ol.geom.LineString(lineCoord);
		line.transform('EPSG:4326', 'EPSG:3857');
		// var f2 = new ol.Feature(line);
		var f2 = new ol.Feature({
			geometry: line,
			id: 2,
			name: '线1-右上'
		});
		vectorSource.addFeature(f2);
		console.log(wktformat.writeGeometry(line))
		console.log(wktformat.writeFeature(f2))
		console.log(line.getLength())

		var lineCoord2 = [
			[107.5305887062942, 34.55617638204109],
			[120.25715013341059, 27.888441634487776]
		];
		var line2 = new ol.geom.LineString(lineCoord2);
		line2.transform('EPSG:4326', 'EPSG:3857');
		// var f2 = new ol.Feature(line);
		var f22 = new ol.Feature({
			geometry: line2,
			id: 2,
			name: '线2-右下'
		});
		vectorSource.addFeature(f22);
		
		// 多线
		var multilineCoord = [
			[
				[103.45246156052698, 34.960539700465915],
				[98.81183763341058, 27.826278348695965]
			]
		];
		var multiline = new ol.geom.MultiLineString(multilineCoord);
		multiline.transform('EPSG:4326', 'EPSG:3857');
		// var f2 = new ol.Feature(line);
		var f23 = new ol.Feature({
			geometry: multiline,
			id: 2,
			name: '多线1-左下'
		});
		vectorSource.addFeature(f23);
		
		var multilineCoord2 = [
			[
				[97.75715013341059, 37.79053483981271],
				[88.1243397791778, 43.59537248307916]
			]
		];
		var multiline2 = new ol.geom.MultiLineString(multilineCoord2);
		multiline2.transform('EPSG:4326', 'EPSG:3857');
		// var f2 = new ol.Feature(line);
		var f24 = new ol.Feature({
			geometry: multiline2,
			id: 2,
			name: '多线2-左上'
		});
		vectorSource.addFeature(f24);
		

		map.on('click', (evt) => {
			console.log(ol.proj.transform(evt.coordinate, 'EPSG:3857', 'EPSG:4326'));
			vectorLayer.getFeatures(evt.pixel).then((features) => {
				var feature = features.length ? features[0] : undefined;
				if (feature) {
					console.log(feature.getProperties())
				}
			});
		});
	</script>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值