import Dialog from '../../Element/Dialog'; import { html } from "./_element"; import EventBinding from '../../Element/Dialog/eventBinding'; import { syncData } from '../../../Global/MultiViewportMode' import LabelObject from '../LabelObject' import DrawPoint from '../../../Draw/drawPoint.js' import richText from '../../Element/richText' import { legp } from '../../Element/datalist' import { FontLoader } from '../../../../static/3rdparty/three/jsm/loaders/FontLoader.js'; import { TextGeometry } from '../../../../static/3rdparty/three/jsm/geometries/TextGeometry.js'; import * as variable from '../../../../static/3rdparty/three/fonts/FZZongYi-M05S_regular.typeface.json' import Base from "../index"; import { setActiveViewer, closeRotateAround, closeViewFollow } from '../../../Global/global' import { setSplitDirection, syncSplitData, setActiveId } from '../../../Global/SplitScreen' class GroundSvg extends Base { /** * @constructor * @param sdk * @description 贴地svg * @param options {object} 属性 * @param options.id {string} 唯一标识 * @param options.show=true {boolean} 显示/隐藏 * @param options.name {string} 名称 * @param options.angle=0 {number} 旋转角度 * @param options.scale {object} 比例 * @param options.scale.x=1 {number} x轴比例 * @param options.scale.y=1 {number} y轴比例 * @param options.url {string} 资源地址 * @param options.flipe {object} 翻转 * @param options.flipe.x=false {boolean} 绕X轴翻转 * @param options.flipe.y=false {boolean} 绕Y轴翻转 * @param {Array.} options.position 位置 * @param options.position.lng {number} 经度 * @param options.position.lat {number} 纬度 * @param options.color {string} 颜色 * @param options.text {object} 文字 * @param options.text.show=true {boolean} 文字 * @param options.text.position.lng {number} 经度 * @param options.text.position.lat {number} 纬度 * @param options.text.position.alt {number} 高度 * @param options.text.fontSize=20 {number} 字体大小 * @param options.text.color=#ffffff {string} 字体大小 * @param options.text.scaleByDistance {boolean} 距离缩放 * @param options.text.near=2000 {number} 视野缩放最近距离 * @param options.text.far=100000 {number} 视野缩放最远距离 * @param options.attribute {object} 属性内容 * @param {object} options.attribute.link={} 链接 * @param options.attribute.link.content=[]] {array} 链接内容 * @param options.attribute.link.content[].name {string} 链接名称 * @param options.attribute.link.content[].url {string} 链接地址 * @param options.richTextContent {string} 富文本内容 * @param options.customView {object} 默认视角 * @param options.customView.orientation {object} 默认视角方位 * @param options.customView.orientation.heading {number} 航向角 * @param options.customView.orientation.pitch {number} 俯仰角 * @param options.customView.orientation.roll {number} 翻滚角 * @param options.customView.relativePosition {object} 视角相对位置 * @param options.customView.relativePosition.lng {number} 经度 * @param options.customView.relativePosition.lat {number} 纬度 * @param options.customView.relativePosition.alt {number} 高度 * */ #loadEvent = void 0 #loaded = false constructor(sdk, options = {}, _Dialog = {}) { super(sdk, options); let jsCode = ` importScripts('${this.getSourceRootPath()}/3rdparty/turf.min.js'); self.addEventListener('message', function (e) { let features = [] eval(e.data.code); self.postMessage(features); }, false); `; let dataUri = 'data:text/javascript;charset=utf-8,' + encodeURIComponent(jsCode); this._worker = new Worker(dataUri); this.options.angle = this.options.angle || 0 this.loaded = false; this.ismove = false; if (this.options.position.lat > 83.5) { this.options.position.lat = 83.5 } if (this.options.position.lat < -83.5) { this.options.position.lat = -83.5 } this.options.show = (options.show || options.show === false) ? options.show : true this.options.scale = options.scale || {} this.options.scale.x = (this.options.scale.x || this.options.scale.x === 0) ? this.options.scale.x : 1 this.options.scale.y = (this.options.scale.y || this.options.scale.y === 0) ? this.options.scale.y : 1 this.options.flipe = options.flipe || {} this.options.flipe.x = this.options.flipe.x || false this.options.flipe.y = this.options.flipe.y || false this.options.attribute = options.attribute || {} this.options.attribute.link = this.options.attribute.link || {} this.options.attribute.link.content = this.options.attribute.link.content || [] this.options.attributeType = options.attributeType || 'richText' options.text = options.text || {} this.options.text = { value: options.text.value || '', show: (options.text.show || options.text.show === false) ? options.text.show : true, position: options.text.position, fontSize: (options.text.fontSize || options.text.fontSize === 0) ? options.text.fontSize : 20, color: options.text.color || '#ffffff', scaleByDistance: options.text.scaleByDistance || false, near: (options.text.near || options.text.near === 0) ? options.text.near : 2000, far: (options.text.far || options.text.far === 0) ? options.text.far : 100000, } if (this.options.text.position) { let point1 = turf.point([this.options.position.lng, this.options.position.lat]) let point2 = turf.point([this.options.text.position.lng, this.options.text.position.lat]) let distance = turf.distance(point1, point2, { units: 'kilometers' }); let angle = turf.rhumbBearing(point1, point2); this._textToCenter = { distance: distance, angle: angle } } this.hierarchys = [] this._elms = {}; this.Dialog = _Dialog this._isdrag = false this._EventBinding = new EventBinding() if(this.sdk.entityMap.get(this.options.id)) { return } this.sdk.addIncetance(this.options.id, this) this.picking = true if (this.options.show) { setSplitDirection(0, this.options.id) } this._entityArray = [] this.init() } get type () { return 'GroundSvg' } get attributeSelect() { return [ { name: '富文本', value: '富文本', key: 'richText' }, { name: '链接', value: '链接', key: 'link' }, ] } get name() { return this.options.name } set name(v) { this.options.name = v this._elms.name && this._elms.name.forEach((item) => { item.value = v }) } get show() { return this.options.show } set show(v) { if (typeof v === "boolean") { if (this.options.text && this.options.text.show) { if(this.text) { if((!this.showView || this.showView == 3)) { this.text.show = v } else { this.text.show = false } } } super.show = v } else { console.error("参数必须为boolean") } } get position() { return this.options.position } set position(v) { this.options.position = v if (this.options.position.lat > 83.5) { this.options.position.lat = 83.5 } if (this.options.position.lat < -83.5) { this.options.position.lat = -83.5 } this._update() if (this._textToCenter) { let point = turf.point([this.options.position.lng, this.options.position.lat]) let targetPoint = turf.destination(point, this._textToCenter.distance, this._textToCenter.angle, { units: 'kilometers' }).geometry.coordinates this.getClampToHeight({ lng: targetPoint[0], lat: targetPoint[1] }).then((height) => { let textPosition = [targetPoint[0], targetPoint[1], height] this.text && (this.text.position = textPosition) }) } } get color() { return this.options.color } set color(v) { this.options.color = v if (this.options.color) { for (let i = 0; i < this.entity.values.length; i++) { this.entity.values[i].polygon.material = Cesium.Color.fromCssColorString(this.options.color) } } else { for (let i = 0; i < this.entity.values.length; i++) { this.entity.values[i].polygon.material = Cesium.Color.fromCssColorString(this.entity.values[i].properties.color._value) } } if (this._elms.color) { this._elms.color.forEach((item, i) => { let colorPicker = new YJColorPicker({ el: item.el, size: 'mini',//颜色box类型 alpha: true,//是否开启透明度 defaultColor: this.color || undefined, disabled: false,//是否禁止打开颜色选择器 openPickerAni: 'opacity',//打开颜色选择器动画 sure: (c) => { this.color = c },//点击确认按钮事件回调 clear: () => { this.color = '' },//点击清空按钮事件回调 }) this._elms.color[i] = colorPicker }) } } get angle() { return this.options.angle } set angle(v) { // console.log(v, Math.ceil(Math.abs(v / 360)), (Number(v) + Number(v) * Math.ceil(Math.abs(v / 360))) % 360) let angle = (Number(v) + 360) % 360 angle = parseFloat(angle.toFixed(1)) this.options.angle = angle if (v > 0 && angle === 0) { this.options.angle = 360 } this._elms.angle && this._elms.angle.forEach((item) => { item.value = this.options.angle }) this._update() } get scale() { return this.options.scale } set scale(scale) { this.options.scale.x = scale.x this.options.scale.y = scale.y if (this._elms) { this._elms.xRange && (this._elms.xRange.value = this.options.scale.x) this._elms.yRange && (this._elms.yRange.value = this.options.scale.y) this._elms.xInput && (this._elms.xInput.value = this.options.scale.x) this._elms.yInput && (this._elms.yInput.value = this.options.scale.y) } this._update() } get flipeY() { return this.options.flipe.y } set flipeY(v) { if (typeof v === "boolean") { this.options.flipe.y = v this._update() } else { console.error("参数必须为boolean") } } get flipeX() { return this.options.flipe.x } set flipeX(v) { if (typeof v === "boolean") { this.options.flipe.x = v this._update() } else { console.error("参数必须为boolean") } } get textValue() { return this.options.text.value } set textValue(v) { this.options.text.value = v if(this.text) { this.text.text = v } else { GroundSvg.createText(this) } this._elms.textValue && this._elms.textValue.forEach((item) => { item.value = v }) } get textShow() { return this.options.text.show } set textShow(v) { this.options.text.show = v if (this.show) { if((!this.showView || this.showView == 3)) { this.text && (this.text.show = v) } else { this.text && (this.text.show = false) } if (this.options.text.position) { setTimeout(() => { if (this.options.text.position.alt) { this.text && (this.text.position = [this.options.text.position.lng, this.options.text.position.lat, this.options.text.position.alt]) } else { this.getClampToHeight({ lng: this.options.text.position.lng, lat: this.options.text.position.lat }).then((height) => { this.text && (this.text.position = [this.options.text.position.lng, this.options.text.position.lat, height]) }) } }, 0); } } else { this.text && (this.text.show = false) } this._elms.textShow && this._elms.textShow.forEach((item) => { item.checked = v }) } get textColor() { return this.options.text.color } set textColor(v) { this.options.text.color = v this.text && (this.text.color = v) if (this._elms.textColor) { this._elms.textColor.forEach((item, i) => { let textColorPicker = new YJColorPicker({ el: item.el, size: 'mini',//颜色box类型 alpha: true,//是否开启透明度 defaultColor: this.textColor, disabled: false,//是否禁止打开颜色选择器 openPickerAni: 'opacity',//打开颜色选择器动画 sure: (color) => { this.textColor = color },//点击确认按钮事件回调 clear: () => { this.textColor = 'rgba(255,255,255,1)' },//点击清空按钮事件回调 }) this._elms.textColor[i] = textColorPicker }) } } get textFontSize() { return this.options.text.fontSize } set textFontSize(v) { this.options.text.fontSize = v if(this.text) { this.text.fontSize = v this.text.pixelOffset = v } this._elms.textFontSize && this._elms.textFontSize.forEach((item) => { item.value = v }) } get textScaleByDistance() { return this.options.text.scaleByDistance } set textScaleByDistance(v) { this.options.text.scaleByDistance = v this.text && (this.text.scaleByDistance = v) this._elms.textScaleByDistance && this._elms.textScaleByDistance.forEach((item) => { item.checked = v }) } get textNear() { return this.options.text.near } set textNear(v) { let near = v if (near > this.textFar) { near = this.textFar } this.options.text.near = near this.text && (this.text.near = near) this._elms.textNear && this._elms.textNear.forEach((item) => { item.value = near }) } get textFar() { return this.options.text.far } set textFar(v) { let far = v if (far < this.textNear) { far = this.textNear } this.options.text.far = far this.text && (this.text.far = far) this._elms.textFar && this._elms.textFar.forEach((item) => { item.value = far }) } get attributeType() { return this.options.attributeType } set attributeType(v) { this.options.attributeType = v this._elms.attributeType && this._elms.attributeType.forEach(item => { item.value = v }) let attributeContent = this._DialogObject._element.content.getElementsByClassName( 'attribute-content' ) for (let i = 0; i < attributeContent.length; i++) { if ( attributeContent[i].className.indexOf('attribute-content-' + v) > -1 ) { attributeContent[i].style.display = 'block' } else { attributeContent[i].style.display = 'none' } } } get attributeLink() { return this.options.attribute.link.content } set attributeLink(v) { this.options.attribute.link.content = v if ( !this._DialogObject || !this._DialogObject._element || !this._DialogObject._element.content || this._DialogObject._element.content.getElementsByClassName( 'attribute-content-link' ).length == 0 ) { return } let table = this._DialogObject._element.content .getElementsByClassName('attribute-content-link')[1] .getElementsByClassName('table')[0] let tableContent = table.getElementsByClassName('table-body')[0] tableContent.innerHTML = '' if (this.options.attribute.link.content.length > 0) { table.getElementsByClassName('table-empty')[0].style.display = 'none' } else { table.getElementsByClassName('table-empty')[0].style.display = 'flex' } for (let i = 0; i < this.options.attribute.link.content.length; i++) { let tr = `
` + this.options.attribute.link.content[i].name + `
` + this.options.attribute.link.content[i].url + `
` let trElm = document.createRange().createContextualFragment(tr) tableContent.appendChild(trElm) } let item = tableContent.getElementsByClassName('tr') let fun = { linkEdit: async index => { this.attributeLink = await this.options.attribute.link.content let table = this._DialogObject._element.content .getElementsByClassName('attribute-content-link')[1] .getElementsByClassName('table')[0] let tableContent = table.getElementsByClassName('table-body')[0] let item = tableContent.getElementsByClassName('tr') for (let i = 0; i < item.length; i++) { if (index === i) { let height = item[i].offsetHeight let html = `
` item[i].innerHTML = html let textareaElm = item[i].getElementsByClassName('link-edit')[0] textareaElm.style.height = height - 10 + 'px' let td = item[i].getElementsByClassName('td') td[0].getElementsByClassName( 'input' )[0].value = this.options.attribute.link.content[index].name td[1].getElementsByClassName( 'input' )[0].value = this.options.attribute.link.content[index].url let btn = item[i].getElementsByTagName('button') for (let n = 0; n < btn.length; n++) { if (!btn[n] || !btn[n].attributes) { continue } for (let m of btn[n].attributes) { if (m.name === '@click') { btn[n].addEventListener('click', e => { if (typeof fun[m.value] === 'function') { fun[m.value]( { name: td[0].getElementsByClassName('input')[0].value, url: td[1].getElementsByClassName('input')[0].value }, i ) } }) btn[n].attributes.removeNamedItem(m.name) break } } } break } } }, linkDelete: i => { this.options.attribute.link.content.splice(i, 1) this.attributeLink = this.options.attribute.link.content }, confirmEdit: (value, i) => { let name = value.name && value.name.replace(/\s/g, '') let url = value.url && value.url.replace(/\s/g, '') if (name && url) { this.options.attribute.link.content[i] = value } else { window.ELEMENT && window.ELEMENT.Message({ message: '名称或链接不能为空!', type: 'warning', duration: 1500 }) } this.attributeLink = this.options.attribute.link.content }, cancelEdit: () => { this.attributeLink = this.options.attribute.link.content }, fileSelect: (value, i) => { let fileElm = item[i].getElementsByClassName('file-select')[0] fileElm.click() fileElm.removeEventListener('change', fileSelect) fileElm.addEventListener('change', fileSelect) } } let fileSelect = event => { if (event.target.value) { let td = item[ event.target.getAttribute('index') ].getElementsByClassName('td') td[1].getElementsByClassName('input')[0].value = event.target.value event.target.value = null } } for (let i = 0; i < item.length; i++) { let btn = item[i].getElementsByTagName('button') for (let n = 0; n < btn.length; n++) { if (!btn[n] || !btn[n].attributes) { continue } for (let m of btn[n].attributes) { if (m.name === '@click') { btn[n].addEventListener('click', e => { if (typeof fun[m.value] === 'function') { fun[m.value](i) } }) btn[n].attributes.removeNamedItem(m.name) break } } } } } init() { let url = this.replaceHost(this.options.url, this.options.host) syncData(this.sdk, this.options.id) this.hierarchys = [] this.originalOptions = this.deepCopyObj(this.options) let geometryArray = [] const loader = new SVGLoader(); loader.load(url, (data) => { if (!this.sdk || !this.sdk.viewer || !this.sdk.viewer.entities) { return } data.xml.style.width = '0' data.xml.style.height = '0' document.body.appendChild(data.xml) for (const path of data.paths) { const fillColor = path.userData.style.fill; let style = window.getComputedStyle(path.userData.node) if (style.strokeWidth) { path.userData.style.strokeWidth = Number(style.strokeWidth.replace(/[a-zA-Z]/g, '')) } if (fillColor !== undefined && fillColor !== 'none') { const shapes = SVGLoader.createShapes(path); for (const shape of shapes) { const geometry = new THREE.ShapeGeometry(shape); const mesh = new THREE.Mesh(geometry); geometryArray.push({ geometry: mesh.geometry, color: fillColor }) } } const strokeColor = path.userData.style.stroke; if (strokeColor !== undefined && strokeColor !== 'none') { for (const subPath of path.subPaths) { const geometry = SVGLoader.pointsToStroke(subPath.getPoints(), path.userData.style); if (geometry) { const mesh = new THREE.Mesh(geometry); geometryArray.push({ geometry: mesh.geometry, color: strokeColor }) } } } } document.body.removeChild(data.xml) let min = 0 let max = 0 let geojson for (let key = 0; key < geometryArray.length; key++) { let geometry = geometryArray[key].geometry; if (!geometry || !geometry.attributes || !geometry.attributes.position) { continue } let array = geometry.attributes.position.array for (let i = 0; i < array.length; i++) { if (min > array[i]) { min = array[i] } if (max < array[i]) { max = array[i] } } } min = Math.abs(min) max = Math.abs(max) if (min > max) { max = min } let max2 = max max = max * (10 / 3) * 100 let scale = (4000 / max) / 5 max2 = max2 * scale for (let key = 0; key < geometryArray.length; key++) { geometryArray[key].geometry.scale(scale, scale, 1) geometryArray[key].geometry.rotateX(THREE.MathUtils.degToRad(180)) } let jsCode = ` let geometryArray = e.data.options.geometryArray let max2 = e.data.options.max2 for (let key = 0; key < geometryArray.length; key++) { let feature let positions = [] let position = [] let geometry = geometryArray[key].geometry; let array = geometry.attributes.position.array for (let i = 0; i < array.length; i += 3) { let x = array[i] - (max2 / 2) let y = array[i + 1] + (max2 / 2) position.push([x, y, array[i + 1]]) } if (geometry.index && geometry.index.array) { let index = geometry.index.array for (let i = 0; i < index.length; i += 3) { positions.push([position[index[i]], position[index[i + 1]], position[index[i + 2]]]) } } else { for (let i = 0; i < position.length; i += 3) { positions.push([position[i], position[i + 1], position[i + 2]]) } } let polygons = [] // 组合多边形 for (let i = 0; i < positions.length; i++) { let polygon = turf.polygon([[ ...positions[i], positions[i][0] ]]); polygons.push(polygon) if (feature) { feature = turf.union(feature, polygon); } else { feature = polygon } } feature.properties.color = geometryArray[key].color features.push(feature) } ` this._worker.postMessage({ code: jsCode, options: { geometryArray: geometryArray, max2: max2 } }); this._worker.onmessage = (event) => { if (!this.sdk || !this.sdk.viewer || !this.sdk.viewer.entities) { return } let features = event.data geojson = turf.featureCollection(features) this.geojson = JSON.parse(JSON.stringify(geojson)) // 计算边界框 let bbox = turf.bbox(geojson); let width = Math.abs(bbox[2] - bbox[0]) let height = Math.abs(bbox[3] - bbox[1]) // 获取最小正方形 let square = turf.square(bbox); // 控制点界限 square[0] = square[0] + this.options.position.lng - (width / 5) square[1] = square[1] + this.options.position.lat - (height / 5) square[2] = square[2] + this.options.position.lng + (width / 5) square[3] = square[3] + this.options.position.lat + (height / 5) this.bbox = square this.geojson.features.forEach(item => { let array = [] let geojson = JSON.parse(JSON.stringify(item)) geojson.properties.directionDistance = [] if (geojson.geometry.type === 'MultiPolygon') { for (let i = 0; i < geojson.geometry.coordinates.length; i++) { let array = [] for (let m = 0; m < geojson.geometry.coordinates[i].length; m++) { let array2 = [] for (let n = 0; n < geojson.geometry.coordinates[i][m].length; n++) { let point1 = turf.point([0, geojson.geometry.coordinates[i][m][n][1]]) let point2 = turf.point([...geojson.geometry.coordinates[i][m][n]]) let distance = turf.distance(point1, point2, { units: 'kilometers' }); let angle = turf.rhumbBearing(point1, point2); array2.push( { origin: geojson.geometry.coordinates[i][m][n], distance: distance, angle: angle } ) } array.push(array2) } geojson.properties.directionDistance.push(array) } } else { for (let i = 0; i < geojson.geometry.coordinates.length; i++) { let array = [] for (let m = 0; m < geojson.geometry.coordinates[i].length; m++) { let point1 = turf.point([0, geojson.geometry.coordinates[i][m][1]]) let point2 = turf.point([...geojson.geometry.coordinates[i][m]]) let distance = turf.distance(point1, point2, { units: 'kilometers' }); let angle = turf.rhumbBearing(point1, point2); array.push( { origin: geojson.geometry.coordinates[i][m], distance: distance, angle: angle } ) } geojson.properties.directionDistance.push(array) } } if (geojson.geometry.type === 'MultiPolygon') { for (let i = 0; i < geojson.geometry.coordinates.length; i++) { let hierarchy = this.getHierarchyPolygon(geojson, i) array.push(hierarchy) } } else { let hierarchy = this.getHierarchyPolygon(geojson) array.push(hierarchy) } this.hierarchys.push(array) }); this.entity = new Cesium.EntityCollection() syncSplitData(this.sdk, this.options.id) let perPositionHeight = false if (this.sdk.viewer._element.className === 'cesium-viewer 2d') { perPositionHeight = true } for (let i = 0; i < this.hierarchys.length; i++) { for (let m = 0; m < this.hierarchys[i].length; m++) { let id = this.options.id + `-${i}_${m}}` let oldEntity = this.sdk.viewer.entities.getById(id) if(oldEntity) { this.sdk.viewer.entities.remove(oldEntity) } let entity = this.sdk.viewer.entities.add({ id: this.options.id + `-${i}_${m}}`, show: this.options.show, polygon: { hierarchy: new Cesium.CallbackProperty(() => { let hierarchy = this.hierarchys[i][m] let holes = [] for (let n = 0; n < hierarchy.holes.length; n++) { holes.push({ positions: hierarchy.holes[n] }) } return { positions: hierarchy.positions, holes: holes } }, true), perPositionHeight: perPositionHeight, zIndex: this.sdk._entityZIndex, material: new Cesium.CustomColorMaterialSource({ color: this.options.color || this.geojson.features[i].properties.color }) }, properties: { id: this.options.id } }) this.sdk._entityZIndex++ if (this.geojson.features[i].properties.color) { entity.properties = { id: this.options.id, color: this.geojson.features[i].properties.color } } this._entityArray.push(entity) this.entity.add(entity) } } this.loaded = true this.#loaded = true if (this.#loadEvent) { this.#loadEvent() } this.scale = this.scale GroundSvg.createText(this) // GroundSvg.initText(this) } }) } static async createText(that) { if (that.options.text.position) { let height if (that.options.text.position.alt) { height = that.options.text.position.alt } else { height = await that.getClampToHeight({ lng: that.options.text.position.lng, lat: that.options.text.position.lat }) } that.text = new LabelObject(that.sdk, { id: that.options.id, show: that.options.show ? (that.options.text.show ? that.options.text.show : false) : false, position: [that.options.text.position.lng, that.options.text.position.lat, height], text: that.options.text.value, fontSize: that.options.text.fontSize, color: that.options.text.color, pixelOffset: that.options.text.fontSize, backgroundColor: that.options.text.backgroundColor, lineColor: '#ffffff00', lineWidth: 0, scaleByDistance: that.options.text.scaleByDistance, backgroundColor: ['#ffffff00', '#ffffff00'], near: that.options.text.near, far: that.options.text.far, }) that.text.entity.billboard.verticalOrigin = Cesium.VerticalOrigin.CENTER // that.text.entity.billboard.horizontalOrigin = Cesium.HorizontalOrigin.LEFT } } /** * 编辑框 * @param {boolean} status=false 状态 */ async edit(state) { if (!this.#loaded) { return } this.originalOptions = this.deepCopyObj(this.options) if (this._DialogObject && this._DialogObject.close) { this._DialogObject.close() this._DialogObject = null } if (state) { this._DialogObject = await new Dialog(this.sdk, this.originalOptions, { title: '军标属性', left: '180px', top: '100px', confirmCallBack: (options) => { this.name = this.name.trim() if (!this.name) { this.name = '未命名对象' } this.text && (this.options.text.position = { lng: this.text.position[0], lat: this.text.position[1], alt: this.text.position[2] }) this.originalOptions = this.deepCopyObj(this.options) this._DialogObject.close() let cdoptions = this.deepCopyObj(this.options) cdoptions.host = '' this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(cdoptions) syncData(this.sdk, this.options.id) syncSplitData(this.sdk, this.options.id) }, resetCallBack: () => { this.reset() this.Dialog.resetCallBack && this.Dialog.resetCallBack() }, removeCallBack: () => { this.Dialog.removeCallBack && this.Dialog.removeCallBack() }, closeCallBack: () => { this._DialogObject = null this.drag(false) this.reset() // 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() }, addFootElm: [ { tagName: 'button', className: 'flipe-over-y', innerHTML: 'Y轴翻转', event: [ 'click', () => { this.flipeY = !this.flipeY } ] }, { tagName: 'button', className: 'flipe-over-x', innerHTML: 'X轴翻转', event: [ 'click', () => { this.flipeX = !this.flipeX } ] }, { tagName: 'button', className: 'drag', innerHTML: '编辑', event: [ 'click', () => { this.drag(!this._isdrag) } ] } ] }, true) this._DialogObject._element.body.className = this._DialogObject._element.body.className + ' ground-svg' let contentElm = document.createElement('div'); contentElm.innerHTML = html(this) await this._DialogObject.contentAppChild(contentElm) this.attributeType = this.options.attributeType // 颜色组件 let colorPicker = new YJColorPicker({ el: contentElm.getElementsByClassName("color")[0], size: 'mini',//颜色box类型 alpha: true,//是否开启透明度 defaultColor: this.color || undefined, disabled: false,//是否禁止打开颜色选择器 openPickerAni: 'opacity',//打开颜色选择器动画 sure: (color) => { this.color = color },//点击确认按钮事件回调 clear: () => { this.color = '' },//点击清空按钮事件回调 }) let textColorPicker = new YJColorPicker({ el: contentElm.getElementsByClassName("textColor")[0], size: 'mini',//颜色box类型 alpha: true,//是否开启透明度 defaultColor: this.textColor, disabled: false,//是否禁止打开颜色选择器 openPickerAni: 'opacity',//打开颜色选择器动画 sure: (color) => { this.textColor = color },//点击确认按钮事件回调 clear: () => { this.textColor = 'rgba(255,255,255,1)' },//点击清空按钮事件回调 }) let all_elm = contentElm.getElementsByTagName("*") this._EventBinding.on(this, all_elm) this._elms = this._EventBinding.element this._elms.color = [colorPicker] this._elms.textColor = [textColorPicker] setTimeout(async () => { if (this.sdk && this.sdk.tabHide && Array.isArray(this.sdk.tabHide)) { for (let m = 0; m < this.sdk.tabHide.length; m++) { if (this.sdk.tabHide[m] === '属性信息') { contentElm.getElementsByClassName('attribute-info')[0].style.display = 'none' break } } } this.attributeLink = this.options.attribute.link.content let tagData = this.attributeSelect let attributeElm = this._DialogObject._element.content.getElementsByClassName( 'attribute-select-box' )[0] if (attributeElm) { let legpObject = legp(attributeElm, '.attribute-select') legpObject.legp_search(tagData) let attributeSelectElm = this._DialogObject._element.content .getElementsByClassName('attribute-select')[0] .getElementsByTagName('input')[0] for (let i = 0; i < tagData.length; i++) { if (tagData[i].key === this.options.attributeType) { attributeSelectElm.value = tagData[i].value legpObject.legp_searchActive(tagData[i].value) break } } attributeSelectElm.addEventListener('input', () => { for (let i = 0; i < tagData.length; i++) { if (tagData[i].value === attributeSelectElm.value) { this.attributeType = tagData[i].key break } } }) } }, 0) let xElm = contentElm.getElementsByClassName('x-scale')[0] let yElm = contentElm.getElementsByClassName('y-scale')[0] let xRange = xElm.getElementsByTagName('input')[0] let xInput = xElm.getElementsByTagName('input')[1] let yRange = yElm.getElementsByTagName('input')[0] let yInput = yElm.getElementsByTagName('input')[1] xRange.value = this.scale.x xInput.value = this.scale.x yRange.value = this.scale.y yInput.value = this.scale.y this._elms.xRange = xRange this._elms.yRange = yRange this._elms.xInput = xInput this._elms.yInput = yInput xRange.addEventListener('input', (e) => { this.scale = { x: xRange.value, y: this.scale.y } }) yRange.addEventListener('input', (e) => { this.scale = { x: this.scale.x, y: yRange.value } }) xInput.addEventListener('input', (e) => { let value = e.target.value value = Number(value) if (e.data != '.' && (e.data != '-' || e.target.value)) { if (((!e.target.max) && (!e.target.min)) || ((value <= Number(e.target.max)) && value >= Number(e.target.min))) { this.scale = { x: value, y: this.scale.y } } } }) xInput.addEventListener('blur', (e) => { let value = e.target.value value = Number(value) if ((e.target.max) && value > Number(e.target.max)) { value = Number(e.target.max) } if ((e.target.min) && value < Number(e.target.min)) { value = Number(e.target.min) } this.scale = { x: value, y: this.scale.y } }) yInput.addEventListener('input', (e) => { let value = e.target.value value = Number(value) if (e.data != '.' && (e.data != '-' || e.target.value)) { if (((!e.target.max) && (!e.target.min)) || ((value <= Number(e.target.max)) && value >= Number(e.target.min))) { this.scale = { x: this.scale.x, y: value } } } }) yInput.addEventListener('blur', (e) => { let value = e.target.value value = Number(value) if ((e.target.max) && value > Number(e.target.max)) { value = Number(e.target.max) } if ((e.target.min) && value < Number(e.target.min)) { value = Number(e.target.min) } this.scale = { x: this.scale.x, y: value } }) } } /** * 重置 */ reset() { if (!this.#loaded) { return } this.options = this.deepCopyObj(this.originalOptions) this.position = this.originalOptions.position this.name = this.originalOptions.name this.angle = this.originalOptions.angle this.scale = this.originalOptions.scale this.color = this.originalOptions.color if (this.text && !this.originalOptions.text.position) { this.text.remove() this.text = null } this.attributeLink = this.options.attribute.link.content this.textShow = this.originalOptions.text.show this.textValue = this.originalOptions.text.value this.textColor = this.originalOptions.text.color this.textFontSize = this.originalOptions.text.fontSize this.textScaleByDistance = this.originalOptions.text.scaleByDistance this.textNear = this.originalOptions.text.near this.textFar = this.originalOptions.text.far } /** * 拖动 * @param {boolean} status=false 状态 */ drag(status, cd) { if (!this.#loaded || !this.sdk || !this.sdk.viewer) { return } this.ismove = false this._isdrag = status if (this.ScreenSpaceEventHandler) { this.ScreenSpaceEventHandler.destroy() this.ScreenSpaceEventHandler = null } if (status) { this.ScreenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler( this.sdk.viewer.canvas ) let width = Math.abs(this.bbox[0] - this.bbox[2]) let height = Math.abs(this.bbox[1] - this.bbox[3]) this.ScreenSpaceEventHandler.setInputAction(async (movement) => { if (this.pickPoint) { let sCartesian = this.pickPoint.position.getValue() let eCartesian = this.sdk.viewer.scene.pickPosition(movement.endPosition) if (!eCartesian) { const ray = this.sdk.viewer.camera.getPickRay(movement.endPosition); eCartesian = this.sdk.viewer.scene.globe.pick(ray, this.sdk.viewer.scene); } if (!sCartesian || !eCartesian) { return } let position1 = this.cartesian3Towgs84(sCartesian, this.sdk.viewer) let position2 = this.cartesian3Towgs84(eCartesian, this.sdk.viewer) let x = 0 let y = 0 let radians, radiansW, radiansH let w = 3.5 * this.scale.x let h = 3.5 * this.scale.y let wh = Math.sqrt(((w / 2) ** 2) + ((h / 2) ** 2)) let angle = Math.atan((w / 2) / (h / 2)) * (180 / Math.PI) let angleW, angleH; if (isNaN(angle)) { angle = 0 } let point = turf.point([this.position.lng, this.position.lat]); let options = { units: 'kilometers' }; let controlPoints = [] controlPoints[0] = turf.destination(point, h / 2 * 1.5, 0 + this.options.angle, options).geometry.coordinates controlPoints[1] = turf.destination(point, wh, 180 + angle + this.options.angle, options).geometry.coordinates controlPoints[2] = turf.destination(point, h / 2, 180 + this.options.angle, options).geometry.coordinates controlPoints[3] = turf.destination(point, wh, 180 - angle + this.options.angle, options).geometry.coordinates controlPoints[4] = turf.destination(point, w / 2, 270 + this.options.angle, options).geometry.coordinates controlPoints[5] = [this.position.lng, this.position.lat] controlPoints[6] = turf.destination(point, w / 2, 90 + this.options.angle, options).geometry.coordinates controlPoints[7] = turf.destination(point, wh, 360 - angle + this.options.angle, options).geometry.coordinates controlPoints[8] = turf.destination(point, h / 2, 0 + this.options.angle, options).geometry.coordinates controlPoints[9] = turf.destination(point, wh, 0 + angle + this.options.angle, options).geometry.coordinates let point1 = turf.point([position1.lng, position1.lat]); let point2 = turf.point([position2.lng, position2.lat]); let pointC = turf.point([this.position.lng, this.position.lat]); let bearing1 = turf.rhumbBearing(pointC, point1); let bearing2_0 = turf.rhumbBearing(pointC, point2); let bearing2 = (((bearing2_0 + 360) - this.angle) % 360) let bearingH let bearingW // 中心点到鼠标的距离 let distance = turf.rhumbDistance(pointC, point2, options); let flag = false let flag2 = false switch (this.pickPoint.id) { case 'svg-control-points_0': angle = bearing2_0 - bearing1 this.angle += angle break case 'svg-control-points_1': case 'svg-control-points_7': bearingW = (((turf.rhumbBearing(pointC, turf.point(controlPoints[4])) + 360) - this.angle) % 360) bearingH = (((turf.rhumbBearing(pointC, turf.point(controlPoints[2])) + 360) - this.angle) % 360) angleW = bearing2 - bearingW angleH = bearing2 - bearingH if ((angleW > -360 && angleW < -90) || (angleW < 360 && angleW > 90)) { angleW = angleW + 180 flag=true } if ((angleH > -360 && angleH < -90) || (angleH < 360 && angleH > 90)) { angleH = angleH + 180 flag2=true } if(flag && flag2) { this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#ff0000') } else { if(flag) { this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#ff0000') this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#00ff0a') } else if(flag2) { this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#ff0000') this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#00ff0a') } else { this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#ff0000') this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#00ff0a') } } radiansW = (Math.PI / 180) * angleW radiansH = (Math.PI / 180) * angleH // 矩形高度 w = (Math.cos(radiansW) * distance) * 2 h = (Math.cos(radiansH) * distance) * 2 // scaleY值 this.scale.x = Math.abs(w) / 3.5 this.scale.y = Math.abs(h) / 3.5 break case 'svg-control-points_2': case 'svg-control-points_8': bearingH = (((turf.rhumbBearing(pointC, turf.point(controlPoints[2])) + 360) - this.angle) % 360) angleH = bearing2 - bearingH if ((angleH > -360 && angleH < -90) || (angleH < 360 && angleH > 90)) { angleH = angleH + 180 this.pointEntityCollection.values[2].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[8].point.color = Cesium.Color.fromCssColorString('#ff0000') } else { this.pointEntityCollection.values[2].point.color = Cesium.Color.fromCssColorString('#ff0000') this.pointEntityCollection.values[8].point.color = Cesium.Color.fromCssColorString('#00ff0a') } radiansH = (Math.PI / 180) * angleH // 矩形高度 h = (Math.cos(radiansH) * distance) * 2 // scaleY值 this.scale.y = h / 3.5 break case 'svg-control-points_3': case 'svg-control-points_9': bearingW = (((turf.rhumbBearing(pointC, turf.point(controlPoints[6])) + 360) - this.angle) % 360) bearingH = (((turf.rhumbBearing(pointC, turf.point(controlPoints[2])) + 360) - this.angle) % 360) angleW = bearing2 - bearingW angleH = bearing2 - bearingH if ((angleW > -360 && angleW < -90) || (angleW < 360 && angleW > 90)) { angleW = angleW + 180 flag=true } if ((angleH > -360 && angleH < -90) || (angleH < 360 && angleH > 90)) { angleH = angleH + 180 flag2=true } if(flag && flag2) { this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#ff0000') this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#00ff0a') } else { if(flag) { this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#ff0000') this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#00ff0a') } else if(flag2) { this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#ff0000') } else { this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#ff0000') this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#00ff0a') } } radiansW = (Math.PI / 180) * angleW radiansH = (Math.PI / 180) * angleH // 矩形高度 w = (Math.cos(radiansW) * distance) * 2 h = (Math.cos(radiansH) * distance) * 2 // scaleY值 this.scale.x = Math.abs(w) / 3.5 this.scale.y = Math.abs(h) / 3.5 break case 'svg-control-points_4': bearingW = (((turf.rhumbBearing(pointC, turf.point(controlPoints[4])) + 360) - this.angle) % 360) angleW = bearing2 - bearingW if ((angleW > -360 && angleW < -90) || (angleW < 360 && angleW > 90)) { angleW = angleW + 180 this.pointEntityCollection.values[4].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[6].point.color = Cesium.Color.fromCssColorString('#ff0000') } else { this.pointEntityCollection.values[6].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[4].point.color = Cesium.Color.fromCssColorString('#ff0000') } radiansW = (Math.PI / 180) * angleW // 矩形宽度 w = (Math.cos(radiansW) * distance) * 2 // scaleY值 this.scale.x = w / 3.5 break case 'svg-control-points_5': if (position2.lat > 83.5) { position2.lat = 83.5 } if (position2.lat < -83.5) { position2.lat = -83.5 } this.position = { lng: position2.lng, lat: position2.lat } let cx = position2.lng - position1.lng let cy = position2.lat - position1.lat this.bbox[0] = this.bbox[0] + cx this.bbox[1] = this.bbox[1] + cy this.bbox[2] = this.bbox[2] + cx this.bbox[3] = this.bbox[3] + cy break case 'svg-control-points_6': bearingW = (((turf.rhumbBearing(pointC, turf.point(controlPoints[6])) + 360) - this.angle) % 360) angleW = bearing2 - bearingW if ((angleW > -360 && angleW < -90) || (angleW < 360 && angleW > 90)) { angleW = angleW + 180 this.pointEntityCollection.values[6].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[4].point.color = Cesium.Color.fromCssColorString('#ff0000') } else { this.pointEntityCollection.values[4].point.color = Cesium.Color.fromCssColorString('#00ff0a') this.pointEntityCollection.values[6].point.color = Cesium.Color.fromCssColorString('#ff0000') } radiansW = (Math.PI / 180) * angleW // 矩形高度 w = (Math.cos(radiansW) * distance) * 2 this.scale.x = w / 3.5 break default: } // let radians = (Math.PI / 180) * this.options.angle // x = x*Math.cos(radians) // y = y*Math.cos(radians) // let bbox = turf.bbox(geojson); // let square = turf.square(bbox); x = x / (width / 2) * 100 y = y / (height / 2) * 100 let scale = { ...this.scale } scale.x = scale.x + x scale.y = scale.y - y // let pt = turf.point(this.center); // let destination1 = turf.rhumbDestination(pt, 220, 45, { units: 'kilometers' }); // let destination2 = turf.rhumbDestination(pt, 220, 225, { units: 'kilometers' }); // width = Math.abs(destination2.geometry.coordinates[0] - destination1.geometry.coordinates[0]) // height = Math.abs(destination2.geometry.coordinates[1] - destination1.geometry.coordinates[1]) if (scale.y > 200) { scale.y = 200 } if (scale.y < 0.001) { scale.y = 0.001 } if (scale.x > 200) { scale.x = 200 } if (scale.x < 0.001) { scale.x = 0.001 } this.scale = { ...scale } } else { let pickedObjectArray = this.sdk.viewer.scene.drillPick(movement.endPosition); let pickPoint for (let i = 0; i < pickedObjectArray.length; i++) { let pickedObject = pickedObjectArray[i] if (pickedObject && pickedObject.primitive && pickedObject.primitive._id && (pickedObject.primitive._id.id && pickedObject.primitive._id.id.indexOf('svg-control-points_') !== -1) ) { pickPoint = pickedObject.primitive._id break } } for (let i = 0; i < this.pointEntityCollection.values.length; i++) { if (pickPoint && this.pointEntityCollection.values[i].id === pickPoint.id) { pickPoint.point.color = Cesium.Color.fromCssColorString('#ffff00') } else { switch (this.pointEntityCollection.values[i].id) { case 'svg-control-points_5': this.pointEntityCollection.values[i].point.color = Cesium.Color.fromCssColorString('#ffff00') break case 'svg-control-points_0': this.pointEntityCollection.values[i].point.color = Cesium.Color.fromCssColorString('#ff0000') break default: this.pointEntityCollection.values[i].point.color = Cesium.Color.fromCssColorString('#00ff0a') } } } } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE) this.ScreenSpaceEventHandler.setInputAction((movement) => { let pickedObjectArray = this.sdk.viewer.scene.drillPick(movement.position); for (let i = 0; i < pickedObjectArray.length; i++) { let pickedObject = pickedObjectArray[i] if (pickedObject && pickedObject.primitive && pickedObject.primitive._id && pickedObject.primitive._id.objectId === this.options.id && (pickedObject.primitive._id.id && pickedObject.primitive._id.id.indexOf('svg-control-points_') !== -1) ) { YJ.Global.CameraController(this.sdk, false) this.pickPoint = pickedObject.primitive._id this.pickPoint.point.color = Cesium.Color.fromCssColorString('#ff0000') break } } }, Cesium.ScreenSpaceEventType.LEFT_DOWN) this.ScreenSpaceEventHandler.setInputAction((movement) => { if (this.pickPoint) { YJ.Global.CameraController(this.sdk, true) switch (this.pickPoint.id) { case 'svg-control-points_4': this.pickPoint.point.color = Cesium.Color.fromCssColorString('#ffff00') break case 'svg-control-points_9': this.pickPoint.point.color = Cesium.Color.fromCssColorString('#ff0000') break default: this.pickPoint.point.color = Cesium.Color.fromCssColorString('#00ff0a') } this.pickPoint = null } }, Cesium.ScreenSpaceEventType.LEFT_UP) this.ScreenSpaceEventHandler.setInputAction((movement) => { this.drag(false) if (!this._DialogObject) { cd && cd(this.options) syncData(this.sdk, this.options.id) syncSplitData(this.sdk, this.options.id) } }, Cesium.ScreenSpaceEventType.RIGHT_CLICK) this.pointEntityCollection = new Cesium.EntityCollection() let w = 3.5 * this.scale.x let h = 3.5 * this.scale.y let wh = Math.sqrt(((w / 2) ** 2) + ((h / 2) ** 2)) let angle = Math.atan((w / 2) / (h / 2)) * (180 / Math.PI) if (isNaN(angle)) { angle = 0 } let point = turf.point([this.position.lng, this.position.lat]); let options = { units: 'kilometers' }; let controlPoints = [] controlPoints[0] = turf.destination(point, h / 2 * 1.5, 0, options).geometry.coordinates controlPoints[1] = turf.destination(point, wh, 180 + angle, options).geometry.coordinates controlPoints[2] = turf.destination(point, h / 2, 180, options).geometry.coordinates controlPoints[3] = turf.destination(point, wh, 180 - angle, options).geometry.coordinates controlPoints[4] = turf.destination(point, w / 2, 270, options).geometry.coordinates controlPoints[5] = [this.position.lng, this.position.lat] controlPoints[6] = turf.destination(point, w / 2, 90, options).geometry.coordinates controlPoints[7] = turf.destination(point, wh, 360 - angle, options).geometry.coordinates controlPoints[8] = turf.destination(point, h / 2, 0, options).geometry.coordinates controlPoints[9] = turf.destination(point, wh, 0 + angle, options).geometry.coordinates this.controlPoints = controlPoints if(!this.sdk || !this.sdk.viewer) { return } for (let i = 0; i < this.controlPoints.length; i++) { let color = '#00ff0a' if (i === 5) { color = '#ffff00' } if (i === 0) { color = '#ff0000' } let entity = this.sdk.viewer.entities.getOrCreateEntity('svg-control-points_' + i) entity.show = true entity.objectId = this.options.id entity.position = new Cesium.CallbackProperty(() => { return Cesium.Cartesian3.fromDegrees(...this.controlPoints[i]) }) entity.point = new Cesium.PointGraphics({ color: Cesium.Color.fromCssColorString(color), // 点的颜色 pixelSize: 10, // 点的大小 heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, scaleByDistance: new Cesium.NearFarScalar(0.0, 1.0, 1.0e10, 1.0), disableDepthTestDistance: Number.POSITIVE_INFINITY // 不应用深度测试 }) this.pointEntityCollection.add(entity) } this._update() } else { for (let i = 0; i < this.controlPoints.length; i++) { let entity = this.sdk.viewer.entities.getById('svg-control-points_' + i) if (entity && (entity.objectId === this.options.id)) { entity.show = false } } } } getHierarchyPolygon(geojson, key) { if (!geojson) { return } let hierarchy = {} let holes = [] let directionDistance = geojson.properties.directionDistance if (key !== undefined) { directionDistance = geojson.properties.directionDistance[key] } for (let i = 0; i < directionDistance.length; i++) { let positions = [] for (let m = 0; m < directionDistance[i].length; m++) { let lng = this.options.position.lng let lat = directionDistance[i][m].origin[1] + this.options.position.lat if (lat > 90) { lng += 180 } let origin = [lng, lat] let pt = turf.point(origin); let destination = turf.rhumbDestination(pt, directionDistance[i][m].distance, directionDistance[i][m].angle, { units: 'kilometers' }); let coordinates = [...destination.geometry.coordinates] // 二维模式下设置高度 coordinates[2] = 10 positions.push(Cesium.Cartesian3.fromDegrees(...coordinates)) } if (i === 0) { hierarchy.positions = positions } else { holes.push(positions) } } hierarchy.holes = holes return hierarchy } _updateGeojson(data, x, y) { if (!this.#loaded) { return } let width = Math.abs(this.bbox[0] - this.bbox[2]) let height = Math.abs(this.bbox[1] - this.bbox[3]) if (typeof data[0] === 'object') { for (let i = 0; i < data.length; i++) { this._updateGeojson(data[i], x, y) } } else { for (let i = 0; i < data.length; i += 2) { data[i] = data[i] + ((data[i] / (width / 2)) * x) } for (let i = 1; i < data.length; i += 2) { data[i] = data[i] - ((data[i] / (height / 2)) * y) } } } _update() { if (!this.#loaded) { return } let point = turf.point([this.position.lng, this.position.lat]); let options = { units: 'kilometers' }; let interimBbox = [...this.bbox] let width = Math.abs(interimBbox[2] - interimBbox[0]) let height = Math.abs(interimBbox[3] - interimBbox[1]) let x = ((width / 2) * this.options.scale.x) / 100 - (width / 2) let y = (height / 2) * (-(this.options.scale.y)) / 100 + (height / 2) interimBbox[0] = interimBbox[0] - x interimBbox[1] = interimBbox[1] + y interimBbox[2] = interimBbox[2] + x interimBbox[3] = interimBbox[3] - y let interim if (interimBbox[0] > interimBbox[2]) { interim = interimBbox[0] interimBbox[0] = interimBbox[2] interimBbox[2] = interim } if (interimBbox[1] > interimBbox[3]) { interim = interimBbox[1] interimBbox[1] = interimBbox[3] interimBbox[3] = interim } let hierarchys = [] let geojson = JSON.parse(JSON.stringify(this.geojson)) const recursion = (data) => { for (let i = 0; i < data.length; i++) { if (typeof data[i] === 'number') { if (this.options.flipe.x && i === 1) { data[i] = -data[i] } if (this.options.flipe.y && i === 0) { data[i] = -data[i] } } else { recursion(data[i]) } } } for (let i = 0; i < geojson.features.length; i++) { recursion(geojson.features[i].geometry.coordinates) } geojson.features.forEach(item => { let array = [] let feature = JSON.parse(JSON.stringify(item)) this._updateGeojson(feature.geometry.coordinates, x, y) feature = turf.transformRotate(feature, this.angle, { pivot: [0, 0] }); let directionDistance = [] if (feature.geometry.type === 'MultiPolygon') { for (let i = 0; i < feature.geometry.coordinates.length; i++) { let array = [] for (let m = 0; m < feature.geometry.coordinates[i].length; m++) { let array2 = [] for (let n = 0; n < feature.geometry.coordinates[i][m].length; n++) { let point1 = turf.point([0, feature.geometry.coordinates[i][m][n][1]]) let point2 = turf.point([...feature.geometry.coordinates[i][m][n]]) let distance = turf.distance(point1, point2, { units: 'kilometers' }); let angle2 = turf.rhumbBearing(point1, point2); array2.push( { origin: feature.geometry.coordinates[i][m][n], distance: distance, angle: angle2 } ) } array.push(array2) } directionDistance.push(array) } } else { for (let i = 0; i < feature.geometry.coordinates.length; i++) { let array = [] for (let m = 0; m < feature.geometry.coordinates[i].length; m++) { let array2 = [] let point1 = turf.point([0, feature.geometry.coordinates[i][m][1]]) let point2 = turf.point([...feature.geometry.coordinates[i][m]]) let distance = turf.distance(point1, point2, { units: 'kilometers' }); let angle2 = turf.rhumbBearing(point1, point2); array.push({ origin: feature.geometry.coordinates[i][m], distance: distance, angle: angle2 }) } directionDistance.push(array) } } feature.properties.directionDistance = directionDistance // this.bbox = [...interimBbox] let w = 3.5 * this.scale.x let h = 3.5 * this.scale.y let wh = Math.sqrt(((w / 2) ** 2) + ((h / 2) ** 2)) let angle = Math.atan((w / 2) / (h / 2)) * (180 / Math.PI) if (isNaN(angle)) { angle = 0 } let controlPoints = [] controlPoints[0] = turf.destination(point, h / 2 * 1.5, 0 + this.options.angle, options).geometry.coordinates controlPoints[1] = turf.destination(point, wh, 180 + angle + this.options.angle, options).geometry.coordinates controlPoints[2] = turf.destination(point, h / 2, 180 + this.options.angle, options).geometry.coordinates controlPoints[3] = turf.destination(point, wh, 180 - angle + this.options.angle, options).geometry.coordinates controlPoints[4] = turf.destination(point, w / 2, 270 + this.options.angle, options).geometry.coordinates controlPoints[5] = [this.position.lng, this.position.lat] controlPoints[6] = turf.destination(point, w / 2, 90 + this.options.angle, options).geometry.coordinates controlPoints[7] = turf.destination(point, wh, 360 - angle + this.options.angle, options).geometry.coordinates controlPoints[8] = turf.destination(point, h / 2, 0 + this.options.angle, options).geometry.coordinates controlPoints[9] = turf.destination(point, wh, 0 + angle + this.options.angle, options).geometry.coordinates let points = turf.points(controlPoints); controlPoints = [] for (let i = 0; i < points.features.length; i++) { controlPoints.push(points.features[i].geometry.coordinates) } this.controlPoints = controlPoints if (feature.geometry.type === 'MultiPolygon') { for (let i = 0; i < feature.geometry.coordinates.length; i++) { let hierarchy = this.getHierarchyPolygon(feature, i) array.push(hierarchy) } } else { let hierarchy = this.getHierarchyPolygon(feature) array.push(hierarchy) } hierarchys.push(array) }) this.hierarchys = [...hierarchys] if (!this.entity) { return } if (this._DialogObject || this._isdrag) { let k = 0 for (let i = 0; i < this.hierarchys.length; i++) { for (let m = 0; m < this.hierarchys[i].length; m++) { if (this.entity.values[k].polygon.hierarchy.isConstant) { this.entity.values[k].polygon.hierarchy = new Cesium.CallbackProperty(() => { let hierarchy = this.hierarchys[i][m] let holes = [] for (let n = 0; n < hierarchy.holes.length; n++) { holes.push({ positions: hierarchy.holes[n] }) } return { positions: hierarchy.positions, holes: holes } }, false) } k++ } } } else { let k = 0 for (let i = 0; i < this.hierarchys.length; i++) { for (let m = 0; m < this.hierarchys[i].length; m++) { // if (!this.entity.values[k].polygon.hierarchy.isConstant) { this.entity.values[k].polygon.hierarchy = new Cesium.CallbackProperty(() => { let hierarchy = this.hierarchys[i][m] let holes = [] for (let n = 0; n < hierarchy.holes.length; n++) { holes.push({ positions: hierarchy.holes[n] }) } return { positions: hierarchy.positions, holes: holes } }, !this.ismove) // } k++ } } } if (this.textObject && this.textObject.geojson) { let textHierarchys = [] let textGeojson = JSON.parse(JSON.stringify(this.textObject.geojson)) const recursion2 = (data) => { for (let i = 0; i < data.length; i++) { if (typeof data[i] === 'number') { if (this.textObject.flipe.x && i === 1) { data[i] = -data[i] } if (this.textObject.flipe.y && i === 0) { data[i] = -data[i] } } else { recursion2(data[i]) } } } for (let i = 0; i < textGeojson.features.length; i++) { recursion(textGeojson.features[i].geometry.coordinates) } textGeojson.features.forEach(item => { let array = [] let feature = JSON.parse(JSON.stringify(item)) this._updateGeojson(feature.geometry.coordinates, x, y) feature = turf.transformRotate(feature, this.angle, { pivot: [0, 0] }); let directionDistance = [] if (feature.geometry.type === 'MultiPolygon') { for (let i = 0; i < feature.geometry.coordinates.length; i++) { let array = [] for (let m = 0; m < feature.geometry.coordinates[i].length; m++) { let array2 = [] for (let n = 0; n < feature.geometry.coordinates[i][m].length; n++) { let point1 = turf.point([0, feature.geometry.coordinates[i][m][n][1]]) let point2 = turf.point([...feature.geometry.coordinates[i][m][n]]) let distance = turf.distance(point1, point2, { units: 'kilometers' }); let angle2 = turf.rhumbBearing(point1, point2); array2.push( { origin: feature.geometry.coordinates[i][m][n], distance: distance, angle: angle2 } ) } array.push(array2) } directionDistance.push(array) } } else { for (let i = 0; i < feature.geometry.coordinates.length; i++) { let array = [] for (let m = 0; m < feature.geometry.coordinates[i].length; m++) { let array2 = [] let point1 = turf.point([0, feature.geometry.coordinates[i][m][1]]) let point2 = turf.point([...feature.geometry.coordinates[i][m]]) let distance = turf.distance(point1, point2, { units: 'kilometers' }); let angle2 = turf.rhumbBearing(point1, point2); array.push({ origin: feature.geometry.coordinates[i][m], distance: distance, angle: angle2 }) } directionDistance.push(array) } } feature.properties.directionDistance = directionDistance // this.bbox = [...interimBbox] let w = 3.5 * this.scale.x let h = 3.5 * this.scale.y let wh = Math.sqrt(((w / 2) ** 2) + ((h / 2) ** 2)) let angle = Math.atan((w / 2) / (h / 2)) * (180 / Math.PI) if (isNaN(angle)) { angle = 0 } let controlPoints = [] controlPoints[0] = turf.destination(point, h / 2 * 1.5, 0 + this.options.angle, options).geometry.coordinates controlPoints[1] = turf.destination(point, wh, 180 + angle + this.options.angle, options).geometry.coordinates controlPoints[2] = turf.destination(point, h / 2, 180 + this.options.angle, options).geometry.coordinates controlPoints[3] = turf.destination(point, wh, 180 - angle + this.options.angle, options).geometry.coordinates controlPoints[4] = turf.destination(point, w / 2, 270 + this.options.angle, options).geometry.coordinates controlPoints[5] = [this.position.lng, this.position.lat] controlPoints[6] = turf.destination(point, w / 2, 90 + this.options.angle, options).geometry.coordinates controlPoints[7] = turf.destination(point, wh, 360 - angle + this.options.angle, options).geometry.coordinates controlPoints[8] = turf.destination(point, h / 2, 0 + this.options.angle, options).geometry.coordinates controlPoints[9] = turf.destination(point, wh, 0 + angle + this.options.angle, options).geometry.coordinates let points = turf.points(controlPoints); controlPoints = [] for (let i = 0; i < points.features.length; i++) { controlPoints.push(points.features[i].geometry.coordinates) } this.controlPoints = controlPoints if (feature.geometry.type === 'MultiPolygon') { for (let i = 0; i < feature.geometry.coordinates.length; i++) { let hierarchy = this.getHierarchyPolygon(feature, i) array.push(hierarchy) } } else { let hierarchy = this.getHierarchyPolygon(feature) array.push(hierarchy) } textHierarchys.push(array) }) this.textObject.hierarchys = [...textHierarchys] // if (this._DialogObject || this._isdrag) { // let k = 0 // for (let i = 0; i < this.textObject.hierarchys.length; i++) { // for (let m = 0; m < this.textObject.hierarchys[i].length; m++) { // if (this.entity.values[k].polygon.hierarchy.isConstant) { // this.entity.values[k].polygon.hierarchy = new Cesium.CallbackProperty(() => { // let hierarchy = this.textObject.hierarchys[i][m] // let holes = [] // for (let n = 0; n < hierarchy.holes.length; n++) { // holes.push({ // positions: hierarchy.holes[n] // }) // } // return { // positions: hierarchy.positions, // holes: holes // } // }, false) // } // k++ // } // } // } // else { // let k = 0 // for (let i = 0; i < this.textObject.hierarchys.length; i++) { // for (let m = 0; m < this.textObject.hierarchys[i].length; m++) { // // if (!this.entity.values[k].polygon.hierarchy.isConstant) { // this.entity.values[k].polygon.hierarchy = new Cesium.CallbackProperty(() => { // let hierarchy = this.textObject.hierarchys[i][m] // let holes = [] // for (let n = 0; n < hierarchy.holes.length; n++) { // holes.push({ // positions: hierarchy.holes[n] // }) // } // return { // positions: hierarchy.positions, // holes: holes // } // }, !this.ismove) // // } // k++ // } // } // } } } textPosPick() { let Draw = new DrawPoint(this.sdk) Draw.start(async (a, position) => { let point1 = turf.point([this.position.lng, this.position.lat]) let point2 = turf.point([position.lng, position.lat]) let distance = turf.distance(point1, point2, { units: 'kilometers' }); let angle = turf.rhumbBearing(point1, point2); this._textToCenter = { distance: distance, angle: angle } this.options.text.position = position if (this.text) { this.text.position = [position.lng, position.lat, position.alt] } else { GroundSvg.createText(this) } }) } load(callback) { if (this.#loaded) { callback(); } else { this.#loadEvent = callback } } async remove() { this._worker.onmessage = (event) => {} await this.sdk.removeIncetance(this.options.id) if (!this.entity) { return } this.drag(false) if(!this.sdk || !this.sdk.viewer) { return } this.sdk.viewer.entities.remove(this.entity) this.text && this.text.remove() for (let i = this.entity.values.length; i >= 0; i--) { this.sdk.viewer.entities.remove(this.entity.values[i]) } if (this._DialogObject && !this._DialogObject.isDestroy) { this._DialogObject.close() this._DialogObject = null } await syncData(this.sdk, this.options.id) } _addLink() { if ( this._DialogObject._element.content.getElementsByClassName('link_add')[0] .value ) { this.options.attribute.link.content.push({ name: '链接', url: this._DialogObject._element.content.getElementsByClassName( 'link_add' )[0].value }) this._DialogObject._element.content.getElementsByClassName( 'link_add' )[0].value = '' this.attributeLink = this.options.attribute.link.content } else { this.Dialog.clickAddLink && this.Dialog.clickAddLink() } } addAttributeLink(link) { this.options.attribute.link.content.push({ name: '链接', url: link }) this.attributeLink = this.options.attribute.link.content } /** * 打开富文本框 */ openRichTextEditor(e) { // var ue = UE.getEditor('app'); richText.open( this.options.id, this.options.name, this.options.richTextContent ) richText.primaryCallBack = content => { this.options.richTextContent = content } } setPosition(v) { if (v) { this.ismove = true let position = {} position.lng = v.position.lng position.lat = v.position.lat this.position = position } else { this.ismove = false } this._update() } async flyTo(options = {}) { if (this._error) { return } setActiveViewer(0) closeRotateAround(this.sdk) closeViewFollow(this.sdk) if (this.options.customView && this.options.customView.relativePosition && this.options.customView.orientation) { let orientation = { heading: Cesium.Math.toRadians(this.options.customView.orientation.heading || 0.0), pitch: Cesium.Math.toRadians(this.options.customView.orientation.pitch || -60.0), roll: Cesium.Math.toRadians(this.options.customView.orientation.roll || 0.0) } let lng = this.options.customView.relativePosition.lng let lat = this.options.customView.relativePosition.lat let alt = this.options.customView.relativePosition.alt let destination = Cesium.Cartesian3.fromDegrees(lng, lat, alt) let position = { ...this.options.position } // 如果没有高度值,则获取紧贴高度计算 if (!position.hasOwnProperty('alt')) { position.alt = await this.getClampToHeight(position) } lng = this.options.customView.relativePosition.lng + position.lng lat = this.options.customView.relativePosition.lat + position.lat alt = this.options.customView.relativePosition.alt + position.alt destination = Cesium.Cartesian3.fromDegrees(lng, lat, alt) this.sdk.viewer.camera.flyTo({ destination: destination, orientation: orientation }) } else { let array = [] for (let i = 0; i < this.controlPoints.length; i++) { let height = await this.getClampToHeight({lng: this.controlPoints[i][0], lat: this.controlPoints[i][1]}) let cartesian = Cesium.Cartesian3.fromDegrees(this.controlPoints[i][0], this.controlPoints[i][1], height) array.push(cartesian.x, cartesian.y, cartesian.z) } let BoundingSphere = Cesium.BoundingSphere.fromVertices(array) this.sdk.viewer.camera.flyToBoundingSphere(BoundingSphere, { offset: options.orientation || { heading: Cesium.Math.toRadians(0.0), pitch: Cesium.Math.toRadians(-60.0), roll: Cesium.Math.toRadians(0.0) } }) } } } export default GroundSvg