import Dialog from '../../../Element/Dialog' import EventBinding from '../../../Element/Dialog/eventBinding' import { html, css } from './_element' import Base from '../../index' import MouseEvent from '../../../../Event/index' import { syncData } from '../../../../Global/MultiViewportMode' import MouseTip from '../../../../MouseTip' import { setSplitDirection } from '../../../../Global/SplitScreen' class GroundText extends Base { /** * @constructor * @param sdk * @description 贴地文字 * @param options {object} 属性 * @param options.show=true {boolean} 显示/隐藏 * @param options.text {string} 文字 * @param options.angle=0 {number} 旋转角度 * @param options.scale=1 {number} 比例 * @param {object} options.position 经纬度和高度{lon,lat,alt} * @param {Array.} options.positions 矩形坐标数组 [最西端的经度,最南端的纬度,最东经度,最北纬度] * @param _Dialog {object} 弹框事件 * @param _Dialog.confirmCallBack {function} 弹框确认时的回调 * */ constructor(sdk, options = {}, _Dialog = {}) { super(sdk, options) this.options.text = options.text || '未命名对象' this.options.name = this.options.text this.options.show = options.show || options.show === false ? options.show : true this.options.angle = options.angle || 0 this.options.scale = options.scale || options.scale === 0 ? options.scale : 1 this.options.fontSize = options.fontSize || 20 this.options.duration = options.duration || options.duration === 0 ? options.duration : 50000 this.options.speed = options.speed || options.speed === 0 ? options.speed : 1 this.options.color = options.color || '#FFC107' this.options.position = options.position this.entity this._positionEditing = false this.Dialog = _Dialog this._EventBinding = new EventBinding() this._elms = {} this.previous = { position: { ...this.options.position } } this.event = new MouseEvent(this.sdk) this.sdk.addIncetance(this.options.id, this) this.create() } get text() { return this.options.text } set text(v) { this.options.text = v if (this.entity) { let canvas = this.getcanvas() let ratio = canvas.height / canvas.width this.entity.rectangle.material = new Cesium.CustomMaterialSource({ image: canvas.toDataURL('image/png'), color: this.options.color, repeat: new Cesium.Cartesian2(1.0, 1.0), duration: this.options.duration / this.options.speed, fltr: false }) this.entity.rectangle.coordinates = new Cesium.CallbackProperty(() => { let gap = Math.abs(Math.cos((Math.PI / 180) * this.options.position.lat)) * (0.0001 * this.options.scale) let fromDegreesArray = [ this.options.position.lng - (0.0001 * this.options.scale) / ratio, this.options.position.lat - gap, this.options.position.lng + (0.0001 * this.options.scale) / ratio, this.options.position.lat + gap ] return Cesium.Rectangle.fromDegrees(...fromDegreesArray) }, false) } this._elms.text && this._elms.text.forEach(item => { item.value = v }) } get angle() { return this.options.angle } set angle(v) { this.options.angle = v this._elms.angle && this._elms.angle.forEach(item => { item.value = v }) } get scale() { return this.options.scale } set scale(v) { this.options.scale = v this._elms.scale && this._elms.scale.forEach(item => { item.value = v }) } get duration() { return this.options.duration } set duration(v) { this.options.duration = v let canvas = this.getcanvas() this.entity.rectangle.material = new Cesium.CustomMaterialSource({ image: canvas.toDataURL('image/png'), color: this.options.color, repeat: new Cesium.Cartesian2(1.0, 1.0), duration: this.options.duration / this.options.speed, fltr: false }) this._elms.duration && this._elms.duration.forEach(item => { item.value = v }) } get speed() { return this.options.speed } set speed(v) { this.options.speed = v let canvas = this.getcanvas() this.entity.rectangle.material = new Cesium.CustomMaterialSource({ image: canvas.toDataURL('image/png'), color: this.options.color, repeat: new Cesium.Cartesian2(1.0, 1.0), duration: this.options.duration / this.options.speed, fltr: false }) this._elms.speed && this._elms.speed.forEach(item => { item.value = v }) } get color() { return this.options.color } set color(v) { this.options.color = v let canvas = this.getcanvas() this.entity.rectangle.material = new Cesium.CustomMaterialSource({ image: canvas.toDataURL('image/png'), color: this.options.color, repeat: new Cesium.Cartesian2(1.0, 1.0), duration: this.options.duration / this.options.speed, fltr: false }) if (this._elms.color) { this._elms.color.forEach((item, i) => { let colorPicker = new YJColorPicker({ el: item.el, size: 'mini', //颜色box类型 alpha: true, //是否开启透明度 defaultColor: v, disabled: false, //是否禁止打开颜色选择器 openPickerAni: 'opacity', //打开颜色选择器动画 sure: c => { this.color = c }, //点击确认按钮事件回调 clear: () => { this.color = 'rgba(255,255,255,1)' } //点击清空按钮事件回调 }) this._elms.color[i] = colorPicker }) } } create() { // let gap = Math.abs(Math.cos(Math.PI/180 * this.options.position.lat)) * (0.0001*this.options.scale) // let fromDegreesArray = [ // this.options.position.lng - 0.05, this.options.position.lat - 0.05, // this.options.position.lng + 0.05, this.options.position.lat - 0.05, // this.options.position.lng + 0.05, this.options.position.lat + 0.05, // this.options.position.lng - 0.05, this.options.position.lat + 0.05, // ] let canvas = this.getcanvas() let ratio = canvas.height / canvas.width let height = ((this.options.positions[2] - this.options.positions[0])/2) * ratio this.options.positions[1] = this.options.positions[3] - height this.entity = this.sdk.viewer.entities.add({ id: this.options.id, show: this.options.show, rectangle: { coordinates: new Cesium.CallbackProperty(() => { let gap = Math.abs(Math.cos((Math.PI / 180) * this.options.position.lat)) * (0.0001 * this.options.scale) let fromDegreesArray = [ this.options.position.lng - (0.0001 * this.options.scale) / ratio, this.options.position.lat - gap, // this.options.position.lng + 0.05, this.options.position.lat - 0.05, this.options.position.lng + (0.0001 * this.options.scale) / ratio, this.options.position.lat + gap // this.options.position.lng - 0.05, this.options.position.lat + 0.05, ] return Cesium.Rectangle.fromDegrees(...this.options.positions) }, false), outline: true, outlineColor: Cesium.Color.RED, outlineWidth: 10, rotation: new Cesium.CallbackProperty(() => { return Cesium.Math.toRadians(this.options.angle) }, false), stRotation: new Cesium.CallbackProperty(() => { return Cesium.Math.toRadians(this.options.angle) }, false) } }) if (this.sdk.viewer._element.className === 'cesium-viewer 2d') { this.entity.rectangle.height = 1000000 } syncData(this.sdk, this.options.id) if(this.options.show) { setSplitDirection(0, this.options.id) } } // 编辑框 async edit(state) { let _this = this this.originalOptions = this.deepCopyObj(this.options) this._element_style = null if (this._DialogObject && this._DialogObject.close) { this._DialogObject.close() this._DialogObject = null } if (state) { this._element_style = document.createElement('style') this._element_style.type = 'text/css' this._element_style.setAttribute('data-name', 'YJ_style_dialog') this._element_style.innerHTML = css() this._DialogObject = await new Dialog( this.sdk, this.originalOptions, { title: '编辑属性', left: '180px', top: '100px', confirmCallBack: options => { this.text = this.text.trim() if (!this.text) { this.text = '未命名对象' } this.originalOptions = this.deepCopyObj(this.options) this._DialogObject.close() this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(this.originalOptions) syncData(this.sdk, this.options.id) }, resetCallBack: () => { this.reset() this.Dialog.resetCallBack && this.Dialog.resetCallBack() }, removeCallBack: () => { this.Dialog.removeCallBack && this.Dialog.removeCallBack() }, closeCallBack: () => { this.reset() this.positionEditing = false // this.entity.style = new Cesium.Cesium3DTileStyle({ // color: "color('rgba(255,255,255," + this.newData.transparency + ")')", // show: true, // }); this.Dialog.closeCallBack && this.Dialog.closeCallBack() }, showCallBack: show => { this.show = show this.Dialog.showCallBack && this.Dialog.showCallBack() }, translationalCallBack: () => { this.positionEditing = !this.positionEditing } }, true ) document.getElementsByTagName('head')[0].appendChild(this._element_style) let contentElm = document.createElement('div') contentElm.innerHTML = html() this._DialogObject.contentAppChild(contentElm) let all_elm = contentElm.getElementsByTagName('*') this._EventBinding.on(this, all_elm) this._elms = this._EventBinding.element // 颜色组件 let colorPicker = new YJColorPicker({ el: contentElm.getElementsByClassName('color')[0], size: 'mini', //颜色box类型 alpha: true, //是否开启透明度 defaultColor: this.color, disabled: false, //是否禁止打开颜色选择器 openPickerAni: 'opacity', //打开颜色选择器动画 sure: color => { this.color = color }, //点击确认按钮事件回调 clear: () => { this.color = 'rgba(255,255,255,1)' } //点击清空按钮事件回调 }) this._elms.color = [colorPicker] } else { if (this._element_style) { document .getElementsByTagName('head')[0] .removeChild(this._element_style) this._element_style = null } if (this._DialogObject && this._DialogObject.remove) { this._DialogObject.remove() this._DialogObject = null } } } /**@desc 打开平移功能 * * @memberOf Source * @param status {boolean} * * */ set positionEditing(status) { if (!this.sdk || !this.sdk.viewer || !this.entity) { return } this._positionEditing = status this.previous = { position: { ...this.options.position } } if (status === true) { this.tip && this.tip.destroy() this.tip = new MouseTip('点击鼠标左键确认,右键取消', this.sdk) this.event.mouse_move((movement, cartesian) => { let position = this.cartesian3Towgs84(cartesian, this.sdk.viewer) this.options.position.lng = position.lng this.options.position.lat = position.lat this.options.position.alt = position.alt this.tip.setPosition( cartesian, movement.endPosition.x, movement.endPosition.y ) }) this.event.mouse_left((movement, cartesian) => { let position = this.cartesian3Towgs84(cartesian, this.sdk.viewer) this.options.position.lng = position.lng this.options.position.lat = position.lat this.options.position.alt = position.alt this.event.mouse_move(() => {}) this.event.mouse_left(() => {}) this.event.mouse_right(() => {}) this.positionEditing = false }) this.event.mouse_right((movement, cartesian) => { this.options.position.lng = this.previous.position.lng this.options.position.lat = this.previous.position.lat this.options.position.alt = this.previous.position.alt this.positionEditing = false }) } else { if (this.event) { this.event.mouse_move(() => { }) this.event.mouse_left(() => { }) this.event.mouse_right(() => { }) } this.tip && this.tip.destroy() } } get positionEditing() { return this._positionEditing } /** * 飞到 */ async flyTo(options = {}) { let canvas = this.getcanvas() let ratio = canvas.height / canvas.width if (this.options.customView) { this.sdk.viewer.camera.flyTo({ destination: this.options.customView.position, orientation: this.options.customView.orientation }) } else { let gap = Math.abs(Math.cos((Math.PI / 180) * this.options.position.lat)) * (0.0001 * this.options.scale) let fromDegreesArray = [ [ this.options.position.lng - (0.0001 * this.options.scale) / ratio, this.options.position.lat - gap ], [ this.options.position.lng + (0.0001 * this.options.scale) / ratio, this.options.position.lat + gap ] ] let height = await this.getClampToHeight(this.options.position) let positionArray = [] for (let i = 0; i < fromDegreesArray.length; i++) { let a = Cesium.Cartesian3.fromDegrees(...fromDegreesArray[i], height) positionArray.push(a.x, a.y, a.z) } let BoundingSphere = Cesium.BoundingSphere.fromVertices(positionArray) this.sdk.viewer.camera.flyToBoundingSphere(BoundingSphere, { offset: options.orientation || { heading: Cesium.Math.toRadians(0.0), pitch: Cesium.Math.toRadians(-90.0), roll: Cesium.Math.toRadians(0.0) } }) } } reset() { if (!this.entity) { return } this.options = this.deepCopyObj(this.originalOptions) this.text = this.originalOptions.text this.angle = this.originalOptions.angle this.scale = this.originalOptions.scale this.color = this.originalOptions.color } async remove() { this.event && this.event.destroy() this.tip && this.tip.destroy() this.sdk.viewer.entities.remove(this.entity) this.entity = null if (this._DialogObject && !this._DialogObject.isDestroy) { this._DialogObject.close() this._DialogObject = null } await this.sdk.removeIncetance(this.options.id) await syncData(this.sdk, this.options.id) } getcanvas() { const canvas = document.createElement('canvas') const ctx = canvas.getContext('2d') let textArray = this.options.text.split('\n') let maxWidth = 0 for (let i = 0; i < textArray.length; i++) { ctx.font = 200 + 'px serif' const width = ctx.measureText(textArray[i]).width if (maxWidth < width) { maxWidth = width } } canvas.width = maxWidth canvas.height = 220 * textArray.length for (let i = 0; i < textArray.length; i++) { ctx.font = 200 + 'px serif' ctx.fillStyle = 'rgba(255, 255, 255, 0)' ctx.fillRect(0, 0, maxWidth + 30, 210) ctx.fillStyle = this.options.color ctx.font = '200px serif' ctx.fillText(textArray[i], 0, 210 * (i + 1)) } return canvas } } export default GroundText