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