cesium实现geojson数据鼠标悬停高亮效果
项目所需,要在cesium上加载geojson数据后实现hover效果,但没找到cesium原生实现的方法,遂用笨办法去模拟一下效果,若大神们有其他方法万望指出。
hover效果可理解为判断鼠标是否移动到目标区域内(不考虑鼠标正好在区域边的情况,目标区域可以看作多边形),若在区域内则区域变色高亮。所以模拟实现的方法可以划归为判断点是否在多边形内部,并进行相应的高亮效果。
具体实现
判断点是否在多边形内部的方法可通过射线法实现,也可利用turf.js中的booleanPointInPolygon
实现。本文利用射线法的方式实现。射线法是通过点引出射线与多边形交点个数判断是否,若为奇数则在多边形内部,为偶数则在多边形外部。
点坐标的数据通过cesium viewer.screenSpaceEventHandler.setInputAction
实时监听实现。
多边形高亮效果则可通过对加载的材质进行赋值实现, 例如:
entities[0].polygon.material = new
Cesium.ColorMaterialProperty(Cesium.Color.fromCssColorString(’#7AFDE0’).withAlpha(0.5));
viewer.screenSpaceEventHandler.setInputAction(function(movement:any) {
//获取鼠标移动后停留位置坐标
let ifcartesian = viewer.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid);
if (ifcartesian) {
let ball = Cesium.Ellipsoid.WGS84.cartesianToCartographic(ifcartesian);
Y_String = Cesium.Math.toDegrees(ball.latitude);
X_String = Cesium.Math.toDegrees(ball.longitude);
let high = viewer.scene.globe.getHeight(ball)
pointPosition = Cesium.Cartesian3.fromDegrees(X_String,Y_String,high);
}
let endPosition = [pointPosition.x,pointPosition.y];
//根据是否在多边形内部,在哪个多边形内部进行材质上色
if(isInPolygon(endPosition,polygon_point[0])){
//高亮效果
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
});
//检测点是否在多边形内部,返回T/F
function isInPolygon(checkPoint:any, polygonPoints:any) {
var counter = 0;
var i;
var xinters;
var p1, p2;
var pointCount = polygonPoints.length;
p1 = polygonPoints[0];
for (i = 1; i <= pointCount; i++) {
p2 = polygonPoints[i % pointCount];
if (
checkPoint[0] > Math.min(p1[0], p2[0]) &&
checkPoint[0] <= Math.max(p1[0], p2[0])
) {
if (checkPoint[1] <= Math.max(p1[1], p2[1])) {
if (p1[0] != p2[0]) {
xinters =
(checkPoint[0] - p1[0]) *
(p2[1] - p1[1]) /
(p2[0] - p1[0]) +
p1[1];
if (p1[1] == p2[1] || checkPoint[1] <= xinters) {
counter++;
}
}
}
}
p1 = p2;
}
if (counter % 2 == 0) {
return false;
} else {
return true;
}
};
该方法存在的弊端是会占用较多的系统资源,并且在响应上会有一定的延迟。若有更好的方法模拟hover效果希望指正。