From b2d307b308cf2b43ab79ad8afbeb9d7dcea21819 Mon Sep 17 00:00:00 2001 From: zh <972939975@qq.com> Date: Thu, 21 Aug 2025 16:34:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B9=BF=E5=91=8A=E7=89=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Obj/Base/BillboardObject/index.js | 370 +++++++++++++++++++++++++- src/Obj/Element/cy_html_tabs.js | 15 +- 2 files changed, 380 insertions(+), 5 deletions(-) diff --git a/src/Obj/Base/BillboardObject/index.js b/src/Obj/Base/BillboardObject/index.js index 3bd6bfc..b637a4f 100644 --- a/src/Obj/Base/BillboardObject/index.js +++ b/src/Obj/Base/BillboardObject/index.js @@ -40,6 +40,10 @@ import { import { getGoodsList } from '../../../Tools/getGoodsList' class BillboardObject extends Base { + #_postRenderEvent = null + #_destroyMouseEvent = null + + /** * @constructor * @description 创建点标注 @@ -145,11 +149,18 @@ class BillboardObject extends Base { this.options.attribute.goods.content || [] this.options.attributeType = options.attributeType || 'richText' this.options.coordinate = options.coordinate || '' + this.options.attributeBoxState = options.attributeBoxState || false this.operate = {} this._elms = {} this.previous = { positions: { ...this.options.positions } } + this.options.attributePos = options.attributePos || { + x: 60, + y: 60, + width: 200, + height: 120 + } this.entity this._proj = this.sdk.proj @@ -182,7 +193,107 @@ class BillboardObject extends Base { + this.#_destroyMouseEvent = () => { + this.attributeElm && (this.attributeElm.style.pointerEvents = 'unset') + this.sdk.viewer._element.onmousemove = null + document.removeEventListener('mouseup', this.#_destroyMouseEvent) + document.removeEventListener('mouseleave', this.#_destroyMouseEvent) + } + this.#_postRenderEvent = () => { + let siteInfoPosition = Cesium.Cartesian3.fromDegrees( + this.options.positions.lng, + this.options.positions.lat + ) + if (this.attributeElm && this.entity) { + let winpos = this.sdk.viewer.scene.cartesianToCanvasCoordinates( + siteInfoPosition + ) + let pixelOffset = this.entity.label.pixelOffset.getValue() + if (winpos) { + let scale = getCurrentBillboardScale(this.entity, this.sdk.viewer.scene) + let height = ((this.entity.billboard.height.getValue() * (this.options.billboard.scale || 0)) + this.options.label.fontSize) * (1 - (scale * scale)) + let flag = false + let lineElm = this.attributeElm.getElementsByClassName('billboard-attribute-box-line')[0] + let leftTopElm = this.attributeElm.getElementsByClassName('left-top')[0] + let rightTopElm = this.attributeElm.getElementsByClassName('right-top')[0] + this.attributeElm.style.left = (winpos.x + this.options.attributePos.x).toFixed(0) + 'px' + this.attributeElm.style.top = (winpos.y + pixelOffset.y - (this.options.label.show ? (this.options.label.fontSize / 2) : -(this.options.label.fontSize / 2)) - this.attributeElm.offsetHeight - this.options.attributePos.y + height).toFixed(0) + 'px' + this.attributeElm.style.width = this.options.attributePos.width + 'px' + this.attributeElm.style.height = this.options.attributePos.height + 'px' + if (this.options.attributePos.x < -this.options.attributePos.width / 2) { + flag = true + lineElm.style.left = 'unset' + lineElm.style.right = '0' + leftTopElm.style.display = 'block' + rightTopElm.style.display = 'none' + } + else { + lineElm.style.left = '0' + lineElm.style.right = 'unset' + leftTopElm.style.display = 'none' + rightTopElm.style.display = 'block' + } + + let lineLength + let lineAngleRad + let lineAngle + let x + let y + if (flag) { + x = this.attributeElm.offsetWidth + this.options.attributePos.x + y = this.options.attributePos.y ? this.options.attributePos.y : 0 + } + else { + x = this.options.attributePos.x + y = this.options.attributePos.y ? this.options.attributePos.y : 0 + } + lineLength = Math.sqrt((x * x) + (y * y)).toFixed(2); + lineAngleRad = Math.atan(x / y); + lineAngle = parseFloat((lineAngleRad * 180 / Math.PI).toFixed(2)); + if (this.options.attributePos.y < 0) { + lineAngle = lineAngle + 180 + } + // if(this.options.attributePos.y<-this.options.attributePos.height/2) { + // lineElm.style.bottom = 'unset' + // lineElm.style.top = '0' + // } + // else { + // lineElm.style.bottom = -lineLength + 'px' + // lineElm.style.top = 'unset' + // } + lineElm.style.height = lineLength + 'px' + lineElm.style.transform = 'rotate(' + lineAngle + 'deg)' + } + } + } + + function getCurrentBillboardScale(entity, scene) { + // 获取相机到Billboard的距离 + const distance = Cesium.Cartesian3.distance( + scene.camera.positionWC, + entity.position.getValue() + ); + // 获取缩放距离配置 + const scaleByDistance = entity.billboard.scaleByDistance ? entity.billboard.scaleByDistance.getValue() : undefined; + + if (!scaleByDistance) { + // 如果没有设置距离缩放,则使用基础缩放值 + return 1.0; + } + + // 解析缩放距离参数 [near, nearScale, far, farScale] + const { near, nearValue, far, farValue } = scaleByDistance; + if (distance <= near) { + return nearValue; + } else if (distance >= far) { + return farValue; + } else { + // 计算中间距离的缩放值(线性插值) + const t = (distance - near) / (far - near); + return Cesium.Math.lerp(nearValue, farValue, t); + } + } this.sdk.addIncetance(this.options.id, this) @@ -243,6 +354,7 @@ class BillboardObject extends Base { that.entity.billboard.imgHeight = 0 that.entity.billboard.image = canvas addCluster(that.sdk, that.entity) + that.attributeBoxState && (that.attributeBoxState = true) } return } @@ -267,6 +379,7 @@ class BillboardObject extends Base { return img }, false) addCluster(that.sdk, that.entity) + that.attributeBoxState && (that.attributeBoxState = true) } }) } @@ -298,6 +411,7 @@ class BillboardObject extends Base { that.entity.billboard.imgHeight = height that.entity.billboard.image = canvas addCluster(that.sdk, that.entity) + that.attributeBoxState && (that.attributeBoxState = true) } } image.onerror = function (err) { @@ -309,6 +423,7 @@ class BillboardObject extends Base { that.entity.billboard.imgHeight = 0 that.entity.billboard.image = canvas addCluster(that.sdk, that.entity) + that.attributeBoxState && (that.attributeBoxState = true) } }; } @@ -465,15 +580,36 @@ class BillboardObject extends Base { return this.options.show } set show(v) { - if(!this.isShowView) { + if (!this.isShowView) { this.options.show = v this.originalOptions.show = v } - if(!this.showView || this.showView == 3) { + if (!this.showView || this.showView == 3) { this.entity && (this.entity.show = this.options.show) + if (this.attributeBoxState && this.options.show) { + this.attributeBoxState = this.options.show + } + else { + // 关闭属性框 + document.addEventListener('mouseup', this.#_destroyMouseEvent); + document.addEventListener('mouseleave', this.#_destroyMouseEvent); + if (this.attributeElm) { + this.sdk.viewer._element.removeChild(this.attributeElm) + this.attributeElm = null + } + this.sdk.viewer.scene.postRender.removeEventListener(this.#_postRenderEvent) + } } else { this.entity && (this.entity.show = false) + // 关闭属性框 + document.addEventListener('mouseup', this.#_destroyMouseEvent); + document.addEventListener('mouseleave', this.#_destroyMouseEvent); + if (this.attributeElm) { + this.sdk.viewer._element.removeChild(this.attributeElm) + this.attributeElm = null + } + this.sdk.viewer.scene.postRender.removeEventListener(this.#_postRenderEvent) } syncData(this.sdk, this.options.id) syncSplitData(this.sdk, this.options.id) @@ -1716,6 +1852,22 @@ class BillboardObject extends Base { this.cameraSelect && this.cameraSelect() this.ISCSelect && this.ISCSelect() this.goodsSelect && this.goodsSelect() + + let col = document.createElement('div') + col.className = 'col' + col.style.flex = '0 0 80px' + col.innerHTML = ` + 属性框 + + ` + + let row = this._DialogObject._element.content.getElementsByClassName('attribute')[0].getElementsByClassName('row')[0] + row.appendChild(col) + let boxSwitch = col.getElementsByClassName('btn-switch')[0] + boxSwitch.checked = this.attributeBoxState + boxSwitch.addEventListener('change', (e) => { + this.attributeBoxState = boxSwitch.checked + }) let tagData = this.attributeSelect let attributeElm = this._DialogObject._element.content.getElementsByClassName( 'attribute-select-box' @@ -2736,6 +2888,220 @@ class BillboardObject extends Base { (this.originalOptions.customView = this.options.customView) } } + + get attributeBoxState() { + return this.options.attributeBoxState + } + + set attributeBoxState(state) { + state = state ? true : false + this.options.attributeBoxState = state + document.addEventListener('mouseup', this.#_destroyMouseEvent); + document.addEventListener('mouseleave', this.#_destroyMouseEvent); + if (this.attributeElm) { + this.sdk.viewer._element.removeChild(this.attributeElm) + this.attributeElm = null + } + this.sdk.viewer.scene.postRender.removeEventListener(this.#_postRenderEvent) + if (state && this.sdk && this.sdk.viewer && this.sdk.viewer._element && this.show) { + let attributeElm = document.createElement('div') + this.attributeElm = attributeElm + attributeElm.className = 'billboard-attribute-box' + attributeElm.style.top = '0px' + attributeElm.style.left = '0px' + attributeElm.style.width = 0 + attributeElm.style.height = 0 + // attributeElm.innerHTML = this.options.richTextContent + this.sdk.viewer._element.appendChild(attributeElm) + let linkHtml = '' + let goodsHtml = '' + let richTextHtml = '' + for (let i = 0; i < this.options.attribute.link.content.length; i++) { + linkHtml += `` + } + if (this.options.attribute.goods && this.options.attribute.goods.content && this.options.attribute.goods.content.length > 0) { + goodsHtml += ` +
+
+
+
序号
+
名称
+
数量
+
+
+
+ ` + for (let i = 0; i < this.options.attribute.goods.content.length; i++) { + goodsHtml += `
+
${i + 1}
+
${this.options.attribute.goods.content[i].name}
+
${this.options.attribute.goods.content[i].cnt}
+
` + } + goodsHtml += `
` + } + if (this.options.richTextContent) { + richTextHtml = ` + ${this.options.richTextContent} + ` + } + + let boxHtml = ` + + + ` + + if (!linkHtml && !goodsHtml && !richTextHtml) { + boxHtml = boxHtml + '

暂无属性信息

' + } + else { + boxHtml = boxHtml + ` + + ${richTextHtml} + ${goodsHtml} + ${linkHtml} + +
` + } + + attributeElm.innerHTML = boxHtml + + if (attributeElm.getElementsByClassName('tabs')[0]) { + let tabsElm = new cy_tabs(attributeElm.getElementsByClassName('tabs')[0], undefined, this.sdk) + } + + let imgElm = attributeElm.getElementsByTagName('img') + for (let i = 0; i < imgElm.length; i++) { + if (!imgElm[i].style.width) { + imgElm[i].style.width = '100%' + } + } + + this.sdk.viewer.scene.postRender.addEventListener(this.#_postRenderEvent) + + let leftTopElm = attributeElm.getElementsByClassName('left-top')[0] + let rightTopElm = attributeElm.getElementsByClassName('right-top')[0] + let leftOnmousedown = (e) => { + console.log(1111111111) + if (this.options.attributePos.width < 200) { + this.options.attributePos.width = 200 + } + if (this.options.attributePos.height < 120) { + this.options.attributePos.height = 120 + } + let x = e.x + let y = e.y + let width = this.options.attributePos.width + let height = this.options.attributePos.height + let positionx = this.options.attributePos.x + this.sdk.viewer._element.onmousemove = (e2) => { + this.options.attributePos.width = width + (x - e2.x) + this.options.attributePos.height = height + (y - e2.y) + if (this.options.attributePos.width < 200) { + this.options.attributePos.width = 200 + } + else { + this.options.attributePos.x = positionx - (x - e2.x) + } + if (this.options.attributePos.height < 120) { + this.options.attributePos.height = 120 + } + // this.options.attributePos.y = positiony + (y - e2.y) + } + document.addEventListener('mouseup', this.#_destroyMouseEvent); + document.addEventListener('mouseleave', this.#_destroyMouseEvent); + } + let rightOnmousedown = (e) => { + let x = e.x + let y = e.y + if (this.options.attributePos.width < 200) { + this.options.attributePos.width = 200 + } + if (this.options.attributePos.height < 120) { + this.options.attributePos.height = 120 + } + let width = this.options.attributePos.width + let height = this.options.attributePos.height + this.sdk.viewer._element.onmousemove = (e2) => { + this.options.attributePos.width = width + (e2.x - x) + this.options.attributePos.height = height + (y - e2.y) + } + document.addEventListener('mouseup', this.#_destroyMouseEvent); + document.addEventListener('mouseleave', this.#_destroyMouseEvent); + } + // leftTopElm.onmousedown = (e) => { + // console.log(1111111111) + // if (this.options.attributePos.width < 200) { + // this.options.attributePos.width = 200 + // } + // if (this.options.attributePos.height < 120) { + // this.options.attributePos.height = 120 + // } + // let x = e.x + // let y = e.y + // let width = this.options.attributePos.width + // let height = this.options.attributePos.height + // let positionx = this.options.attributePos.x + // this.sdk.viewer._element.onmousemove = (e2) => { + // this.options.attributePos.width = width + (x - e2.x) + // this.options.attributePos.height = height + (y - e2.y) + // if (this.options.attributePos.width < 200) { + // this.options.attributePos.width = 200 + // } + // else { + // this.options.attributePos.x = positionx - (x - e2.x) + // } + // if (this.options.attributePos.height < 120) { + // this.options.attributePos.height = 120 + // } + // // this.options.attributePos.y = positiony + (y - e2.y) + // } + // document.addEventListener('mouseup', this.#_destroyMouseEvent); + // document.addEventListener('mouseleave', this.#_destroyMouseEvent); + // } + // rightTopElm.onmousedown = (e) => { + // let x = e.x + // let y = e.y + // if (this.options.attributePos.width < 200) { + // this.options.attributePos.width = 200 + // } + // if (this.options.attributePos.height < 120) { + // this.options.attributePos.height = 120 + // } + // let width = this.options.attributePos.width + // let height = this.options.attributePos.height + // this.sdk.viewer._element.onmousemove = (e2) => { + // this.options.attributePos.width = width + (e2.x - x) + // this.options.attributePos.height = height + (y - e2.y) + // } + // document.addEventListener('mouseup', this.#_destroyMouseEvent); + // document.addEventListener('mouseleave', this.#_destroyMouseEvent); + // } + + attributeElm.onmousedown = (e) => { + attributeElm.style.pointerEvents = 'none' + if (e.target.className.indexOf('left-top') != -1) { + leftOnmousedown(e) + } + else if (e.target.className.indexOf('right-top') != -1) { + rightOnmousedown(e) + } + else { + let x = e.x + let y = e.y + let oldX = this.options.attributePos.x + let oldXY = this.options.attributePos.y + let height = this.options.attributePos.height + this.sdk.viewer._element.onmousemove = (e2) => { + this.options.attributePos.x = oldX + (e2.x - x) + this.options.attributePos.y = oldXY - (e2.y - y) + } + document.addEventListener('mouseup', this.#_destroyMouseEvent); + document.addEventListener('mouseleave', this.#_destroyMouseEvent); + } + } + } + } } export default BillboardObject diff --git a/src/Obj/Element/cy_html_tabs.js b/src/Obj/Element/cy_html_tabs.js index 1270e29..464c37b 100644 --- a/src/Obj/Element/cy_html_tabs.js +++ b/src/Obj/Element/cy_html_tabs.js @@ -1,6 +1,13 @@ class cy_tabs { - constructor(id, clickTabCallBack, sdk) { - let elm = document.getElementById(id); + constructor(boxElm, clickTabCallBack, sdk) { + let elm + if(typeof boxElm === 'string') { + elm = document.getElementById(boxElm); + } + else { + elm = boxElm + } + // let elm = document.getElementById(id); let pane = elm.getElementsByTagName('DIV-cy-tab-pane') let tabTop = `
` @@ -37,7 +44,9 @@ tabContent = tabContent + `
` let BoxElm = document.createElement('div'); - BoxElm.setAttribute('id', id) + if(typeof boxElm === 'string') { + BoxElm.setAttribute('id', boxElm) + } BoxElm.setAttribute('class', 'DIV-cy-tabs') BoxElm.innerHTML = tabTop + tabContent elm.parentNode.insertBefore(BoxElm, elm);