OpenLayers 5 一个固定视口中心位置的球面测距demo

代码功能:使用屏幕中心点作为终点,平移地图时动态修改起始点(天津)到屏幕中心点所在位置的连线,并实时计算两点间的球面距离(EPSG:3857坐标系),显示距离的文字沿连线做出标记。

主要思想是借用了openlayers的渲染机制,监听tileLayer的postcompose事件,在回调函数中使用vectorContext的API动态绘制图形。

代码中的ol.js和ol.css请自备,版本是5.3.0

<!DOCTYPE html>
<html>

<head>
	<title></title>
	<link rel="stylesheet" href="./include/ol.css" type="text/css" />
	<script src="./include/ol.js"></script>
</head>
<style>
</style>

<body>

	<div id="map" class="map"></div>
	<script>
		var raster = new ol.layer.Tile({
			source: new ol.source.OSM()
		});

		var view = new ol.View({
			center: ol.proj.fromLonLat([116.403571, 39.909193]),
			zoom: 7
		});

		//准备一个空的矢量图层存放表示天津的点要素
		var sourceVector = new ol.source.Vector()
		var vector = new ol.layer.Vector({
			source: sourceVector
		});

		var map = new ol.Map({
			layers: [raster, vector],
			target: 'map',
			view: view
		});
		//以上是常规操作

		//添加天津的点要素
		var tianjin = ol.proj.fromLonLat([117.247504, 39.365469]);
		var tjFeature = new ol.Feature(new ol.geom.Point(tianjin));
		sourceVector.addFeature(tjFeature);

		//下面缓存几个样式,在postcompose的回调函数里复用,提高内存利用率
		var pointStyle = new ol.style.Style({
			image: new ol.style.Circle({
				radius: 5,
				fill: new ol.style.Fill({
					color: 'red'
				})
			})
		})

		var lineStyle = new ol.style.Style({
			stroke: new ol.style.Stroke({
				color: 'green',
				width: 3
			}),
		})

		var textStyle = new ol.style.Style({
			text: new ol.style.Text({
				//文字标签的文本内容在回调函数里动态修改
				font: 'bold 15px "Open Sans", "Arial Unicode MS", "sans-serif"',
				placement: 'line',
				fill: new ol.style.Fill({
					color: 'black'
				}),
				stroke: new ol.style.Stroke({
					color: 'white'
				})
			})
		});

		//监听瓦片图层的postcompose事件,在其渲染结束之后进行绘制
		raster.on("postcompose", function (evt) {
			//拿到vectorContex对象,开始绘制
			var vCtx = evt.vectorContext;
			var center = view.getCenter();
			var centerFeature = new ol.Feature(new ol.geom.Point(center));
			var distance = Math.floor(ol.sphere.getDistance(ol.proj.toLonLat(center), [117.247504,
				39.365469
			]));
			var lineGeom = new ol.geom.LineString([center, tianjin]);
			var lineFeature = new ol.Feature(lineGeom);
			//动态修改文字样式的文本
			textStyle.getText().setText("球面距离:" + distance + " 米")
			//计算文字倾斜角度
			textStyle.getText().setRotation(Math.atan2(center[1] - tianjin[1], -center[0] + tianjin[0]))
			//绘制中心点、连线和文字标签
			vCtx.drawFeature(centerFeature, pointStyle);
			vCtx.drawFeature(lineFeature, lineStyle);
			vCtx.drawFeature(lineFeature, textStyle);
		})
	</script>
</body>

</html>

 

把上面的例子稍作改动,可以做成一个连续打点测量路径总长度的实例:

<!DOCTYPE html>
<html>

<head>
	<title></title>
	<link rel="stylesheet" href="./include/ol.css" type="text/css" />
	<script src="./include/ol.js"></script>
</head>
<style>
</style>

<body>
	<input type="button" id="addInput" value="添加路径点">
	<div id="map" class="map"></div>
	<script>
		var raster = new ol.layer.Tile({
			source: new ol.source.OSM()
		});

		var view = new ol.View({
			center: ol.proj.fromLonLat([116.403571, 39.909193]),
			zoom: 7
		});

		var sourceVector = new ol.source.Vector()
		var vector = new ol.layer.Vector({
			source: sourceVector
		});

		var map = new ol.Map({
			layers: [raster, vector],
			target: 'map',
			view: view
		});

		var tianjin = ol.proj.fromLonLat([117.247504, 39.365469]);
		var tjFeature = new ol.Feature(new ol.geom.Point(tianjin));
		sourceVector.addFeature(tjFeature);

		var pointStyle = new ol.style.Style({
			image: new ol.style.Circle({
				radius: 5,
				fill: new ol.style.Fill({
					color: 'red'
				})
			})
		})

		var lineStyle = new ol.style.Style({
			stroke: new ol.style.Stroke({
				color: 'green',
				width: 3
			}),
		})

		var textStyle = new ol.style.Style({
			text: new ol.style.Text({
				font: 'bold 15px "Open Sans", "Arial Unicode MS", "sans-serif"',
				placement: 'line',
				fill: new ol.style.Fill({
					color: 'black'
				}),
				stroke: new ol.style.Stroke({
					color: 'white'
				})
			})
		});

		var endPoint = tianjin;

		var addButton = document.getElementById('addInput');
		var routeLine = null;

		addButton.onclick = function () {
			var centerFeature = new ol.Feature(new ol.geom.Point(view.getCenter()));
			if (routeLine===null) {
				routeLine = new ol.Feature(new ol.geom.LineString([endPoint, view.getCenter()]));
				sourceVector.addFeature(routeLine);
			}else{
				routeLine.getGeometry().appendCoordinate( view.getCenter());
			}
			sourceVector.addFeature(centerFeature);
			endPoint = view.getCenter();
		};


		raster.on("postcompose", function (evt) {
			var vCtx = evt.vectorContext;
			var center = view.getCenter();
			var centerFeature = new ol.Feature(new ol.geom.Point(center));
			var distance = (routeLine===null?
			Math.floor(ol.sphere.getDistance(ol.proj.toLonLat(center), ol.proj.toLonLat(endPoint)))			
			:Math.floor(ol.sphere.getLength(routeLine.getGeometry())));
			var lineGeom = new ol.geom.LineString([center, endPoint]);
			var lineFeature = new ol.Feature(lineGeom);
			textStyle.getText().setText("球面距离:" + distance + " 米")
			textStyle.getText().setRotation(Math.atan2(center[1] - endPoint[1], -center[0] + endPoint[0]))
			vCtx.drawFeature(centerFeature, pointStyle);
			vCtx.drawFeature(lineFeature, lineStyle);
			vCtx.drawFeature(lineFeature, textStyle);
		})
	</script>
</body>

</html>

效果图

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

战斗中的老胡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值