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>
效果圖