二三维增加单独展示在二维或者三维的功能,贴地图片增加设置锚点功能

This commit is contained in:
zh
2025-08-09 18:20:02 +08:00
parent 656a21a6dd
commit e38dd4d029
17 changed files with 510 additions and 120 deletions

View File

@ -8,6 +8,7 @@ function html() {
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col">
<button class="anchor btn" @click="setAnchorPoint">调整锚点</button>
</div>
</div>
</div>
@ -27,9 +28,9 @@ function html() {
<div class="row">
<div class="col">
<span class="label">调整大小</span>
<input type="range" max="99999" min="0" step="0.1" @model="scale">
<input type="range" max="40000" min="0" step="0.1" @model="scale">
<div class="input-number input-number-unit-1" style="width: 100px;flex: 0 0 100px;margin-left: 10px;">
<input class="input" type="number" title="" min="0" max="99999" step="0.1" @model="scale">
<input class="input" type="number" title="" min="0" max="40000" step="0.1" @model="scale">
<span class="arrow"></span>
</div>
</div>

View File

@ -7,7 +7,7 @@ import MouseEvent from '../../../Event/index'
import { syncData } from '../../../Global/MultiViewportMode'
import MouseTip from '../../../MouseTip'
import { setSplitDirection, syncSplitData, setActiveId } from '../../../Global/SplitScreen'
import { setActiveViewer, closeRotateAround, closeViewFollow} from '../../../Global/global'
import { setActiveViewer, closeRotateAround, closeViewFollow } from '../../../Global/global'
class GroundImage extends Base {
/**
@ -36,6 +36,7 @@ class GroundImage extends Base {
this.options.angle = options.angle || 0
this.options.scale = (options.scale || options.scale === 0) ? options.scale : 1
this.options.positions = options.positions
this.options.offset = { x: 0.5, y: 0.5 }
this.options.flipe = options.flipe || {}
this.options.flipe.x = this.options.flipe.x || false
@ -56,6 +57,13 @@ class GroundImage extends Base {
this.create()
}
get offset() {
return this.options.offset
}
set offset(v) {
this.options.offset = v
}
get angle() {
return this.options.angle
}
@ -87,8 +95,9 @@ class GroundImage extends Base {
if (!this.entity) {
return
}
const img = new Image();
img.src = this.options.url;
img.src = this.replaceHost(this.options.url, this.options.host);
img.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
@ -111,6 +120,10 @@ class GroundImage extends Base {
image: canvas,
transparent: true
}))
// this.offset = {
// x: Math.abs(this.offset.x - 1),
// y: this.offset.y,
// }
}
} else {
console.error("参数必须为boolean")
@ -125,8 +138,9 @@ class GroundImage extends Base {
if (!this.entity) {
return
}
const img = new Image();
img.src = this.options.url;
img.src = this.replaceHost(this.options.url, this.options.host);
img.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
@ -149,6 +163,10 @@ class GroundImage extends Base {
image: canvas,
transparent: true
})
// this.offset = {
// x: this.offset.x,
// y: Math.abs(this.offset.y - 1),
// }
}
} else {
console.error("参数必须为boolean")
@ -163,7 +181,7 @@ class GroundImage extends Base {
// this.options.positions.lng + 0.05, this.options.positions.lat + 0.05,
// this.options.positions.lng - 0.05, this.options.positions.lat + 0.05,
// ]
let response = await fetch(this.options.url, {
let response = await fetch(this.replaceHost(this.options.url, this.options.host), {
method: 'get',
headers: {
'Content-Type': 'application/json',
@ -174,7 +192,7 @@ class GroundImage extends Base {
// let arrayBuffer = await data.arrayBuffer()
// const str = String.fromCharCode(...new Uint8Array(arrayBuffer));
const img = new Image();
img.src = this.options.url;
img.src = this.replaceHost(this.options.url, this.options.host);
img.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
@ -199,11 +217,27 @@ class GroundImage extends Base {
rectangle: {
coordinates: new Cesium.CallbackProperty(() => {
let gap = Math.abs(Math.cos(Math.PI / 180 * this.options.positions.lat)) * (0.0001 * this.options.scale)
let offset = {
x: this.flipeY ? Math.abs(this.options.offset.x - 1) : this.options.offset.x,
y: this.flipeX ? Math.abs(this.options.offset.y - 1) : this.options.offset.y,
}
offset = {
lng: offset.x * ((0.0001 * this.options.scale) * 2),
lat: Math.abs(offset.y-1) * (gap * 2)
}
let fromDegreesArray = [
this.options.positions.lng - (0.0001 * this.options.scale), this.options.positions.lat - gap,
// this.options.positions.lng + 0.05, this.options.positions.lat - 0.05,
this.options.positions.lng + (0.0001 * this.options.scale), this.options.positions.lat + gap,
// this.options.positions.lng - 0.05, this.options.positions.lat + 0.05,
this.options.positions.lng - offset.lng, this.options.positions.lat - offset.lat,
(this.options.positions.lng - offset.lng) + ((0.0001 * this.options.scale) * 2), (this.options.positions.lat - offset.lat) + (gap * 2),
// this.options.positions.lng - (0.0001 * this.options.scale), this.options.positions.lat - gap,
// // this.options.positions.lng + 0.05, this.options.positions.lat - 0.05,
// this.options.positions.lng + (0.0001 * this.options.scale), this.options.positions.lat + gap,
// // this.options.positions.lng - 0.05, this.options.positions.lat + 0.05,
]
return Cesium.Rectangle.fromDegrees(...fromDegreesArray)
@ -224,8 +258,8 @@ class GroundImage extends Base {
this.entity.rectangle.height = 0
}
syncData(this.sdk, this.options.id)
if(this.options.show) {
if (this.options.show) {
setSplitDirection(0, this.options.id)
}
}
@ -253,6 +287,10 @@ class GroundImage extends Base {
this._DialogObject = null
}
if (state) {
let anchorSetDialogObject
let canvas
let point
let billboardAnchorPosition
this._DialogObject = await new Dialog(this.sdk, this.originalOptions, {
title: '军标属性', left: '180px', top: '100px',
confirmCallBack: (options) => {
@ -280,6 +318,9 @@ class GroundImage extends Base {
// show: true,
// });
this.positionEditing = false
if (anchorSetDialogObject && anchorSetDialogObject.close) {
anchorSetDialogObject.close()
}
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
},
showCallBack: (show) => {
@ -315,6 +356,7 @@ class GroundImage extends Base {
]
}, true)
this._DialogObject._element.body.className = this._DialogObject._element.body.className + ' ground-image'
let contentElm = document.createElement('div');
contentElm.innerHTML = html()
this._DialogObject.contentAppChild(contentElm)
@ -322,6 +364,114 @@ class GroundImage extends Base {
this._EventBinding.on(this, all_elm)
this._elms = this._EventBinding.element
let anchorBtn = contentElm.getElementsByClassName('anchor')[0]
anchorBtn.addEventListener('click', async () => {
if (anchorSetDialogObject && anchorSetDialogObject.close) {
anchorSetDialogObject.close()
}
document.body.addEventListener('mouseup', mouseupEvent)
let DialogClientRect = _this._DialogObject._element.body.getBoundingClientRect()
let _DialogObject = await new Dialog(this.sdk, this.originalOptions, {
title: '锚点设置', left: (DialogClientRect.left + 80) + 'px', top: (DialogClientRect.top + 200) + 'px',
confirmCallBack: (options) => {
_this.offset = { x: billboardAnchorPosition.x, y: billboardAnchorPosition.y }
_DialogObject.close()
},
closeCallBack: () => {
document.body.removeEventListener('mouseup', mouseupEvent)
},
}, false)
anchorSetDialogObject = _DialogObject
_DialogObject._element.body.className = _DialogObject._element.body.className + ' anchor-point'
let contentElm = document.createElement('div');
let image = new Image()
image.src = this.replaceHost(this.options.url, this.options.host)
image.onload = function () {
let ratio = image.width / image.height
canvas = document.createElement('canvas')
let width = 150
let height = 150 / ratio
const ctx = canvas.getContext('2d', { willReadFrequently: true })
canvas.width = width
canvas.height = height;
canvas.style.display = 'block';
ctx.drawImage(image, 0, 0, width, height)
contentElm.appendChild(canvas)
_DialogObject.contentAppChild(contentElm)
point = document.createElement('span')
point.className = 'point'
contentElm.appendChild(point)
billboardAnchorPosition = { x: _this.offset.x, y: _this.offset.y }
point.style.top = `calc(${Number(billboardAnchorPosition.y) * 100}% - 6px)`
point.style.left = `calc(${Number(billboardAnchorPosition.x) * 100}% - 6px)`
canvas.addEventListener('click', (e) => {
let x = e.offsetX
let y = e.offsetY
let anchor = { x: Number((x / canvas.width).toFixed(2)), y: Number((y / canvas.height).toFixed(2)) }
if (anchor.x < 0) {
anchor.x = 0
}
if (anchor.x > 1) {
anchor.x = 1
}
if (anchor.y < 0) {
anchor.y = 0
}
if (anchor.y > 1) {
anchor.y = 1
}
billboardAnchorPosition = { x: anchor.x, y: anchor.y }
point.style.top = `calc(${billboardAnchorPosition.y * 100}% - 5px)`
point.style.left = `calc(${billboardAnchorPosition.x * 100}% - 5px)`
})
point.addEventListener('mousedown', (e) => {
_DialogObject._element.body.addEventListener('mousemove', mousemoveEvent)
})
}
})
function mousemoveEvent(e) {
getDialogBodyElm(e.target)
function getDialogBodyElm(elm) {
if (!elm) {
return
}
else if (elm === anchorSetDialogObject._element.body) {
let x = e.x - elm.getBoundingClientRect().left
let y = e.y - elm.getBoundingClientRect().top
let anchor = { x: Number(((x - 42) / canvas.width).toFixed(2)), y: Number(((y - 71) / canvas.height).toFixed(2)) }
if (anchor.x < 0) {
anchor.x = 0
}
if (anchor.x > 1) {
anchor.x = 1
}
if (anchor.y < 0) {
anchor.y = 0
}
if (anchor.y > 1) {
anchor.y = 1
}
billboardAnchorPosition = { x: anchor.x, y: anchor.y }
point.style.top = `calc(${billboardAnchorPosition.y * 100}% - 5px)`
point.style.left = `calc(${billboardAnchorPosition.x * 100}% - 5px)`
}
else {
getDialogBodyElm(elm.offsetParent)
}
}
}
function mouseupEvent() {
if (anchorSetDialogObject) {
anchorSetDialogObject._element.body.removeEventListener('mousemove', mousemoveEvent)
}
}
} else {
if (this._DialogObject && this._DialogObject.remove) {
this._DialogObject.remove()
@ -428,7 +578,7 @@ class GroundImage extends Base {
async flyTo(options = {}) {
setActiveViewer(0)
closeRotateAround(this.sdk)
closeViewFollow(this.sdk)
closeViewFollow(this.sdk)
if (this.options.customView && this.options.customView.relativePosition && this.options.customView.orientation) {
let orientation = {