前言
在地图中添加随鼠标位置更新的经纬度显示框是一个基本需求,本文分别使用函数组件和类实例实现这个功能,采用的技术栈是react和cesium,mapbox-gl同理可用。
封装组件
要实现这样一个功能,大多数人都会采用组件的形式实现,分为以下几步。
- 该组件接收Viewer对象。
- 给场景绑定鼠标移动事件,获取最鼠标所在位置的经纬度,Cesium内部提供了将屏幕坐标转移至大地经纬度的API,可查阅API文档。
- 获取的经纬度实时更新。
import React, { FC, useState, useEffect, useRef } from 'react'
// import * as Cesium from 'cesium'
import * as Cesium from 'cesium'
import styles from './index.module.less';
interface MousePostionComponentProps {
viewer: Cesium.Viewer | null
className?:React.HTMLAttributes<HTMLDivElement>
}
const MousePostion: FC<MousePostionComponentProps> = ({ viewer }) => {
const [longitude, setLongitude] = useState('0')
const [latitude, setLatitude] = useState('0')
useEffect(()=>{
viewer && freshCurMousePosition()
console.log('freshCurMousePosition')
},[viewer])
const freshCurMousePosition = () =>{
const handler = new Cesium.ScreenSpaceEventHandler(viewer!.scene.canvas)
handler.setInputAction((movement: any) => {
// 获取鼠标的坐标
getPosition(movement)
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}
const getPosition = (movement: any) => {
const cartesian = viewer!.camera.pickEllipsoid(
movement.endPosition,
viewer!.scene.globe.ellipsoid
);
if (cartesian) {
// 转换成经纬度
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const longitudeString = Cesium.Math.toDegrees(
cartographic.longitude
).toFixed(4);
const latitudeString = Cesium.Math.toDegrees(
cartographic.latitude
).toFixed(2);
setLongitude(longitudeString);
setLatitude(latitudeString);
}
}
return (
<div className={styles.mousePositionWrap}>
{ `经度:${longitude} 纬度:${latitude}`}
</div>
)
}
export default MousePostion
这个样式我也是从别的地方借鉴的。
.mousePositionWrap{
position: fixed;
bottom:0;
right:0;
width:200px;
height:40px;
background-color: rgba(0,0,0,0.5);
color: #fff;
font-size: 14px;
line-height: 40px;
text-align: center;
z-index: 100;
}
封装类
只针对这个功能的话其实并不需要这么麻烦,但是作为刚开始工作的小白,部门的前端sdk都是采用面向对象的方式开发并发布的,因此本着学习的目的使用这种方式重写了一下,代码如下。
import * as Cesium from "cesium";
class MousePosition {
_positionDiv = document.createElement("div");
_lat = 0.0;
_lng = 0.0;
_handler: Cesium.ScreenSpaceEventHandler;
viewer: Cesium.Viewer
constructor(viewer: Cesium.Viewer) {
this._positionDiv.style.cssText = `
position: fixed;
bottom:0;
right:0;
width:200px;
height:40px;
background-color: rgba(0,0,0,0.5);
color: #fff;
font-size: 14px;
line-height: 40px;
text-align: center;
z-index: 100;
`;
this.viewer = viewer
this._handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
viewer.container.append(this._positionDiv)
this._handler.setInputAction((movement: any) => {
// 获取鼠标的坐标
this.getPosition(movement)
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}
// 获取鼠标位置
getPosition(movement: any) {
const cartesian = this.viewer.camera.pickEllipsoid(
movement.endPosition,
this.viewer.scene.globe.ellipsoid
);
if (cartesian) {
// 转换成经纬度
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const longitude = Cesium.Math.toDegrees(
cartographic.longitude
).toFixed(4);
const latitude = Cesium.Math.toDegrees(
cartographic.latitude
).toFixed(2);
this._positionDiv.innerHTML = `经度:${longitude} 纬度:${latitude} `;
}
}
}
export default MousePosition;
可以看到思路和方法一是完全一样的,使用时把Viewer传给MousePosition的构造函数内部即可。
const MP = new MousePosition(view);
总结
- 经纬度显示组件:react组件
- 经纬度显示组件: 封装一个类