import DomUtil from './common/doms.js'
import '../Assets/styles/StatusBar.css';
/**
* 状态栏
*/
class StatusBar {
/**
* 状态栏工具类
* @param {Viewer} viewer - 三维场景
*/
constructor(viewer) {
if (!viewer) throw new Error('viewer is required!');
this._viewer = viewer;
this._show = false; //初始化显示状态
this._handler;
this._posX;
this._posY;
this._posZ;
this._cameraHeight;
this._pitch;
this._heading;
this._scale;
this.initListener()
}
/**
* 状态栏参数
* @readonly
*/
get params() {
return {
posX: this._posX, //经度
posY: this._posY, //维度
posZ: this._posZ, //模型高度
cameraHeight: this._cameraHeight, //相机视角高度
pitch: this._pitch, //俯仰角
heading: this._heading, //方向
scale: this._scale //比例尺
}
}
get statusDom() {
let innerHtml = `
比例尺:
${this._scale}
空间信息
刷帧率:|
`
return innerHtml
}
/**
* 控制显示Boolean常量
* @constant
*/
get show() {
return this._show
}
set show(bool) {
bool ? this.createStatusBar() : this.removeStatusBar()
this._show = bool
}
initListener() {
const $this = this
const scene = this._viewer.scene
this._scaleListener = function() {
let width = scene.canvas.clientWidth
let height = scene.canvas.clientHeight
let left = scene.camera.getPickRay(
new Cesium.Cartesian2((width / 2) | 0, height - 1)
)
let right = scene.camera.getPickRay(
new Cesium.Cartesian2((1 + width / 2) | 0, height - 1)
)
let globe = scene.globe
let leftPosition = globe.pick(left, scene)
let rightPosition = globe.pick(right, scene)
if (leftPosition && rightPosition) {
let geodesic = new Cesium.EllipsoidGeodesic()
let leftCartographic = globe.ellipsoid.cartesianToCartographic(leftPosition)
let rightCartographic = globe.ellipsoid.cartesianToCartographic(rightPosition)
geodesic.setEndPoints(leftCartographic, rightCartographic)
let distance = geodesic.surfaceDistance
let curScaleNum = $this.closest(distance / 10)
if (curScaleNum < 1) {
$this._scale = curScaleNum * 1000 + 'm'
} else {
$this._scale = curScaleNum + 'km'
}
}
document.getElementsByClassName("scale-border")[0].innerText = $this._scale;
if (document.getElementsByClassName("cesium-performanceDisplay-ms").length > 0) {
document.getElementById("status_ms").innerText = document.getElementsByClassName("cesium-performanceDisplay-ms")[0].innerText;
}
if (document.getElementsByClassName("cesium-performanceDisplay-fps").length > 0) {
document.getElementById("status_fps").innerText = document.getElementsByClassName("cesium-performanceDisplay-fps")[0].innerText;
}
}
}
createStatusBar() {
const _delegate = this._viewer
this.initHandler(_delegate)
this.initScale(_delegate, true)
this._domContainer = DomUtil.create(
'div',
'lk-status-bar',
document.getElementById(this._viewer._container.id)
)
this._domContainer.innerHTML = this.statusDom;
// var canvas = this._viewer.canvas; // 获取画布
// this._domContainer.style.width = canvas.width + "px";
// console.log('画布', canvas.width)
}
removeStatusBar() {
this.initScale(this._viewer, false)
if (this._handler) {
this._handler.destroy()
}
if (this._domContainer) {
DomUtil.remove(this._domContainer)
}
}
initHandler(viewer) {
const $this = this
this._handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
const mouseOverHandler = function(movement) {
/* 识别屏幕位置 */
let loc = $this._getScreenClickPositionAndHeight(movement.endPosition);
if (!Cesium.defined(loc)) return;
if (!loc.lng) return;
$this._posX = loc.lng.toFixed(8);
$this._posY = loc.lat.toFixed(8);
$this._posZ = loc.height.toFixed(2);
// const cameraH = viewer.camera.positionCartographic.height
// $this._cameraHeight =
// cameraH < 1000 ?
// cameraH.toFixed(2) + 'm' :
// (cameraH / 1000).toFixed(2) + 'km';
// $this._pitch = Number(viewer.scene.camera.pitch).toFixed(2);
// $this._heading = Number(viewer.scene.camera.heading).toFixed(2);
document.getElementById("status_spaceInfo").innerHTML = `
经度:${$this._posX}
纬度:${$this._posY}
高度:${$this._posZ}
`;
}
this._handler.setInputAction(
mouseOverHandler,
Cesium.ScreenSpaceEventType.MOUSE_MOVE
)
}
initScale(viewer, bool) {
const scene = viewer.scene
bool
?
scene.postRender.addEventListener(this._scaleListener) :
scene.postRender.removeEventListener(this._scaleListener)
}
closest(num) {
const scaleList = [
0.001,
0.002,
0.003,
0.005,
0.01,
0.015,
0.02,
0.025,
0.03,
0.035,
0.04,
0.045,
0.05,
0.06,
0.07,
0.08,
0.09,
0.1,
0.12,
0.15,
0.2,
0.25,
0.3,
0.5,
1,
2,
3,
5,
10,
15,
20,
25,
30,
35,
40,
45,
50,
60,
70,
80,
90,
100,
120,
150,
200,
250,
300,
500,
1000,
2000,
5000,
10000,
100000,
500000,
1000000
]
let ret = scaleList[0]
let distance = Math.abs(ret - num)
for (let i = 1; i < scaleList.length; i++) {
let newDistance = Math.abs(scaleList[i] - num)
if (newDistance < distance) {
distance = newDistance
ret = scaleList[i]
}
}
return ret
}
/**
* 根据地形或实景或模型检测当前屏幕位置的经纬度及高度
* @ignore 生成方法时不对外公开
* @param {JSON} screenPoint 屏幕坐标
* @param {Number} screenPoint.x 屏幕坐标x
* @param {Number} screenPoint.y 屏幕坐标y
* @return {JSON} 位置信息{lng,lat,height}
*/
_getScreenClickPositionAndHeight(screenPoint) {
var lng = undefined,
lat = undefined,
height = undefined;
/* 从相机位置到 windowPosition 处的像素创建射线在世界坐标系中 */
var ray = this._viewer.scene.camera.getPickRay(screenPoint);
/* 找到射线与渲染的地球表面之间的交点 */
var position = this._viewer.scene.globe.pick(ray, this._viewer.scene);
if (position) {
/* 获取地理位置的制图表达 */
var cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position);
cartographic = Cesium.Cartographic.fromCartesian(position);
/* 查询屏幕位置的要素 */
var feature = this._viewer.scene.pick(screenPoint);
if (feature === undefined && Cesium.defined(cartographic)) {
lng = this._arcToDegree(cartographic.longitude);
lat = this._arcToDegree(cartographic.latitude);
height = cartographic.height;
} else {
var cartesian = this._viewer.scene.pickPosition(screenPoint);
if (Cesium.defined(cartesian)) {
var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
if (Cesium.defined(cartographic)) {
lng = this._arcToDegree(cartographic.longitude);
lat = this._arcToDegree(cartographic.latitude);
height = cartographic.height;
}
}
}
}
/* 返回结果 */
return {
lng: lng,
lat: lat,
height: height,
}
}
/**
* 弧度转度
* @ignore 生成方法时不对外公开
* @param {Number} arc 弧度
* @return {Number} 角度
*/
_arcToDegree(arc) {
return arc / Math.PI * 180;
}
}
export default StatusBar