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>

效果图
在这里插入图片描述