OpenLayers 5 一個(gè)固定視口中心位置的球面測距demo

代碼功能:使用屏幕中心點(diǎn)作為終點(diǎn),平移地圖時(shí)動(dòng)態(tài)修改起始點(diǎn)(天津)到屏幕中心點(diǎn)所在位置的連線,并實(shí)時(shí)計(jì)算兩點(diǎn)間的球面距離(EPSG:3857坐標(biāo)系),顯示距離的文字沿連線做出標(biāo)記。

主要思想是借用了openlayers的渲染機(jī)制,監(jiān)聽tileLayer的postcompose事件,在回調(diào)函數(shù)中使用vectorContext的API動(dòng)態(tài)繪制圖形。

代碼中的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
    		});
     
    		//準(zhǔn)備一個(gè)空的矢量圖層存放表示天津的點(diǎn)要素
    		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
    		});
    		//以上是常規(guī)操作
     
    		//添加天津的點(diǎn)要素
    		var tianjin = ol.proj.fromLonLat([117.247504, 39.365469]);
    		var tjFeature = new ol.Feature(new ol.geom.Point(tianjin));
    		sourceVector.addFeature(tjFeature);
     
    		//下面緩存幾個(gè)樣式,在postcompose的回調(diào)函數(shù)里復(fù)用,提高內(nèi)存利用率
    		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({
    				//文字標(biāo)簽的文本內(nèi)容在回調(diào)函數(shù)里動(dòng)態(tài)修改
    				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'
    				})
    			})
    		});
     
    		//監(jiān)聽瓦片圖層的postcompose事件,在其渲染結(jié)束之后進(jìn)行繪制
    		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);
    			//動(dòng)態(tài)修改文字樣式的文本
    			textStyle.getText().setText("球面距離:" + distance + " 米")
    			//計(jì)算文字傾斜角度
    			textStyle.getText().setRotation(Math.atan2(center[1] - tianjin[1], -center[0] + tianjin[0]))
    			//繪制中心點(diǎn)、連線和文字標(biāo)簽
    			vCtx.drawFeature(centerFeature, pointStyle);
    			vCtx.drawFeature(lineFeature, lineStyle);
    			vCtx.drawFeature(lineFeature, textStyle);
    		})
    	</script>
    </body>
     
    </html>

在這里插入圖片描述














把上面的例子稍作改動(dòng),可以做成一個(gè)連續(xù)打點(diǎn)測量路徑總長度的實(shí)例:

    <!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="添加路徑點(diǎn)">
    	<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>

效果圖
在這里插入圖片描述