This commit is contained in:
zh
2025-09-01 16:17:11 +08:00
parent d802602200
commit 6fa99df21c
1035 changed files with 377083 additions and 1 deletions

View File

@ -0,0 +1,93 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row" style="align-items: flex-start;">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col" style="flex: 0 0 60%;">
<div class="row">
<div class="col input-select-unit-box">
<span class="label" style="margin-right: 0px;">投影面积:</span>
<input class="input input-text" readonly="readonly" type="text" @model="area">
<div class="input-select-unit"></div>
</div>
</div>
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<DIV-cy-tabs id="assemble-object-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="空间信息">
<div class="row">
<div class="col height-mode-box">
<span class="label" style="flex: 0 0 56px;">高度模式</span>
<div class="height-mode"></div>
</div>
<div class="col">
<span class="label">Z值统一增加</span>
<div class="input-number input-number-unit-1 height-box">
<input class="input height" type="number" title="" min="-9999999" max="999999999">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
<button class="confirm height-confirm" style="margin-left: 5px;">确认</button>
</div>
</div>
<div class="row">
<div class="table spatial-info-table">
<div class="table-head">
<div class="tr">
<div class="th"></div>
<div class="th">经度X</div>
<div class="th">纬度Y</div>
<div class="th">高度Z</div>
</div>
</div>
<div class="table-body">
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="面风格">
<div class="row">
<div class="col">
<span class="label">面颜色</span>
<div class="color"></div>
</div>
<div class="col">
<span class="label">边线颜色</span>
<div class="lineColor"></div>
</div>
<div class="col">
<span class="label">边线宽度</span>
<div class="input-number input-number-unit-2" style="width: 80px;">
<input class="input" type="number" title="" min="0" max="99" @model="lineWidth">
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
</DIV-cy-tabs>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,115 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row" style="align-items: flex-start;">
<div class="col">
<span class="label" style="flex: 0 0 56px;">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col" style="flex: 0 0 60%;">
<div class="row">
<div class="col input-select-unit-box">
<span class="label" style="margin-right: 0px;">投影面积:</span>
<input class="input input-text" readonly="readonly" type="text" @model="area">
<div class="input-select-unit"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">动画时长</span>
<div class="input-number input-number-unit-3">
<input class="input blur" type="number" title="" min="500" max="9999999" @model="spreadTime">
<span class="unit">ms</span>
<span class="arrow"></span>
</div>
</div>
<div class="col" style="flex: 0 0 60%;">
<div class="row">
<div class="col">
<span class="label">动画</span>
<input class="btn-switch" type="checkbox" @model="spreadState">
</div>
<div class="col">
<span class="label">动画重复</span>
<input class="btn-switch" type="checkbox" @model="loop">
</div>
</div>
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<DIV-cy-tabs id="attack-arrow-object-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="空间信息">
<div class="row">
<div class="col height-mode-box">
<span class="label" style="flex: 0 0 56px;">高度模式</span>
<div class="height-mode"></div>
</div>
<div class="col">
<span class="label">Z值统一增加</span>
<div class="input-number input-number-unit-1 height-box">
<input class="input height" type="number" title="" min="-9999999" max="999999999">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
<button class="confirm height-confirm" style="margin-left: 5px;">确认</button>
</div>
</div>
<div class="row">
<div class="table spatial-info-table">
<div class="table-head">
<div class="tr">
<div class="th"></div>
<div class="th">经度X</div>
<div class="th">纬度Y</div>
<div class="th">高度Z</div>
</div>
</div>
<div class="table-body">
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="面风格">
<div class="row">
<div class="col">
<span class="label">面颜色</span>
<div class="color"></div>
</div>
<div class="col">
<span class="label">边线颜色</span>
<div class="lineColor"></div>
</div>
<div class="col">
<span class="label">边线宽度</span>
<div class="input-number input-number-unit-2" style="width: 80px;">
<input class="input" type="number" title="" min="0" max="99" @model="lineWidth">
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
</DIV-cy-tabs>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
/**
* @name: index
* @author: Administrator
* @date: 2023-11-20 19:00
* @descriptionindex
* @update: 2023-11-20 19:00
*/
import BaseLayer from "../index";
import { setSplitDirection, setActiveId } from '../../../../../Global/SplitScreen'
class ArcgisLayer extends BaseLayer {
constructor(sdk, options = {}) {
super(sdk, options);
}
get type() {
return "layer"
}
async createArcGis(url) {
let imageryProvider
if (Number(Cesium.VERSION.split('.')[1]) >= 107) {
imageryProvider = await Cesium.ArcGisMapServerImageryProvider.fromUrl(url);
}
else {
imageryProvider = new Cesium.ArcGisMapServerImageryProvider({
url
});
}
if (this.options.hasOwnProperty("layer_index")) {
this.entity = this.sdk.viewer.imageryLayers.addImageryProvider(imageryProvider, this.options.layer_index)
} else {
this.entity = this.sdk.viewer.imageryLayers.addImageryProvider(imageryProvider,)
}
this.entity._id = this.options.id
for (let i = 0; i < this.sdk.viewer.imageryLayers._layers.length; i++) {
if (this.sdk.viewer.imageryLayers._layers[i]._imageryProvider && this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type && (this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'flw' || this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'jww')) {
let layer = this.sdk.viewer.imageryLayers._layers[i]
this.sdk.viewer.imageryLayers.raiseToTop(layer)
}
}
this.show = this.options.show
this.alpha = this.options.alpha
this.brightness = this.options.brightness
if(this.options.show) {
setSplitDirection(0, this.options.id)
}
}
}
class ArcgisWXImagery extends ArcgisLayer {
constructor(sdk, options) {
super(sdk, options);
this.createArcGis("https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer")
}
}
class ArcgisBLUEImagery extends ArcgisLayer {
constructor(sdk, options) {
super(sdk, options);
this.createArcGis("https://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer")
}
}
class ArcgisLWImagery extends ArcgisLayer {
constructor(sdk, options) {
super(sdk, options);
this.createArcGis("https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer")
}
}
export {ArcgisWXImagery, ArcgisBLUEImagery, ArcgisLWImagery}

View File

@ -0,0 +1,72 @@
import BaseLayer from "../index";
import { setSplitDirection, setActiveId } from '../../../../../Global/SplitScreen'
/**
* @name: index
* @author: Administrator
* @date: 2023-11-20 19:18
* @descriptionindex
* @update: 2023-11-20 19:18
*/
class GdImagery extends BaseLayer {
constructor(sdk, options = {}) {
super(sdk, options);
}
get type() {
return "layer"
}
createGD(url) {
let gdLayer = new Cesium.UrlTemplateImageryProvider({
url,
minimumLevel: 3,
maximumLevel: 18,
tilingScheme: this.amapMercatorTilingScheme()
})
if (this.options.hasOwnProperty("layer_index")) {
this.entity = this.sdk.viewer.imageryLayers.addImageryProvider(gdLayer, this.options.layer_index)
} else {
this.entity = this.sdk.viewer.imageryLayers.addImageryProvider(gdLayer,)
}
this.entity._id = this.options.id
for (let i = 0; i < this.sdk.viewer.imageryLayers._layers.length; i++) {
if (this.sdk.viewer.imageryLayers._layers[i]._imageryProvider && this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type && (this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'flw' || this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'jww')) {
let layer = this.sdk.viewer.imageryLayers._layers[i]
this.sdk.viewer.imageryLayers.raiseToTop(layer)
}
}
this.show = this.options.show
this.alpha = this.options.alpha
this.brightness = this.options.brightness
if(this.options.show) {
setSplitDirection(0, this.options.id)
}
}
}
class GDLWImagery extends GdImagery {
constructor(earth, options = {}) {
super(earth, options);
this.createGD("https://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8")
}
}
class GDWXImagery extends GdImagery {
constructor(earth, options = {}) {
super(earth, options);
this.createGD("https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}")
}
}
class GDSLImagery extends GdImagery {
constructor(earth, options = {}) {
super(earth, options);
this.createGD("https://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}")
}
}
export {GDLWImagery, GDWXImagery, GDSLImagery}

View File

@ -0,0 +1,147 @@
/**
* @name: index
* @author: Administrator
* @date: 2023-11-20 15:51
* @descriptionindex
* @update: 2023-11-20 15:51
*/
import { getHost } from "../../../../../on";
import { syncData } from '../../../../../Global/MultiViewportMode'
import BaseLayer from "../index";
import { setSplitDirection, setActiveId } from '../../../../../Global/SplitScreen'
class Layer extends BaseLayer {
constructor(sdk, options = {}) {
super(sdk, options)
this.object = {}
this.options.host = this.options.host || getHost()
}
get type() {
return "layer"
}
on() {
return this.add()
}
async add() {
let res = await this.requestResource()
let text = await res.text()
text = JSON.parse(text)
if ([0, 200].includes(text.code)) {
return this.loadLayer(text.data)
} else {
return new Promise((res, reject) => {
reject(text.msg || text.message)
})
}
}
async loadLayer(data) {
this.object = { ...data }
let url = ""
if (this.object.url.startsWith("http"))
url = this.object.url
else {
if (this.options.host) {
let o = new URL(this.object.url, this.options.host)
url = o.href
} else
url = this.object.url
}
let params = {
url: url,
mimmumLevel: this.object.minimumLevel,
maximumLevel: this.object.maximumLevel,
rectangle: new Cesium.Rectangle(
Cesium.Math.toRadians(this.object.west),
Cesium.Math.toRadians(this.object.south),
Cesium.Math.toRadians(this.object.east),
Cesium.Math.toRadians(this.object.north)
),
}
// if (this.object.scheme_name === "GeographicTilingScheme") {
// console.log("添加GeographicTilingScheme")
// params.tilingScheme = new Cesium.GeographicTilingScheme()
// }
// if (this.object.scheme_name === "amapMercatorTilingScheme") {
// console.log("添加amapMercatorTilingScheme")
// params.tilingScheme = this.amapMercatorTilingScheme()
// }
let layer
// if (this.object.tiletrans === 'tms') {
// params.url = params.url.substr(0, params.url.indexOf('{'))
// tms = new Cesium.TileMapServiceImageryProvider(params)
// } else {
// tms = new Cesium.UrlTemplateImageryProvider(params)
// }
switch (this.object.scheme_name) {
case "amapMercatorTilingScheme":
params.tilingScheme = this.amapMercatorTilingScheme()
break;
case "":
break;
default:
params.tilingScheme = new Cesium[this.object.scheme_name]()
break;
}
switch (this.object.load_method) {
case "tms":
if(this.object.url.endsWith("tilemapresource.xml")){
let arr = this.object.url.split("/")
arr.pop()
let url = arr.join("/")
params.url = url
}
if (Number(Cesium.VERSION.split('.')[1]) >= 107) {
layer = await Cesium.TileMapServiceImageryProvider.fromUrl(params.url, params);
}
else {
layer = new Cesium.TileMapServiceImageryProvider(params)
}
break;
case "xyz":
layer = new Cesium.UrlTemplateImageryProvider(params)
break;
case "wmts":
layer = new Cesium.WebMapTileServiceImageryProvider(params)
break;
default:
layer = new Cesium.UrlTemplateImageryProvider(params)
break;
}
if(!this.sdk || !this.sdk.viewer) {
return
}
if (this.options.hasOwnProperty("layer_index")) {
this.entity =
this.sdk.viewer.scene.imageryLayers.addImageryProvider(layer, this.options.layer_index)
} else {
this.entity =
this.sdk.viewer.scene.imageryLayers.addImageryProvider(layer,)
}
this.entity._id = this.options.id
for (let i = 0; i < this.sdk.viewer.imageryLayers._layers.length; i++) {
if (this.sdk.viewer.imageryLayers._layers[i]._imageryProvider && this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type && (this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'flw' || this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'jww')) {
let layer = this.sdk.viewer.imageryLayers._layers[i]
this.sdk.viewer.imageryLayers.raiseToTop(layer)
}
}
this.show = this.options.show
this.alpha = this.options.alpha
this.brightness = this.options.brightness
if(this.options.show) {
setSplitDirection(0, this.options.id)
}
}
}
export default Layer

View File

@ -0,0 +1,58 @@
/**
* @name: index
* @author: Administrator
* @date: 2023-11-20 15:51
* @descriptionindex
* @update: 2023-11-20 15:51
*/
import BaseLayer from "../index";
import { setSplitDirection, setActiveId } from '../../../../../Global/SplitScreen'
class Layer3rdparty extends BaseLayer {
constructor(sdk, options = {}) {
super(sdk, options)
this.loadLayer()
}
get type() {
return "layer"
}
loadLayer(data) {
let params = {
url: this.options.url,
mimmumLevel: this.options.minimumLevel || 0,
maximumLevel: this.options.maximumLevel || 20,
subdomains: ['0','1','2','3','4','5','6','7'],
}
let layer
layer = new Cesium.UrlTemplateImageryProvider(params)
if (this.options.hasOwnProperty("layer_index")) {
this.entity =
this.sdk.viewer.scene.imageryLayers.addImageryProvider(layer, this.options.layer_index)
} else {
this.entity =
this.sdk.viewer.scene.imageryLayers.addImageryProvider(layer,)
}
this.entity._id = this.options.id
for (let i = 0; i < this.sdk.viewer.imageryLayers._layers.length; i++) {
if (this.sdk.viewer.imageryLayers._layers[i]._imageryProvider && this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type && (this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'flw' || this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'jww')) {
let layer = this.sdk.viewer.imageryLayers._layers[i]
this.sdk.viewer.imageryLayers.raiseToTop(layer)
}
}
this.show = this.options.show
this.alpha = this.options.alpha
this.brightness = this.options.brightness
if(this.options.show) {
setSplitDirection(0, this.options.id)
}
}
}
export default Layer3rdparty

View File

@ -0,0 +1,322 @@
/**
* @name: index
* @author: Administrator
* @date: 2023-11-20 18:06
* @descriptionindex
* @update: 2023-11-20 18:06
*/
import Dialog from '../../../Element/Dialog';
import CoordTransform from "../../../../transform/CoordTransform";
import BaseSource from "../index";
import { syncData, get2DView } from '../../../../Global/MultiViewportMode'
import { setSplitDirection, syncSplitData } from '../../../../Global/SplitScreen'
import { setActiveViewer, closeRotateAround, closeViewFollow } from '../../../../Global/global'
class BaseLayer extends BaseSource {
constructor(sdk, options, _Dialog = {}) {
super(sdk, options);
this.options.name = options.name || '未命名对象'
this.Dialog = _Dialog
this._elms = {};
}
setDefaultValue() {
super.setDefaultValue();
this.options.alpha = this.options.alpha ?? 1
this.options.brightness = this.options.brightness ?? 1
}
get layerIndex() {
return this.entity ? this.entity._layerIndex : undefined
}
get layer_index() {
return this.entity ? this.entity._layerIndex : undefined
}
get brightness() {
return this.options.brightness
}
set brightness(v) {
this.options.brightness = v
this.entity.brightness = v
}
get alpha() {
return this.options.alpha
}
set alpha(v) {
if (Number(v) > 1) v = 1
if (Number(v) < 0) v = 0
this.entity.alpha = v
this.options.alpha = v
this._elms.alpha && this._elms.alpha.forEach((item) => {
item.value = v
})
}
/**@description 提高图层的一层层级
* @method layerRaise
* @param id {string} 图层id
*@memberOf Layer
* */
layerRaise(id) {
this.sdk.viewer.imageryLayers.raise(this.entity)
for (let i = 0; i < this.sdk.viewer.imageryLayers._layers.length; i++) {
if (this.sdk.viewer.imageryLayers._layers[i]._imageryProvider && this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type && (this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'flw' || this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'jww')) {
let layer = this.sdk.viewer.imageryLayers._layers[i]
this.sdk.viewer.imageryLayers.raiseToTop(layer)
}
}
this.options.layer_index = this.entity._layerIndex
return this.entity._layerIndex
}
/**@description 降低图层的一层层级
* @method layerLower
* @memberOf Layer
* */
layerLower() {
this.sdk.viewer.imageryLayers.lower(this.entity)
this.options.layer_index = this.entity._layerIndex
return this.entity._layerIndex
}
/**@description 置顶
* @method layerToTop
* @memberOf Layer
* */
layerToTop() {
this.sdk.viewer.imageryLayers.raiseToTop(this.entity)
for (let i = 0; i < this.sdk.viewer.imageryLayers._layers.length; i++) {
if (this.sdk.viewer.imageryLayers._layers[i]._imageryProvider && this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type && (this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'flw' || this.sdk.viewer.imageryLayers._layers[i]._imageryProvider._type === 'jww')) {
let layer = this.sdk.viewer.imageryLayers._layers[i]
this.sdk.viewer.imageryLayers.raiseToTop(layer)
}
}
this.options.layer_index = this.entity._layerIndex
return this.entity._layerIndex
}
/**@description 置底
* @method lowerToBottom
* @memberOf Layer
* */
layerToBottom() {
this.sdk.viewer.imageryLayers.lowerToBottom(this.entity)
this.options.layer_index = this.entity._layerIndex
return this.entity._layerIndex
}
remove() {
super.remove()
this.sdk.viewer.scene.imageryLayers.remove(this.entity)
this.entity = null
}
/**@description 定位
* @method flyTo
* @memberOf Layer
* */
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 = { lng: 0, lat: 0 }
if (this.options.position) {
position = { ...this.options.position }
}
else if (this.options.positions) {
position = { ...this.options.positions[0] }
}
else if (this.options.center) {
position = { ...this.options.center }
}
else if (this.options.start) {
position = { ...this.options.start }
}
else {
if (this.options.hasOwnProperty('lng')) {
position.lng = this.options.lng
}
if (this.options.hasOwnProperty('lat')) {
position.lat = this.options.lat
}
if (this.options.hasOwnProperty('alt')) {
position.alt = this.options.alt
}
}
// 如果没有高度值,则获取紧贴高度计算
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 {
this.sdk.viewer.flyTo(this.entity)
}
}
/*高德的纠偏*/
amapMercatorTilingScheme(options) {
class AmapMercatorTilingScheme extends Cesium.WebMercatorTilingScheme {
constructor(options) {
super(options)
let projection = new Cesium.WebMercatorProjection()
this._projection.project = function (cartographic, result) {
result = CoordTransform.WGS84ToGCJ02(
Cesium.Math.toDegrees(cartographic.longitude),
Cesium.Math.toDegrees(cartographic.latitude)
)
result = projection.project(
new Cesium.Cartographic(
Cesium.Math.toRadians(result[0]),
Cesium.Math.toRadians(result[1])
)
)
return new Cesium.Cartesian2(result.x, result.y)
}
this._projection.unproject = function (cartesian, result) {
let cartographic = projection.unproject(cartesian)
result = CoordTransform.GCJ02ToWGS84(
Cesium.Math.toDegrees(cartographic.longitude),
Cesium.Math.toDegrees(cartographic.latitude)
)
return new Cesium.Cartographic(
Cesium.Math.toRadians(result[0]),
Cesium.Math.toRadians(result[1])
)
}
}
}
return new AmapMercatorTilingScheme(options)
}
/**
* @description 编辑框
* @param state=false {boolean} 状态: true打开, false关闭
*/
async edit(state = false) {
this.originalOptions = this.deepCopyObj(this.options)
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
this._DialogObject = await new Dialog(this.sdk, this.options, {
title: '底图属性', left: '180px', top: '100px',
confirmCallBack: (options) => {
this.name = this.name.trim()
if (!this.name) {
this.name = '未命名对象'
}
this.originalOptions = this.deepCopyObj(this.options)
this._DialogObject.close()
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(this.originalOptions)
// syncData(this.sdk, this.options.id)
syncSplitData(this.sdk, this.options.id)
let sdk2D = get2DView()
if (sdk2D && sdk2D != this.sdk) {
for(let i=0;i<sdk2D.viewer.imageryLayers._layers.length;i++) {
let layer = sdk2D.viewer.imageryLayers._layers[i]
if(layer._id && layer._id == this.options.id) {
layer.alpha = this.options.alpha
break
}
}
}
},
closeCallBack: () => {
this.reset()
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
},
// resetCallBack: () => {
// this.name = this.originalOptions.name
// this.alpha = this.originalOptions.alpha
// this.Dialog.resetCallBack && this.Dialog.resetCallBack()
// },
removeCallBack: () => {
this.Dialog.removeCallBack && this.Dialog.removeCallBack()
},
}, true)
let contentElm = document.createElement('div')
contentElm.style.width = '300px'
let html = `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label" style="flex: 0 0 60px;">名称:</span>
<input class="input name" type="text">
</div>
</div>
<div class="row">
<div class="col">
<span class="label" style="flex: 0 0 60px;">透明度:</span>
<input type="range" class="alpha" min="0" max="1" step="0.01">
</div>
</div>
</div>
`
contentElm.innerHTML = html
let nameElm = contentElm.getElementsByClassName('name')[0]
let alphaElm = contentElm.getElementsByClassName('alpha')[0]
nameElm.value = this.name
alphaElm.value = this.alpha
nameElm.addEventListener('input', () => {
this.name = nameElm.value
})
alphaElm.addEventListener('input', () => {
this.alpha = alphaElm.value
})
this._DialogObject.contentAppChild(contentElm)
this._elms.name = [nameElm]
this._elms.alpha = [alphaElm]
}
reset() {
if (!this.entity && !this._DialogObject) {
return
}
this.options = this.deepCopyObj(this.originalOptions)
this.name = this.options.name
this.alpha = this.options.alpha
this.brightness = this.options.brightness
}
flicker() { }
}
export default BaseLayer

View File

@ -0,0 +1,196 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row" style="align-items: flex-start;">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col">
<span class="label" style="flex: 0 0 60px;">颜色</span>
<div class="color"></div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" min="-180" max="180" @model="lng">
</div>
<div class="col">
<span class="label" style="flex: 0 0 60px;">最大比例</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="0.1" max="99999" step="0.1" @model="maximumScale">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-90" max="90" @model="lat">
</div>
<div class="col">
<span class="label" style="flex: 0 0 60px;">最小像素</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="1" max="99999" @model="minimumPixelSize">
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="-99999" max="9999999" @model="alt">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label" style="flex: 0 0 60px;">固定大小</span>
<input class="btn-switch" type="checkbox" @model="scaleByDistance">
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<DIV-cy-tabs id="model-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="方向信息">
<div>
<div class="row">
<p class="lable-left-line">旋转</p>
</div>
<div class="row">
<div class="col">
<span class="label">x 轴</span>
<input style="flex: 1;margin-right: 15px;" type="range" max="360" min="0" step="0.01" @model="rotateX">
<div class="input-number input-number-unit-1" style="width: auto;">
<input style="width: 100px;" type="number" title="" min="0" max="360" @model="rotateX">
<span class="unit">°</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">y 轴</span>
<input style="flex: 1;margin-right: 15px;" type="range" max="360" min="0" step="0.01" @model="rotateY">
<div class="input-number input-number-unit-1" style="width: auto;">
<input style="width: 100px;" type="number" title="" min="0" max="360" @model="rotateY">
<span class="unit">°</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">z 轴</span>
<input style="flex: 1;margin-right: 15px;" type="range" max="360" min="0" step="0.01" @model="rotateZ">
<div class="input-number input-number-unit-1" style="width: auto;">
<input style="width: 100px;" type="number" title="" min="0" max="360" @model="rotateZ">
<span class="unit">°</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="lable-left-line">
<span>缩放</span>
<div class="checkbox-box">
<input type="checkbox">
<span>是否等比例缩放</span>
</div>
</div>
</div>
<div class="row no-equal" style="display: none;">
<div class="row">
<div class="col">
<span class="label">x 轴</span>
<input style="flex: 1;margin-right: 15px;" type="range" max="99999" min="0" step="1" @model="scaleX">
<div class="input-number input-number-unit-1" style="width: auto;">
<input style="width: 100px;" type="number" title="" min="0" max="99999" @model="scaleX">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">y 轴</span>
<input style="flex: 1;margin-right: 15px;" type="range" max="99999" min="0" step="1" @model="scaleY">
<div class="input-number input-number-unit-1" style="width: auto;">
<input style="width: 100px;" type="number" title="" min="0" max="99999" @model="scaleY">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">z 轴</span>
<input style="flex: 1;margin-right: 15px;" type="range" max="99999" min="0" step="1" @model="scaleZ">
<div class="input-number input-number-unit-1" style="width: auto;">
<input style="width: 100px;" type="number" title="" min="0" max="99999" @model="scaleZ">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<div class="row equal" style="display: none;">
<div class="row">
<div class="col">
<span class="label">等比例缩放</span>
<input style="flex: 1;margin-right: 15px;" type="range" max="99999" min="0" step="1">
<div class="input-number input-number-unit-1" style="width: auto;">
<input style="width: 100px;" type="number" title="" min="0" max="99999" step="1">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<div class="row">
<p class="lable-left-line">高度</p>
</div>
<div class="row">
<div class="col">
<span class="label">高度</span>
<input style="flex: 1;margin-right: 15px;" type="range" max="999999" min="-99999" step="0.01" @model="alt">
<div class="input-number input-number-unit-1" style="width: auto;">
<input style="width: 100px;" type="number" title="" min="-99999" max="999999" @model="alt">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
</DIV-cy-tabs>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,123 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../../../Element/elm_html'
function html(that) {
return `
<div class="row" style="align-items: flex-start;">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col">
<span class="label">颜色</span>
<div class="color"></div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" min="-180" max="180" @model="lng">
</div>
<div class="col">
<span class="label">最大比例</span>
<input class="input" type="number" title="" min="0.1" max="99999" step="0.1" @model="maximumScale">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-90" max="90" @model="lat">
</div>
<div class="col">
<span class="label">最小像素</span>
<input class="input" type="number" title="" min="1" max="99999" @model="minimumPixelSize">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">高度</span>
<input class="input" type="number" title="" min="-9999999" max="999999999" @model="alt">
</div>
<div class="col">
<span class="label">视野缩放</span>
<input class="btn-switch" type="checkbox" @model="scaleByDistance">
</div>
</div>
<div class="row">
<DIV-cy-tabs id="model-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="方向信息">
<div>
<div class="row">
<div class="col">
<span class="label">x轴</span>
<input style="width: 332px;" type="range" max="360" min="0" step="0.01" @model="rotateX">
<input style="font-size: 13px;width: 100px;" type="number" title="" min="0" max="360" @model="rotateX">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">y轴</span>
<input style="width: 332px;" type="range" max="360" min="0" step="0.01" @model="rotateY">
<input style="font-size: 13px;width: 100px;" type="number" title="" min="0" max="360" @model="rotateY">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">z轴</span>
<input style="width: 332px;" type="range" max="360" min="0" step="0.01" @model="rotateZ">
<input style="font-size: 13px;width: 100px;" type="number" title="" min="0" max="360" @model="rotateZ">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">高度</span>
<input style="width: 332px;" type="range" max="999999" min="-99999" step="0.01" @model="alt">
<input style="font-size: 13px;width: 100px;" type="number" title="" min="-99999" max="999999" @model="alt">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">缩放</span>
<input style="width: 332px;" type="range" max="999" min="0" step="1" @model="scale">
<input style="font-size: 13px;width: 100px;" type="number" title="" min="0" max="999" step="1" @model="scale">
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
</DIV-cy-tabs>
</div>
`
}
function css() {
return `
.YJ-custom-base-dialog>.content {
width: 600px;
}
.YJ-custom-base-dialog>.content>div>.row .col {
margin: 0 10px;
}
.YJ-custom-base-dialog>.content>div>.row .col:first-child {
margin-left: 0;
}
.YJ-custom-base-dialog>.content>div>.row .col:last-child {
margin-right: 0;
}
.YJ-custom-base-dialog>.content>div>.row .label {
flex: 0 0 74px;
}
.YJ-custom-base-dialog>.content .DIV-cy-tab-content-pane .input-select {
width: 100px;
}
`
}
export { html, css }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
import richText from "../../../Element/richText";
import BaseSource from "../index";
class BaseModel extends BaseSource {
constructor(sdk, options, _Dialog = {}) {
super(sdk, options);
}
async add() {
if (this.options.url) {
return this.loadModel(this.options.url)
}
}
_addLink() {
// document.getElementsByClassName
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
}
_addRr() {
if (this._DialogObject._element.content.getElementsByClassName('vr_add')[0].value) {
this.options.attribute.vr.content.push({
name: '全景图' ,
url: this._DialogObject._element.content.getElementsByClassName('vr_add')[0].value
})
this._DialogObject._element.content.getElementsByClassName('vr_add')[0].value = ''
this.attributeVr = this.options.attribute.vr.content
}
else {
this.Dialog.clickAddVr && this.Dialog.clickAddVr()
}
}
addAttributeRr(vr) {
this.options.attribute.vr.content.push({
name: '全景图' ,
url: vr
})
this.attributeVr = this.options.attribute.vr.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
}
}
}
export default BaseModel

View File

@ -0,0 +1,293 @@
/**
* @name: index
* @author: Administrator
* @date: 2023-11-20 17:54
* @descriptionindex
* @update: 2023-11-20 17:54
*/
import Dialog from '../../../Element/Dialog';
import { getHost } from "../../../../on";
import BaseSource from "../index";
import { setActiveViewer, closeRotateAround, closeViewFollow } from '../../../../Global/global'
import { setSplitDirection, syncSplitData } from '../../../../Global/SplitScreen'
class BaseTerrain extends BaseSource {
#updateModelTimeout;
constructor(sdk, options = {}, object = {}, _Dialog = {}) {
super(sdk, options);
this.object = JSON.parse(JSON.stringify(object))
this.object.west || (this.object.west = 40)
this.object.south || (this.object.south = 30)
this.object.east || (this.object.east = 160)
this.object.north || (this.object.north = 50)
this.show = this.options.show
this._elms = {};
this.Dialog = _Dialog
}
get type() {
return "terrain"
}
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.sdk.viewer.scene.terrainProvider instanceof
Cesium.EllipsoidTerrainProvider
)
}
set show(status) {
status ? this.open() : this.close()
}
async open() {
if (this.options.url) {
return this.loadTerrain({
url: this.options.url
})
} else {
let res = await this.requestResource()
let text = await res.text()
text = JSON.parse(text)
if ([0, 200].includes(text.code)) {
if (text.data.url.length)
return this.loadTerrain(text.data)
else
return new Promise((res, reject) => {
reject('资源不存在')
})
} else {
return new Promise((res, reject) => {
reject(text.msg || text.message)
})
}
}
}
//关闭地形
close() {
this.sdk.viewer.scene.terrainProvider =
new Cesium.EllipsoidTerrainProvider({})
for (let i = 0; i < YJ.Analysis.AnalysesResults.length; i++) {
if (YJ.Analysis.AnalysesResults[i].type === 'ContourAnalysis') {
YJ.Analysis.AnalysesResults[i].destroy()
}
}
syncSplitData(this.sdk, this.options.id)
clearTimeout(this.#updateModelTimeout)
this.#updateModelTimeout = setTimeout(() => {
clearTimeout(this.#updateModelTimeout)
for (let [key, entity] of this.sdk.entityMap) {
if (entity.type === 'BillboardObject' && (entity.heightMode == 1 || entity.heightMode == 3)) {
entity.updateHeight()
}
else {
if (entity.label) {
entity.label.show = entity.label.show
}
}
}
}, 500);
}
async loadTerrain(options) {
let object = { ...options }
let url = ""
if (object.url.startsWith("http"))
url = object.url
else {
//说明是本地的json在磁盘中存在的
if (object.url.includes(":")) {
url = object.url
} else {
if (this.options.host) {
let o = new URL(object.url, this.options.host)
url = o.href
} else
url = object.url
}
}
if (Number(Cesium.VERSION.split('.')[1]) >= 107) {
this.terrainProvider = await Cesium.CesiumTerrainProvider.fromUrl(url)
}
else {
this.terrainProvider = new Cesium.CesiumTerrainProvider({
url: url
})
}
if (!this.sdk || !this.sdk.viewer) {
return
}
this.sdk.viewer.terrainProvider = this.terrainProvider;
clearTimeout(this.#updateModelTimeout)
this.#updateModelTimeout = setTimeout(() => {
clearTimeout(this.#updateModelTimeout)
this.terrainProvider.readyPromise.then(() => {
for (let [key, entity] of this.sdk.entityMap) {
if (entity.type === 'BillboardObject' && (entity.heightMode == 1 || entity.heightMode == 3)) {
entity.updateHeight()
}
else {
if (entity.label) {
entity.label.show = entity.label.show
}
}
}
})
}, 1000);
syncSplitData(this.sdk, this.options.id)
}
remove() {
this.close()
}
async flyTo(duration = 3) {
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 = { lng: 0, lat: 0 }
if (this.options.position) {
position = { ...this.options.position }
}
else if (this.options.positions) {
position = { ...this.options.positions[0] }
}
else if (this.options.center) {
position = { ...this.options.center }
}
else if (this.options.start) {
position = { ...this.options.start }
}
else {
if (this.options.hasOwnProperty('lng')) {
position.lng = this.options.lng
}
if (this.options.hasOwnProperty('lat')) {
position.lat = this.options.lat
}
if (this.options.hasOwnProperty('alt')) {
position.alt = this.options.alt
}
}
// 如果没有高度值,则获取紧贴高度计算
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,
duration
})
}
else {
let rectangle = new Cesium.Rectangle(
Cesium.Math.toRadians(this.object.west),
Cesium.Math.toRadians(this.object.south),
Cesium.Math.toRadians(this.object.east),
Cesium.Math.toRadians(this.object.north)
)
this.sdk.viewer.camera.flyTo({
destination: rectangle,
duration,
})
}
}
setDefaultValue() {
super.setDefaultValue()
this.options.host = this.options.host || getHost()
this.options.url = this.options.url || ""
}
/**
* @description 编辑框
* @param state=false {boolean} 状态: true打开, false关闭
*/
async edit(state = false) {
this.originalOptions = this.deepCopyObj(this.options)
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
this._DialogObject = await new Dialog(this.sdk, this.options, {
title: '地形属性', left: '180px', top: '100px',
confirmCallBack: (options) => {
this.name = this.name.trim()
if (!this.name) {
this.name = '未命名对象'
}
this.originalOptions = this.deepCopyObj(this.options)
this._DialogObject.close()
let cdoptions = this.deepCopyObj(this.options)
cdoptions.host = ''
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(cdoptions)
},
// resetCallBack: () => {
// this.name = this.originalOptions.name
// this.Dialog.resetCallBack && this.Dialog.resetCallBack()
// },
removeCallBack: () => {
this.Dialog.removeCallBack && this.Dialog.removeCallBack()
},
}, true)
let contentElm = document.createElement('div')
contentElm.style.width = '300px'
let html = `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称:</span>
<input class="input name" type="text">
</div>
</div>
</div>
`
contentElm.innerHTML = html
let nameElm = contentElm.getElementsByClassName('name')[0]
nameElm.value = this.name
nameElm.addEventListener('input', () => {
this.name = nameElm.value
})
this._DialogObject.contentAppChild(contentElm)
this._elms.name = [nameElm]
}
flicker() { }
}
export default BaseTerrain

View File

@ -0,0 +1,93 @@
function html() {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" @model="name">
</div>
<div class="col">
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" min="-180" max="180" @model="lng">
</div>
<div class="col">
<span class="label">x轴</span>
<input type="number" title="" min="-180" max="180" @model="roll">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-90" max="90" @model="lat">
</div>
<div class="col">
<span class="label">y轴</span>
<input type="number" title="" min="-180" max="180" @model="heading">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="-9999999" max="999999999" @model="height">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">z轴</span>
<input type="number" title="" min="-180" max="180" @model="pitch">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">大小</span>
<input type="range" max="10" min="0.1" step="0.1" @model="scale">
<div class="input-number" style="width: 100px;margin-left: 10px;">
<input type="number" title="" min="0" max="10" step="0.1" @model="scale">
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<div class="divide">
<div class="line"></div>
<p>BIM属性导出选项</p>
<div class="line"></div>
</div>
<div class="row">
<div style="display: flex;">
<div class="checkbox-box" @click="exportState">
<input type="checkbox" value="3">
<span>修建中</span>
</div>
<div class="checkbox-box" @click="exportState">
<input type="checkbox" value="2">
<span>未完成</span>
</div>
<div class="checkbox-box" @click="exportState">
<input type="checkbox" value="1">
<span>已完成</span>
</div>
</div>
<div class="col">
<button @click="exportProperty">导 出</button>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,82 @@
function html2() {
return `
<div class="row">
<div class="col">
<span class="label">构件名称</span>
<input class="input" name="name" disabled="disabled">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">选择状态</span>
<select class="input input-select" name="state-select">
<option value="0" style="color: #000;">重置</option>
<option value="1" style="color: #f00;">已完成</option>
<option value="2" style="color: #0f0;">未完成</option>
<option value="3" style="color: #00f;">修建中</option>
</select>
</div>
</div>
<div class="divide">
<div class="line"></div>
<p>自定义属性</p>
<div class="line"></div>
</div>
<div class="property">
</div>
`
}
function css2() {
return `
.YJ-custom-base-dialog>.content {
width: 440px;
}
.YJ-custom-base-dialog>.content .row .label {
flex: 0 0 110px;
}
.col:first-child {
margin-right: 10px;
}
.col:last-child {
margin-left: 10px;
}
.YJ-custom-base-dialog>.content .divide {
position: relative;
display: flex;
align-items: center;
margin: 20px 0;
}
.YJ-custom-base-dialog>.content .divide .line{
height: 1px;
background: #ddd;
flex: 1;
}
.YJ-custom-base-dialog>.content .divide p{
margin: 0 10px;
}
.YJ-custom-base-dialog>.content .property .property-item .btn{
font-size: 24px;
line-height: 20px;
padding: 2px 0;
}
.YJ-custom-base-dialog>.content .property .property-item .input_lable {
flex: 0 0 115px;
border: none;
margin-right: 15px;
text-align: right;
}
.YJ-custom-base-dialog>.content .property .property-item:first-child .delete{
display: none
}
.YJ-custom-base-dialog>.content .property .property-item .add{
display: none;
}
.YJ-custom-base-dialog>.content .property .property-item:last-child .add{
display: inline-block;
}
`
}
export { html2, css2 }

View File

@ -0,0 +1,877 @@
/**
* @name: index
* @author: Administrator
* @date: 2023-11-20 16:05
* @descriptionindex
* @update: 2023-11-20 16:05
*/
import BaseTileset from "../index";
import { html } from "./_element";
import { html2, css2 } from "./_element2";
import Dialog from '../../../../Element/Dialog';
import EventBinding from '../../../../Element/Dialog/eventBinding';
import BaseDialog from '../../../../../BaseDialog'
import { syncData } from '../../../../../Global/MultiViewportMode'
import { syncSplitData } from '../../../../../Global/SplitScreen'
import { setActiveViewer, closeRotateAround, closeViewFollow} from '../../../../../Global/global'
class BIM extends BaseTileset {
#updateModelTimeout
/**
* @constructor
* @description 加载BIM模型
* @param sdk {object} sdk
* @param options {object} 模型参数
* @param options.id {string} 对象id
* @param options.show=true {boolean} 模型显隐
* @param options.name {string} 名称
* @param options.url {string} 资源地址
* @param options.position {object} 模型位置
* @param options.position.lng {number} 经度
* @param options.position.lat {number} 纬度
* @param options.position.alt {number} 高度
* */
constructor(sdk, options = {}, _Dialog = {}) {
super(sdk, options)
this.picking = false
this.features = options.features || []
this.exportStateArray = []
this.Dialog = _Dialog
this._elms = {};
this._EventBinding = new EventBinding()
this.Dialog.exportState = (e) => {
this.exportState(e)
}
this.Dialog.exportProperty = (e) => {
this.exportProperty(this.exportStateArray)
}
this.features = new Map()
}
get type() {
return "bim"
}
get name() {
return this.newData.name
}
set name(v) {
this.newData.name = v
this._elms.name && this._elms.name.forEach((item) => {
item.value = v
})
}
get lng() {
return this.newData.lng
}
set lng(v) {
this.newData.lng = v
this.updateModel(this.newData.lng, this.newData.lat, this.newData.height, this.newData.roll, this.newData.heading, this.newData.pitch, this.newData.scale)
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = v
})
}
get lat() {
return this.newData.lat
}
set lat(v) {
this.newData.lat = v
this.updateModel(this.newData.lng, this.newData.lat, this.newData.height, this.newData.roll, this.newData.heading, this.newData.pitch, this.newData.scale)
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = v
})
}
get height() {
return this.newData.height
}
set height(v) {
this.newData.height = v
this.updateModel(this.newData.lng, this.newData.lat, this.newData.height, this.newData.roll, this.newData.heading, this.newData.pitch, this.newData.scale)
this._elms.height && this._elms.height.forEach((item) => {
item.value = v
})
}
get roll() {
return this.newData.roll
}
set roll(v) {
this.newData.roll = v
this.updateModel(this.newData.lng, this.newData.lat, this.newData.height, this.newData.roll, this.newData.heading, this.newData.pitch, this.newData.scale)
this._elms.roll && this._elms.roll.forEach((item) => {
item.value = v
})
}
get heading() {
return this.newData.heading
}
set heading(v) {
this.newData.heading = v
this.updateModel(this.newData.lng, this.newData.lat, this.newData.height, this.newData.roll, this.newData.heading, this.newData.pitch, this.newData.scale)
this._elms.heading && this._elms.heading.forEach((item) => {
item.value = v
})
}
get pitch() {
return this.newData.pitch
}
set pitch(v) {
this.newData.pitch = v
this.updateModel(this.newData.lng, this.newData.lat, this.newData.height, this.newData.roll, this.newData.heading, this.newData.pitch, this.newData.scale)
this._elms.pitch && this._elms.pitch.forEach((item) => {
item.value = v
})
}
get scale() {
return this.newData.scale
}
set scale(v) {
this.newData.scale = v
this.updateModel(this.newData.lng, this.newData.lat, this.newData.height, this.newData.roll, this.newData.heading, this.newData.pitch, this.newData.scale)
this._elms.scale && this._elms.scale.forEach((item) => {
item.value = v
})
}
// get transparency() {
// return this.newData.transparency
// }
// set transparency(v) {
// this.newData.transparency = v
// this.entity.style = new Cesium.Cesium3DTileStyle({
// color: "color('rgba(255,255,255," + this.newData.transparency + ")')",
// show: true,
// });
// this.entity.transparency = Number(this.newData.transparency)
// this._elms.transparency && this._elms.transparency.forEach((item) => {
// item.value = v
// })
// }
async loadSceneTree(url) {
// Cesium.ExperimentalFeatures.enableModelExperimental = true;
let array = url.split('/')
array[array.length - 1] = 'scenetree.json'
await Cesium.Resource.fetchJson({
url: array.join('/')
}).then(res => {
this.scenetree = res
const initData = (array) => {
array.forEach(item => {
if (this.features.has(item.id)) {
this.features.get(item.id).sphere = item.sphere
}
else {
this.features.set(item.id, { sphere: item.sphere })
}
if (item.children) {
initData(item.children)
}
})
}
initData(res.scenes[0].children)
// res.scenes[0].children.forEach(item => {
// if (this.features.has(item.id)) {
// this.features.get(item.id).sphere = item.sphere
// }
// else {
// this.features.set(item.id, {sphere: item.sphere})
// }
// })
})
}
// 编辑框
async edit(state) {
let _this = this
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.newData, {
title: 'BIM模型属性', left: '180px', top: '100px',
resetCallBack: () => {
this.reset()
this.Dialog.resetCallBack && this.Dialog.resetCallBack()
},
confirmCallBack: (info) => {
this.name = this.name.trim()
if (!this.name) {
this.name = '未命名对象'
}
this.oldData.name = this.newData.name
this.oldData.height = this.newData.height
this.oldData.lng = this.newData.lng
this.oldData.lat = this.newData.lat
// this.oldData.transparency = this.newData.transparency
this.oldData.scale = this.newData.scale
this.oldData.roll = this.newData.roll
this.oldData.heading = this.newData.heading
this.oldData.pitch = this.newData.pitch
this._DialogObject.close()
let features = new Map()
this.features.forEach((item, key) => {
let data = { ...item }
delete data.features
features.set(key, data)
})
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack({ ...this.oldData, features: features, type: this.type })
syncSplitData(this.sdk, this.oldData.id)
},
removeCallBack: () => {
this.Dialog.removeCallBack && this.Dialog.removeCallBack()
},
closeCallBack: () => {
this.reset()
// this.newData.transparency = this.oldData.transparency
// this.newData.name = this.oldData.name
// this.newData.height = this.oldData.height
// this.newData.lng = this.oldData.lng
// this.newData.lat = this.oldData.lat
// this.newData.scale = this.oldData.scale
// this.entity.style = new Cesium.Cesium3DTileStyle({
// color: "color('rgba(255,255,255," + this.newData.transparency + ")')",
// show: true,
// });
this.editObj.destroy()
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
},
showCallBack: (show) => {
this.newData.show = show
this.entity && (this.entity.show = show)
this.Dialog.showCallBack && this.Dialog.showCallBack()
},
rotateCallBack: () => {
if (this.rotationEditing) {
this.rotationEditing = false
}
else {
this.rotationEditing = true
}
},
translationalCallBack: () => {
if (this.positionEditing) {
this.positionEditing = false
}
else {
this.positionEditing = true
}
}
})
this._DialogObject._element.body.className = this._DialogObject._element.body.className + ' tileset-bim'
// 内容部分
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
} else {
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
}
}
async featureEdit(state, feature) {
let _this = this
this._element_style = null
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
if (state) {
// console.log(this.entity)
// console.log(this.entity.root.children[0].content)
// console.log(feature.getProperty('id'), feature.getProperty('name'), feature.getProperty('state'))
let name = feature.getProperty('name')
// console.log(feature.getProperty('descriptions'))
let data = {
id: feature.getProperty('id'),
name: name,
state: feature.getProperty('state') || 0,
descriptions: feature.getProperty('descriptions') || [
{
id: this.randomString(),
key: "点击此处可编辑",
value: ""
}
]
}
switch (feature.getProperty('state')) {
case '0': data.stateCH = ''
break
case '1': data.stateCH = '已完成'
break
case '2': data.stateCH = '未完成'
break
case '3': data.stateCH = '修建中'
break
}
// let feature = this.entity.root.children[0].content.getFeature(0)
// console.log(id,feature, this.entity)
// return
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 = css2();
this._DialogObject = await new BaseDialog(this.sdk.viewer._container, {
title: this.oldData.name + '-----设置状态', left: 'calc(50% - 200px)', top: 'calc(50% - 200px)',
closeCallBack: () => {
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
}
})
await this._DialogObject.init()
document.getElementsByTagName('head')[0].appendChild(this._element_style);
// 内容部分
let content = document.createElement('div');
content.innerHTML = html2()
// 名称
let e_name = content.querySelector("input[name='name']")
e_name.value = name
//状态
let e_state = content.querySelector("select[name='state-select']")
e_state.value = data.state
e_state.addEventListener('change', (e) => {
data.state = e.target.value
switch (data.state) {
case '0': data.stateCH = ''
break
case '1': data.stateCH = '已完成'
break
case '2': data.stateCH = '未完成'
break
case '3': data.stateCH = '修建中'
break
}
});
//自定义属性
let e_property = content.getElementsByClassName('property')[0]
for (let i = 0; i < data.descriptions.length; i++) {
createPropertyItem(data.descriptions[i], i)
}
function createPropertyItem(item) {
let html = `<div class="row property-item">
<div class="col">
<input class="input_lable" name="key" value="${item.key}">
<input class="input" name="value" value="${item.value}">
<button class="btn add"></button>
<button class="btn delete"></button>
</div>
</div>`
// document.createRange().createContextualFragment(html)
let newElement = document.createElement("div");
newElement.innerHTML = html
let itemElm = newElement.getElementsByClassName('property-item')[0]
let e_key = itemElm.querySelector("input[name='key']")
let e_value = itemElm.querySelector("input[name='value']")
let e_add = itemElm.getElementsByClassName('add')[0]
let e_delete = itemElm.getElementsByClassName('delete')[0]
e_key.addEventListener('input', (e) => {
item.key = e.target.value
})
e_value.addEventListener('input', (e) => {
item.value = e.target.value
})
e_add.addEventListener('click', () => {
let newItem = {
id: _this.randomString(),
key: "点击此处可编辑",
value: ""
}
data.descriptions.push(newItem)
createPropertyItem(newItem)
})
e_delete.addEventListener('click', (e) => {
for (let i = 0; i < data.descriptions.length; i++) {
if (data.descriptions[i].id === item.id) {
data.descriptions.splice(i, 1)
break
}
}
e_property.removeChild(itemElm)
// let item = {
// key: "点击此处可编辑",
// value: ""
// }
// createPropertyItem(item)
})
e_property.appendChild(itemElm)
}
let target = this._DialogObject._element.foot.getElementsByClassName('translational')[0]
this._DialogObject.contentAppChild(content)
// foot部分
let confirmBtn = document.createElement('button');
confirmBtn.className = 'confirm';
confirmBtn.innerHTML = '确认'
this._DialogObject.footAppChild(confirmBtn, target)
confirmBtn.addEventListener('click', () => {
let flag = false
for (let i = 0; i < this.features.length; i++) {
if (this.features[i].id == data.id) {
this.features[i] = data
flag = true
break
}
}
if (!flag) {
this.features.push(data)
}
feature.setProperty('state', data.state)
feature.setProperty('descriptions', data.descriptions)
let color = '#fff'
switch (data.state) {
case '0':
color = '#fff'
break;
case '1':
color = '#f00'
break;
case '2':
color = '#0f0'
break;
case '3':
color = '#00f'
break;
default:
}
feature.color = Cesium.Color.fromCssColorString(color)
this._DialogObject.close()
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack({ ...this.newData, features: this.features })
});
} else {
if (this._element_style) {
document.getElementsByTagName('head')[0].removeChild(this._element_style)
this._element_style = null
}
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
}
}
reset() {
if (!this.entity) {
return
}
// this.transparency = this.oldData.transparency
this.name = this.oldData.name
this.height = this.oldData.height
this.lng = this.oldData.lng
this.lat = this.oldData.lat
this.roll = this.oldData.roll
this.heading = this.oldData.heading
this.pitch = this.oldData.pitch
this.scale = this.oldData.scale
}
//更新模型位置
updateModel(_tx, _ty, _tz, _rx = 0, _ry = 0, _rz = 0, s = 1) {
if (!this.tileset.root.transform) {
if (window.ELEMENT) {
window.ELEMENT.Message.closeAll();
window.ELEMENT.Message({
message: '该模型不支持移动和旋转!',
type: 'warning',
duration: 1500
});
}
console.warn('该模型不支持移动和旋转!')
return
}
if ((!_tx && _tx!==0) || (!_ty && _ty!==0) || (!_tz && _tz!==0)) {
return
}
let mx = Cesium.Matrix3.fromRotationX(
Cesium.Math.toRadians(_rx)
)
let my = Cesium.Matrix3.fromRotationY(
Cesium.Math.toRadians(_ry)
)
let mz = Cesium.Matrix3.fromRotationZ(
Cesium.Math.toRadians(_rz)
)
// 平移
let m = Cesium.Transforms.eastNorthUpToFixedFrame(new Cesium.Cartesian3.fromDegrees(_tx, _ty, _tz))
// 旋转
let rotationX = Cesium.Matrix4.fromRotationTranslation(mx)
let rotationY = Cesium.Matrix4.fromRotationTranslation(my)
let rotationZ = Cesium.Matrix4.fromRotationTranslation(mz)
let originalMatrix = new Cesium.Matrix4()
Cesium.Matrix4.multiply(m, rotationX, originalMatrix)
Cesium.Matrix4.multiply(originalMatrix, rotationY, originalMatrix)
Cesium.Matrix4.multiply(originalMatrix, rotationZ, originalMatrix)
const scale = Cesium.Matrix4.fromUniformScale(s);
Cesium.Matrix4.multiply(originalMatrix, scale, this.entity._root.transform)
if (!this.editObj.activeAxis) {
this.editObj.position = { lng: _tx, lat: _ty, alt: _tz }
}
if (!this.editObj.activeCircle) {
this.editObj.rotate = { x: _rx, y: _ry, z: _rz }
}
this.editObj && this.editObj.update()
clearTimeout(this.#updateModelTimeout)
this.#updateModelTimeout = setTimeout(() => {
clearTimeout(this.#updateModelTimeout)
let center = this.cartesian3Towgs84(this.entity.boundingSphere.center, this.sdk.viewer)
let circle = turf.circle([center.lng, center.lat], this.entity.boundingSphere.radius / 1000, { steps: 360, units: 'kilometers' });
for (let [key, entity] of this.sdk.entityMap) {
if (entity.type === 'BillboardObject' && entity.heightMode == 3) {
let pt = turf.point([entity.lng, entity.lat]);
if (turf.booleanPointInPolygon(pt, circle)) {
entity.updateHeight()
}
}
else {
if(entity.label) {
entity.label.show = entity.label.show
}
}
}
}, 300);
}
// exportProperty(states) {
// console.log(this.features)
// let fieldKeys = ['name', '', '', '', '', '', '', '', '', '', '', '', 'stateCH', 'descriptions']
// let fieldLabels = ['构件名称', '体积', '墩全高H', '墩身高h', '底部高程', '承台宽', '承台长', '承台高', '族', '桩径', '桩长', '结构材质', '完成情况', '自定义属性']
// let dataStr = fieldLabels.toString() + '\r\n';
// for (let i = 0; i < this.features.length; i++) {
// for (let j = 0; j < states.length; j++) {
// if (this.features[i].state == states[j]) {
// fieldKeys.forEach(key => {
// if (Array.isArray(this.features[i][key])) {
// let str = ''
// for (let k in this.features[i][key]) {
// str += `${this.features[i][key][k].key + '' + this.features[i][key][k].value}\n`
// }
// dataStr += `"${str}"\t`
// }
// else {
// // 加引号是为了使换行符在单元格内正常显示
// dataStr += `"${this.features[i][key] ? this.features[i][key] : ''}"\t,`;
// }
// });
// dataStr += '\r\n';
// break
// }
// }
// }
// // encodeURIComponent 解决中文乱码
// const url = "data:text/xls;charset=utf-8,\ufeff" + encodeURIComponent(dataStr);
// console.log(url)
// // const link = document.createElement("a");
// // link.href = url;
// // link.download = this.oldData.name + "--构件属性.xls";
// // link.style.display = 'none';
// // document.body.appendChild(link);
// // link.click();
// // document.body.removeChild(link); //释放标签
// }
getScenetree() {
return this.scenetree
}
// 设置feature颜色
featureColor(id, color) {
if (this.features.has(id)) {
let features = this.features.get(id).features
for (let key in features) {
if (features[key].content._model) {
features[key].color = Cesium.Color.fromCssColorString(color)
}
features[key].customColor = Cesium.Color.fromCssColorString(color)
}
this.features.get(id).customColor = Cesium.Color.fromCssColorString(color)
}
}
getFeatureColor(id) {
if (this.features.has(id)) {
if (this.features.get(id).customColor) {
return this.features.get(id).customColor
}
let features = this.features.get(id).features
for (let key in features) {
if (features[key].content._model) {
return features[key].customColor || features[key].color
}
}
}
}
// 设置feature显隐
featureShow(id, show) {
if (this.features.has(id)) {
let features = this.features.get(id).features
for (let key in features) {
if (features[key].content._model) {
features[key].show = show
}
features[key].customShow = show
}
this.features.get(id).customShow = show
}
}
//飞到feature位置
async featureFlyto(id) {
if (this.features.has(id)) {
let sphere = this.features.get(id).sphere
let center = new Cesium.Cartesian3(
sphere[0],
sphere[1],
sphere[2]
)
let srcMatInv = this.entity._root.originalTransform
srcMatInv = Cesium.Matrix4.inverse(srcMatInv, new Cesium.Matrix4())
let curMat = this.entity._root.transform
let mat = Cesium.Matrix4.multiply(curMat, srcMatInv, new Cesium.Matrix4())
let center2 = Cesium.Matrix4.multiplyByPoint(
mat,
center,
new Cesium.Cartesian3()
)
let wgs84 = this.cartesian3Towgs84(center2, this.sdk.viewer)
let cartesian3 = Cesium.Cartesian3.fromDegrees(
wgs84.lng,
wgs84.lat,
wgs84.alt + sphere[3]
)
setActiveViewer(0)
closeRotateAround(this.sdk)
closeViewFollow(this.sdk)
this.sdk.viewer.camera.flyTo({
destination: cartesian3
})
// this.entity.style = await new Cesium.Cesium3DTileStyle({
// color: "color('rgba(255,255,255,0.2)')"
// });
this.features.forEach((item, key) => {
if (key === id) {
let color = this.getFeatureColor(id)
if (this.features.has(id) && color) {
let features = this.features.get(id).features
for (let k in features) {
if (features[k].content._model) {
features[k].color = color
}
features[k].customAlpha = 1
}
this.features.get(id).customAlpha = 1
}
// this.featureColor(id, `rgba(${Cesium.Color.floatToByte(color.red)},${Cesium.Color.floatToByte(color.green)},${Cesium.Color.floatToByte(color.blue)},${color.alpha})`)
}
else {
let color = this.getFeatureColor(key)
if (this.features.has(key) && color) {
let features = this.features.get(key).features
for (let k in features) {
if (features[k].content._model) {
features[k].color = Cesium.Color.fromCssColorString(`rgba(${Cesium.Color.floatToByte(color.red)},${Cesium.Color.floatToByte(color.green)},${Cesium.Color.floatToByte(color.blue)},${color.alpha * 0.2})`)
}
features[k].customAlpha = color.alpha * 0.2
}
this.features.get(key).customAlpha = color.alpha * 0.2
}
// this.featureColor(key, `rgba(${Cesium.Color.floatToByte(color.red)},${Cesium.Color.floatToByte(color.green)},${Cesium.Color.floatToByte(color.blue)},${color.alpha * 0.2})`)
}
})
// this.entity.readyPromise.then(()=>{
// this.featureColor(id, '#ffffff')
// })
}
else {
this.features.forEach((item, key) => {
let features = this.features.get(key).features
let color = this.getFeatureColor(key)
if (color) {
for (let k in features) {
if (features[k].content._model) {
features[k].color = color
}
features[k].customAlpha = 1
}
this.features.get(key).customAlpha = color.alpha * 0.2
}
})
}
}
// 导出属性
exportProperty(states) {
if (this.exportStateArray.length === 0) {
window.ELEMENT && window.ELEMENT.Message({
message: '未选择属性导出选项!',
type: 'warning',
duration: 1500
});
return
}
let fieldKeys = ['name', '', '', '', '', '', '', '', '', '', '', '', 'stateCH', 'descriptions']
let fieldLabels = ['构件名称', '体积', '墩全高H', '墩身高h', '底部高程', '承台宽', '承台长', '承台高', '族', '桩径', '桩长', '结构材质', '完成情况', '自定义属性']
var url = 'data:application/vnd.ms-excel;base64,',
tmplWorkbookXML = '<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?><Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">'
+ '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"><Author>Axel Richter</Author><Created>{created}</Created></DocumentProperties>'
+ '<Styles>'
+ '<Style ss:ID="Currency"><NumberFormat ss:Format="Currency"></NumberFormat></Style>'
+ '<Style ss:ID="Date"><NumberFormat ss:Format="Medium Date"></NumberFormat></Style>'
+ '</Styles>'
+ '{worksheets}</Workbook>'
, tmplWorksheetXML = '<Worksheet ss:Name="{nameWS}"><Table><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="240"/>{rows}</Table></Worksheet>'
, tmplCellXML = '<Cell><Data ss:Type="{nameType}">{data}</Data></Cell>'
, base64 = function (s) {
return window.btoa(unescape(encodeURIComponent(s)))
}
, format = function (s, c) {
return s.replace(/{(\w+)}/g, function (m, p) {
return c[p];
})
}
var ctx = "";
var workbookXML = "";
var worksheetsXML = "";
var rowsXML = "";
var pil = 0;
for (var i = 0; i < this.features.length; i++) {
for (let j = 0; j < states.length; j++) {
if (this.features[i].state == states[j]) {
if (i == 0) {
rowsXML += '<Row>' +
'<Cell><Data ss:Type="String">构件名称</Data></Cell>' +
'<Cell><Data ss:Type="String">体积</Data></Cell>' +
'<Cell><Data ss:Type="String">墩全高H</Data></Cell>' +
'<Cell><Data ss:Type="String">墩身高h</Data></Cell>' +
'<Cell><Data ss:Type="String">底部高程</Data></Cell>' +
'<Cell><Data ss:Type="String">承台宽</Data></Cell>' +
'<Cell><Data ss:Type="String">承台长</Data></Cell>' +
'<Cell><Data ss:Type="String">承台高</Data></Cell>' +
'<Cell><Data ss:Type="String">族</Data></Cell>' +
'<Cell><Data ss:Type="String">桩径</Data></Cell>' +
'<Cell><Data ss:Type="String">桩长</Data></Cell>' +
'<Cell><Data ss:Type="String">结构材质</Data></Cell>' +
'<Cell><Data ss:Type="String">完成情况</Data></Cell>' +
'<Cell><Data ss:Type="String">自定义属性</Data></Cell>' +
'</Row>';
}
rowsXML += '<Row>';
for (var key in fieldKeys) {
if (Array.isArray(this.features[i][fieldKeys[key]])) {
let str = ''
for (let k in this.features[i][fieldKeys[key]]) {
str += `${this.features[i][fieldKeys[key]][k].key + '' + this.features[i][fieldKeys[key]][k].value}&#10;`
}
ctx = {
nameType: 'String',
data: str
};
}
else {
ctx = {
nameType: 'String',
data: this.features[i][fieldKeys[key]] || "0"
};
}
rowsXML += format(tmplCellXML, ctx);
}
rowsXML += '</Row>';
if (i > 0 && (i / 60000) % 1 === 0) {
pil++;
ctx = { rows: rowsXML, nameWS: 'Sheet' + i };
worksheetsXML += format(tmplWorksheetXML, ctx);
rowsXML = "";
rowsXML += '<Row>' +
'<Cell><Data ss:Type="String">构件名称</Data></Cell>' +
'<Cell><Data ss:Type="String">体积</Data></Cell>' +
'<Cell><Data ss:Type="String">墩全高H</Data></Cell>' +
'<Cell><Data ss:Type="String">墩身高h</Data></Cell>' +
'<Cell><Data ss:Type="String">底部高程</Data></Cell>' +
'<Cell><Data ss:Type="String">承台宽</Data></Cell>' +
'<Cell><Data ss:Type="String">承台长</Data></Cell>' +
'<Cell><Data ss:Type="String">承台高</Data></Cell>' +
'<Cell><Data ss:Type="String">族</Data></Cell>' +
'<Cell><Data ss:Type="String">桩径</Data></Cell>' +
'<Cell><Data ss:Type="String">桩长</Data></Cell>' +
'<Cell><Data ss:Type="String">结构材质</Data></Cell>' +
'<Cell><Data ss:Type="String">完成情况</Data></Cell>' +
'<Cell><Data ss:Type="String">自定义属性</Data></Cell>' +
'</Row>';
}
}
}
}
ctx = { rows: rowsXML, nameWS: 'Sheet' };
worksheetsXML += format(tmplWorksheetXML, ctx);
rowsXML = "";
ctx = { created: (new Date()).getTime(), worksheets: worksheetsXML };
workbookXML = format(tmplWorkbookXML, ctx);
var link = document.createElement("A");
link.href = url + base64(workbookXML);
link.download = this.oldData.name + "--构件属性.xls"
link.target = '_blank';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
exportState(e) {
let checkbox = e.target.getElementsByTagName('input')[0]
checkbox.checked = !checkbox.checked
if (checkbox.checked) {
this.exportStateArray.push(checkbox.value)
this.exportStateArray = Array.from(new Set(this.exportStateArray))
}
else {
for (let i = 0; i < this.exportStateArray.length; i++) {
if (this.exportStateArray[i] == checkbox.value) {
this.exportStateArray.splice(i, 1)
break
}
}
}
}
}
export default BIM

View File

@ -0,0 +1,54 @@
function html() {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" @model="name">
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">高度</span>
<div class="input-number input-number-unit-3">
<input class="input" type="number" title="" @model="height">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">精度</span>
<div class="input-number input-number-unit-3">
<input class="input" type="number" title="" min="0.1" max="10" step="0.1" @model="accuracy">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">透视</span>
<input type="range" min="0" max="1" step="0.01" @model="transparency">
</div>
</div>
</div>
`
}
function css() {
return `
.YJ-custom-base-dialog>.content {
width: 420px;
}
.YJ-custom-base-dialog>.content .row .label {
flex: 0 0 45px;
}
`
}
export { html, css }

View File

@ -0,0 +1,87 @@
class eventBinding {
constructor() {
this.element = {}
}
static event = {}
getEvent(name) {
return eventBinding.event[name]
}
getEventAll() {
return eventBinding.event
}
setEvent(name, event) {
eventBinding.event[name] = event
}
on(that, elements) {
for (let i = 0; i < elements.length; i++) {
let Event = []
let isEvent = false
let removeName = []
if (!elements[i] || !elements[i].attributes) {
continue;
}
for (let m of elements[i].attributes) {
switch (m.name) {
case '@model': {
isEvent = true
if (elements[i].type == 'checkbox') {
Event.push((e) => { that[m.value] = e.target.checked })
elements[i].checked = that[m.value]
}
else {
Event.push((e) => {
let value = e.target.value
if(e.target.type == 'number') {
value = Number(value)
}
that[m.value] = value
})
if(elements[i].nodeName=='IMG') {
elements[i].src = that[m.value]
}
else {
elements[i].value = that[m.value]
}
}
this.element[m.value] = elements[i]
removeName.push(m.name)
break;
}
case '@click': {
elements[i].addEventListener('click', (e) => {
if (typeof (that.Dialog[m.value]) === 'function') {
that.Dialog[m.value](e)
}
});
removeName.push(m.name)
// elements[i].attributes.removeNamedItem(m.name)
break;
}
}
// elements[i].attributes[m] = undefined
}
for(let n=0;n<removeName.length;n++) {
elements[i].attributes.removeNamedItem(removeName[n])
}
if (isEvent) {
let ventType = 'input'
if (elements[i].tagName != 'INPUT' || elements[i].type == 'checkbox') {
ventType = 'change'
}
elements[i].addEventListener(ventType, (e) => {
for (let t = 0; t < Event.length; t++) {
Event[t](e)
}
});
}
}
}
}
const EventBinding = new eventBinding();
export default EventBinding;

View File

@ -0,0 +1,373 @@
/**
* @name: index
* @author: Administrator
* @date: 2023-11-20 16:05
* @descriptionindex
* @update: 2023-11-20 16:05
*/
import BaseTileset from "../index";
import cy_slider from "../../../../Element/cy_html_slider";
import { html, css } from "./_element";
import EventBinding from '../../../../Element/Dialog/eventBinding';
import { syncSplitData } from '../../../../../Global/SplitScreen'
import Dialog from '../../../../Element/Dialog';
class Tileset extends BaseTileset {
#updateModelTimeout;
/**
* @constructor
* @description 加载Tileset模型
* @param sdk {object} sdk
* @param options {object} 模型参数
* @param options.id {string} 对象id
* @param options.show=true {boolean} 模型显隐
* @param options.name {string} 名称
* @param options.url {string} 资源地址
* @param options.accuracy=1 {number} 精度(倍)
* @param options.position {object} 模型位置
* @param options.position.lng {number} 经度
* @param options.position.lat {number} 纬度
* @param options.position.alt {number} 高度
* */
constructor(earth, options = {}, _Dialog = {}) {
super(earth, options)
this.picking = false
this.Dialog = _Dialog
this._elms = {};
this._EventBinding = new EventBinding()
}
get type() {
return "tileset"
}
on() {
return this.add()
}
get name() {
return this.newData.name
}
set name(v) {
this.newData.name = v
this._elms.name && this._elms.name.forEach((item) => {
item.value = v
})
}
get height() {
return this.newData.height
}
set height(v) {
this.newData.height = v
this.options.position.alt = v
this._elms.height && this._elms.height.forEach((item) => {
item.value = v
})
this.updateModel(this.newData.lng, this.newData.lat, this.newData.height, this.newData.roll, this.newData.heading, this.newData.pitch)
}
get accuracy() {
return this.newData.accuracy
}
set accuracy(v) {
this.newData.accuracy = Number(v.toFixed(1))
if(this.newData.accuracy<0.1) {
this.newData.accuracy = 0.1
}
if(this.entity) {
this.entity.maximumScreenSpaceError = 32/this.newData.accuracy
}
this._elms.accuracy && this._elms.accuracy.forEach((item) => {
item.value = this.newData.accuracy
})
}
get lng() {
return this.newData.lng
}
set lng(v) {
this.newData.lng = v
this.options.position.lng = v
this.updateModel(this.newData.lng, this.newData.lat, this.newData.height, this.newData.roll, this.newData.heading, this.newData.pitch)
}
get lat() {
return this.newData.lat
}
set lat(v) {
this.newData.lat = v
this.options.position.lat = v
this.updateModel(this.newData.lng, this.newData.lat, this.newData.height, this.newData.roll, this.newData.heading, this.newData.pitch)
}
get roll() {
return this.newData.roll
}
set roll(v) {
this.newData.roll = v
this.updateModel(this.newData.lng, this.newData.lat, this.newData.height, this.newData.roll, this.newData.heading, this.newData.pitch, this.newData.scale)
}
get heading() {
return this.newData.heading
}
set heading(v) {
this.newData.heading = v
this.updateModel(this.newData.lng, this.newData.lat, this.newData.height, this.newData.roll, this.newData.heading, this.newData.pitch, this.newData.scale)
}
get pitch() {
return this.newData.pitch
}
set pitch(v) {
this.newData.pitch = v
this.updateModel(this.newData.lng, this.newData.lat, this.newData.height, this.newData.roll, this.newData.heading, this.newData.pitch, this.newData.scale)
}
get transparency() {
return this.newData.transparency
}
set transparency(v) {
if (!this.newData) {
return
}
this.newData.transparency = Number(v)
this._elms.transparency && this._elms.transparency.forEach((item) => {
item.value = v
})
let transparency = this.newData.transparency
// if (transparency == 1) {
// transparency = 0.99
// }
this.entity.style = new Cesium.Cesium3DTileStyle({
color: {
"conditions": [
//有size属性表示为点云需要与点颜色融合
["Boolean(${SIZE})", "${COLOR} * color('rgba(255,255,255)', " + transparency + ")"],
["true", "color('rgba(255,255,255," + transparency + ")')"]
]
},
show: true,
});
}
/**
* @description 编辑框
* @param state=false {boolean} 状态: true打开, false关闭
*/
async edit(state = false) {
let _this = this
this._element_style = null
// let elms = this.sdk.viewer._container.getElementsByClassName('YJ-custom-base-dialog')
// for (let i = elms.length - 1; i >= 0; i--) {
// this.sdk.viewer._container.removeChild(elms[i])
// }
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.newData, {
title: '倾斜模型属性', left: '180px', top: '100px',
confirmCallBack: (options) => {
this.oldData.name = this.newData.name
this.oldData.height = this.newData.height
this.oldData.lng = this.newData.lng
this.oldData.lat = this.newData.lat
this.oldData.transparency = this.newData.transparency
this.oldData.scale = this.newData.scale
this.oldData.roll = this.newData.roll
this.oldData.heading = this.newData.heading
this.oldData.pitch = this.newData.pitch
this.oldData.type = this.type
this.oldData.accuracy = this.newData.accuracy
this._DialogObject.close()
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack({ ...this.oldData, type: this.type })
syncSplitData(this.sdk, this.oldData.id)
},
resetCallBack: () => {
this.reset()
this.Dialog.resetCallBack && this.Dialog.resetCallBack()
},
removeCallBack: () => {
this.Dialog.removeCallBack && this.Dialog.removeCallBack()
},
closeCallBack: () => {
this.reset()
if (this.positionEditing) {
this.positionEditing = false
}
if (this.rotationEditing) {
this.rotationEditing = false
}
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
},
showCallBack: (show) => {
this.newData.show = show
this.entity && (this.entity.show = show)
this.Dialog.showCallBack && this.Dialog.showCallBack()
},
rotateCallBack: () => {
if (this.rotationEditing) {
this.rotationEditing = false
}
else {
this.rotationEditing = true
}
},
translationalCallBack: () => {
if (this.positionEditing) {
this.positionEditing = false
}
else {
this.positionEditing = true
}
}
}, 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
} 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
// }
}
}
//更新模型位置
updateModel(_tx, _ty, _tz, _rx = 0, _ry = 0, _rz = 0, s = 1) {
if (!this.tileset.root.transform) {
if (window.ELEMENT) {
window.ELEMENT.Message.closeAll();
window.ELEMENT.Message({
message: '该模型不支持移动和旋转!',
type: 'warning',
duration: 1500
});
}
console.warn('该模型不支持移动和旋转!')
return
}
if ((!_tx && _tx!==0) || (!_ty && _ty!==0) || (!_tz && _tz!==0)) {
return
}
let mx = Cesium.Matrix3.fromRotationX(
Cesium.Math.toRadians(_rx)
)
let my = Cesium.Matrix3.fromRotationY(
Cesium.Math.toRadians(_ry)
)
let mz = Cesium.Matrix3.fromRotationZ(
Cesium.Math.toRadians(_rz)
)
// 平移
let m = Cesium.Transforms.eastNorthUpToFixedFrame(new Cesium.Cartesian3.fromDegrees(_tx, _ty, _tz))
// 旋转
let rotationX = Cesium.Matrix4.fromRotationTranslation(mx)
let rotationY = Cesium.Matrix4.fromRotationTranslation(my)
let rotationZ = Cesium.Matrix4.fromRotationTranslation(mz)
let originalMatrix = new Cesium.Matrix4()
Cesium.Matrix4.multiply(m, rotationX, originalMatrix)
Cesium.Matrix4.multiply(originalMatrix, rotationY, originalMatrix)
Cesium.Matrix4.multiply(originalMatrix, rotationZ, originalMatrix)
const scale = Cesium.Matrix4.fromUniformScale(s);
Cesium.Matrix4.multiply(originalMatrix, scale, this.entity._root.transform)
// console.log(_tx, _ty, _tz)
if (!this.editObj.activeAxis) {
this.editObj.position = { lng: _tx, lat: _ty, alt: _tz }
}
if (!this.editObj.activeCircle) {
this.editObj.rotate = { x: _rx, y: _ry, z: _rz }
}
this.editObj && this.editObj.update()
clearTimeout(this.#updateModelTimeout)
this.#updateModelTimeout = setTimeout(() => {
clearTimeout(this.#updateModelTimeout)
let center = this.cartesian3Towgs84(this.entity.boundingSphere.center, this.sdk.viewer)
let circle = turf.circle([center.lng, center.lat], this.entity.boundingSphere.radius / 1000, { steps: 360, units: 'kilometers' });
for (let [key, entity] of this.sdk.entityMap) {
if (entity.type === 'BillboardObject' && entity.heightMode == 3) {
let pt = turf.point([entity.lng, entity.lat]);
if (turf.booleanPointInPolygon(pt, circle)) {
entity.updateHeight()
}
}
else {
if (entity.label) {
entity.label.show = entity.label.show
}
}
}
}, 300);
}
// flyTo() {
// this.entity.readyPromise.then(() => {
// console.log(this.entity)
// let boundingSphere
// if(!this.lng || !this.lat) {
// boundingSphere = new Cesium.BoundingSphere(this.entity.boundingSphere)
// }
// else {
// boundingSphere = new Cesium.BoundingSphere(Cesium.Cartesian3.fromDegrees(this.lng, this.lat, this.height), this.entity.boundingSphere.radius)
// }
// this.sdk.viewer.camera.flyToBoundingSphere(boundingSphere)
// })
// }
reset() {
this.editObj.destroy()
if (!this.entity) {
return
}
this.transparency = this.oldData.transparency
this.name = this.oldData.name
this.height = this.oldData.height
this.lng = this.oldData.lng
this.lat = this.oldData.lat
this.roll = this.oldData.roll
this.heading = this.oldData.heading
this.pitch = this.oldData.pitch
this.scale = this.oldData.scale
this.accuracy = this.oldData.accuracy
this.entity.style = new Cesium.Cesium3DTileStyle({
color: {
"conditions": [
["Boolean(${SIZE})", "${COLOR} * color('rgba(255,255,255)', " + this.transparency + ")"],
["true", "color('rgba(255,255,255," + this.transparency + ")')"]
]
},
show: true,
});
}
}
export default Tileset

View File

@ -0,0 +1,650 @@
/**
* @name: index
* @author: Administrator
* @date: 2023-11-20 17:54
* @descriptionindex
* @update: 2023-11-20 17:54
*/
import { getHost } from "../../../../on";
import BaseSource from "../index";
import { regLeftClickCallback, regRightClickCallback, regMoveCallback } from "../../../../Global/ClickCallback";
import Controller from "../../../../Controller/index";
import { syncData } from '../../../../Global/MultiViewportMode'
import { setSplitDirection, syncSplitData, setActiveId } from '../../../../Global/SplitScreen'
class BaseTileset extends BaseSource {
#updateModelTimeout;
/**
* @constructor
* @param sdk
* @description 模型
* @param options {object}
* @param options.id{string} id
* @param options.name{string} 名称
* @param options.url{string} 模型地址
* @param options.lng{number} 经度
* @param options.lat{number} 纬度
* @param options.height=0{number} 高度
* @param options.scale=1{number} 模型比例
* @param options.roll=0{number} 模型x旋转
* @param options.heading=0{number} 模型z轴旋转角度
* @param options.pitch=0{number} 模型y轴旋转角度
* */
constructor(sdk, options) {
super(sdk, options);
this.setDefaultValue()
this.watchs = []
this.positionCallBack = null
this.rotationCallback = null
this.onClickCallback = null
this._DialogObject = null
this._element_style = null
this.options.accuracy = options.accuracy ? Number(options.accuracy.toFixed(1)) : 1
this.options.position = this.options.position || {}
this.oldData = {
id: this.options.id,
transparency: (this.options.transparency || this.options.transparency === 0) ? this.options.transparency : 1,
name: this.options.name,
accuracy: this.options.accuracy,
url: this.options.url,
height: this.options.position.alt || 0,
lng: this.options.position.lng,
lat: this.options.position.lat,
scale: (this.options.scale || this.options.scale === 0) ? this.options.scale : 1,
roll: this.options.roll || 0,
heading: this.options.heading || 0,
pitch: this.options.pitch || 0
}
this.newData = {
id: this.options.id,
transparency: (this.options.transparency || this.options.transparency === 0) ? this.options.transparency : 1,
name: this.options.name,
accuracy: this.options.accuracy,
url: this.options.url,
height: this.options.position.alt || 0,
lng: this.options.position.lng,
lat: this.options.position.lat,
scale: (this.options.scale || this.options.scale === 0) ? this.options.scale : 1,
roll: this.options.roll || 0,
heading: this.options.heading || 0,
pitch: this.options.pitch || 0
}
this.tileset = undefined
this.editObj = new Controller(this.sdk)
this.editObj.controllerCallBack = this.rotationEditingCallBack
}
async add() {
if (this.options.url) {
return this.loadTileset({
url: this.options.url
})
} else {
let res = await this.requestResource()
let text = await res.text()
text = JSON.parse(text)
if ([0, 200].includes(text.code)) {
if (text.data.url.length)
return this.loadTileset(text.data)
else
return new Promise((res, reject) => {
reject('资源不存在')
})
} else {
return new Promise((res, reject) => {
reject(text.msg || text.message)
})
}
}
}
loadSceneTree() {
}
async loadTileset(options) {
let object = { ...options }
let url = ""
if (object.url.startsWith("http"))
url = object.url
else {
//说明是本地的json在磁盘中存在的
if (object.url.includes(":")) {
url = object.url
} else {
if (this.options.host) {
let o = new URL(object.url, this.options.host)
url = o.href
} else
url = object.url
}
}
let response = await fetch(url, {
method: 'get',
headers: {
'Content-Type': 'application/json',
}
})
if (response.status === 200) {
this.tileset = await response.json()
}
let params = {
show: this.options.show,
skipLevelOfDetail: true,
baseScreenSpaceError: 1024,
maximumScreenSpaceError: 32, // 数值加大,能让最终成像变模糊
skipScreenSpaceErrorFactor: 16,
skipLevels: 1,
immediatelyLoadDesiredLevelOfDetail: false,
loadSiblings: true, // 如果为true则不会在已加载完概况房屋后自动从中心开始超清化房屋
cullWithChildrenBounds: true,
cullRequestsWhileMoving: true,
cullRequestsWhileMovingMultiplier: 10, // 值越小能够更快的剔除
preloadWhenHidden: false,
preferLeaves: true,
maximumCacheOverflowBytes: 128, // 内存分配变小有利于倾斜摄影数据回收,提升性能体验
progressiveResolutionHeightFraction: 0.5, // 数值偏于0能够让初始加载变得模糊
dynamicScreenSpaceErrorDensity: 0.1, // 数值加大,能让周边加载变快
dynamicScreenSpaceErrorFactor: 1,
dynamicScreenSpaceError: true // 有了这个后,会在真正的全屏加载完之后才清晰化房屋
}
let tileset
if (Number(Cesium.VERSION.split('.')[1]) >= 107) {
tileset = await Cesium.Cesium3DTileset.fromUrl(url, params);
this.entity = tileset
this.entity.imageBasedLighting.luminanceAtZenith = 0.1
}
else {
params.url = url
tileset = new Cesium.Cesium3DTileset(params);
this.entity = await tileset.readyPromise
this.entity.imageBasedLighting.luminanceAtZenith = 0.1
}
// syncData(this.sdk, this.options.id)
await this.loadSceneTree(url)
const initData = (tile) => {
if (tile._contents) {
for (let i = 0; i < tile._contents.length; i++) {
initData(tile._contents[i])
}
}
else {
for (let i = 0; i < tile.featuresLength; i++) {
let feature = tile.getFeature(i)
let file = feature.content.url
let id = feature.getProperty('id')
if (this.features.has(id)) {
if (this.features.get(id).features) {
if (this.features.get(id).features[file]) {
// feature = this.features.get(id).features[feature.featureId]
if (this.features.get(id).features[file].customColor) {
feature.color = this.features.get(id).features[file].customColor
feature.customColor = this.features.get(id).features[file].customColor
}
if (this.features.get(id).features[file].customAlpha) {
let color = feature.color
feature.color = Cesium.Color.fromCssColorString(`rgba(${Cesium.Color.floatToByte(color.red)},${Cesium.Color.floatToByte(color.green)},${Cesium.Color.floatToByte(color.blue)},${this.features.get(id).features[file].customAlpha})`)
feature.customAlpha = this.features.get(id).features[file].customAlpha
}
if (this.features.get(id).features[file].customShow) {
feature.show = this.features.get(id).features[file].customShow
feature.customShow = this.features.get(id).features[file].customShow
}
}
this.features.get(id).features[file] = feature
}
else {
let object = {}
if (this.features.get(id).customColor) {
feature.color = this.features.get(id).customColor
feature.customColor = this.features.get(id).customColor
}
if (this.features.get(id).customAlpha) {
let color = feature.color
feature.color = Cesium.Color.fromCssColorString(`rgba(${Cesium.Color.floatToByte(color.red)},${Cesium.Color.floatToByte(color.green)},${Cesium.Color.floatToByte(color.blue)},${this.features.get(id).customAlpha})`)
feature.customAlpha = this.features.get(id).customAlpha
}
if (this.features.get(id).customShow) {
feature.show = this.features.get(id).customShow
feature.customShow = this.features.get(id).customShow
}
object[file] = feature
this.features.get(id).features = object
}
}
else {
let object = {}
object[file] = feature
this.features.set(id, { features: object })
}
if (!feature.customColor) {
feature.customColor = Cesium.Color.fromCssColorString('#ffffff')
}
}
}
// for (let i = 0; i < tile._content.featuresLength; i++) {
// let feature = tile._content.getFeature(i)
// feature.show = false
// }
// if (tile._content._contents) {
// for (let i = 0; i < tile._content._contents.length; i++) {
// for (let m = 0; m < tile._content._contents[i].featuresLength; m++) {
// let feature = tile._content._contents[i].getFeature(m)
// feature.show = false
// }
// }
// }
}
if (!this.sdk || !this.sdk.viewer || !this.sdk.viewer.scene) {
return
}
tileset.tileLoad.addEventListener(tile => {
// this.test()
initData(tile._content)
clearTimeout(this.#updateModelTimeout)
this.#updateModelTimeout = setTimeout(() => {
clearTimeout(this.#updateModelTimeout)
let center = this.cartesian3Towgs84(tileset.boundingSphere.center, this.sdk.viewer)
let circle = turf.circle([center.lng, center.lat], tileset.boundingSphere.radius / 1000, { steps: 360, units: 'kilometers' });
for (let [key, entity] of this.sdk.entityMap) {
if (entity.type === 'BillboardObject' && entity.heightMode == 3) {
let pt = turf.point([entity.lng, entity.lat]);
if (turf.booleanPointInPolygon(pt, circle)) {
entity.updateHeight()
}
}
else {
if (entity.label) {
entity.label.show = entity.label.show
}
}
}
}, 500);
// if (tile._content._contents) {
// for (let i = 0; i < tile._content._contents.length; i++) {
// for (let m = 0; m < tile._content._contents[i].featuresLength; m++) {
// let feature = tile._content._contents[i].getFeature(m)
// console.log(feature)
// feature.show = false
// }
// }
// }
// for (let i = 0; i < tile._content.featuresLength; i++) {
// let feature = tile._content.getFeature(i)
// let file = feature.content.url
// let id = feature.getProperty('id')
// if (this.features.has(id)) {
// if (this.features.get(id).features) {
// if (this.features.get(id).features[file]) {
// // feature = this.features.get(id).features[feature.featureId]
// if (this.features.get(id).features[file].customColor) {
// feature.color = this.features.get(id).features[file].customColor
// feature.customColor = this.features.get(id).features[file].customColor
// }
// if (this.features.get(id).features[file].customAlpha) {
// let color = feature.color
// feature.color = Cesium.Color.fromCssColorString(`rgba(${Cesium.Color.floatToByte(color.red)},${Cesium.Color.floatToByte(color.green)},${Cesium.Color.floatToByte(color.blue)},${this.features.get(id).features[file].customAlpha})`)
// feature.customAlpha = this.features.get(id).features[file].customAlpha
// }
// if (this.features.get(id).features[file].customShow) {
// feature.show = this.features.get(id).features[file].customShow
// feature.customShow = this.features.get(id).features[file].customShow
// }
// }
// this.features.get(id).features[file] = feature
// }
// else {
// let object = {}
// object[file] = feature
// this.features.get(id).features = object
// }
// }
// else {
// let object = {}
// object[file] = feature
// this.features.set(id, { features: object })
// }
// if (!feature.customColor) {
// feature.customColor = Cesium.Color.fromCssColorString('#ffffff')
// }
// }
})
// // console.log(tileset)
// if (this.type === 'bim') {
// const setTilesetStyle = (f) => {
// if (tileset.style) {
// // tileset.style = new Cesium.Cesium3DTileStyle({
// // color: {
// // conditions: [
// // ['${name} ==="对象074" ', 'color("red")'], //符合条件项
// // ['true', 'rgba(255,255,255,1)'] //其他项
// // ]
// // }
// // })
// // tileset.tileLoad.removeEventListener(setTilesetStyle)
// }
// console.log(f)
// }
// tileset.tileLoad.addEventListener(setTilesetStyle)
// }
this.entity._root.originalTransform = { ...this.entity._root.transform }
this.entity.id = this.options.id || this.randomString()
this.entity.type = this.type
// this.editObj = new EditB3DM(this.sdk, this.entity)
this.sdk.viewer.scene.primitives.add(tileset);
if (this.options.position && JSON.stringify(this.options.position) != "{}"
&& (this.options.position.lng || this.options.position.lng === 0) && (this.options.position.lat || this.options.position.lat === 0)) {
this.options.position.alt == this.options.position.alt || 0
let cartographic = Cesium.Cartographic.fromCartesian(this.entity.boundingSphere.center);
if (this.tileset.root.transform) {
cartographic = Cesium.Cartographic.fromCartesian({ x: this.tileset.root.transform[12], y: this.tileset.root.transform[13], z: this.tileset.root.transform[14] })
}
this.entity.original = {
lng: Cesium.Math.toDegrees(cartographic.longitude), // 经度
lat: Cesium.Math.toDegrees(cartographic.latitude), // 纬度
height: cartographic.height
}
let m = Cesium.Transforms.eastNorthUpToFixedFrame(new Cesium.Cartesian3.fromDegrees(this.options.position.lng, this.options.position.lat, this.options.position.alt))
const scale = Cesium.Matrix4.fromUniformScale(this.oldData.scale);
if (this.tileset.root.transform) {
Cesium.Matrix4.multiply(m, scale, this.entity._root.transform)
}
this.lng = this.oldData.lng
this.lat = this.oldData.lat
this.height = this.oldData.height
}
else {
this.options.position = {}
let cartographic = Cesium.Cartographic.fromCartesian(this.entity.boundingSphere.center);
if (this.tileset.root.transform) {
cartographic = Cesium.Cartographic.fromCartesian({ x: this.tileset.root.transform[12], y: this.tileset.root.transform[13], z: this.tileset.root.transform[14] })
}
this.entity.original = {
lng: Cesium.Math.toDegrees(cartographic.longitude),
lat: this.oldData.lat = Cesium.Math.toDegrees(cartographic.latitude),
height: cartographic.height,
}
this.lng = this.oldData.lng = Cesium.Math.toDegrees(cartographic.longitude); // 经度
this.lat = this.oldData.lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
this.height = this.oldData.height = cartographic.height; // 高度
}
this.scale = this.oldData.scale
this.roll = this.oldData.roll
this.heading = this.oldData.heading
this.pitch = this.oldData.pitch
this.transparency = this.oldData.transparency
syncSplitData(this.sdk, this.options.id)
regMoveCallback(this.entity.id, this.mouseMoveCB, this)
// this.entity = this.sdk.viewer.scene.primitives.add(tileset);
// if (this.options.position && JSON.stringify(this.options.position) != "{}") {
// let m = Cesium.Transforms.eastNorthUpToFixedFrame(new Cesium.Cartesian3.fromDegrees(this.options.position.lng, this.options.position.lat, this.options.position.alt))
// const scale = Cesium.Matrix4.fromUniformScale(this.oldData.scale);
// Cesium.Matrix4.multiply(m, scale, this.entity._root.transform)
// }
// else {
// this.options.position = {}
// }
// this.lng = this.oldData.lng
// this.lat = this.oldData.lat
// this.height = this.oldData.height
// this.scale = this.oldData.scale
// this.roll = this.oldData.roll
// this.heading = this.oldData.heading
// this.pitch = this.oldData.pitch
// this.transparency = this.oldData.transparency
// regMoveCallback(this.entity.id, this.mouseMoveCB, this)
// this.editObj = new EditB3DM(this.sdk, this.entity)
// this.editObj.transformCallBack = this.rotationEditingCallBack
// tileset.readyPromise.then(() => {
// this.entity = this.sdk.viewer.scene.primitives.add(tileset);
// })
// let x = this.sdk.viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
// url: url
// }));
// setTimeout(() => {
// console.log(x)
// this.sdk.viewer.flyTo(this.entity)
// }, 3000);
}
// test() {
// let heightstyle = new Cesium.Cesium3DTileStyle({
// color: {
// conditions: [
// ["Number(${height})>=300", "rgba(45,0,75,0.5)"],
// ["Number(${height})>=200", "rgb(102,71,151)"],
// ["Number(${height})>=100", "rgb(170,162,204)"],
// ["Number(${height})>=50", "rgb(224,226,238)"],
// ["Number(${height})>=25", "rgb(252,230, 200)"],
// ["Number(${height})>=10", "rgb(248,176,87)"],
// ["Number(${height})>=5", "rgb(198, 106,11)"],
// ["isNaN(Number(${height}))", "rgb(255, 255, 255)"],
// ["true", "rgb(127,59,8)"]
// ]
// }
// });
// this.entity.style = heightstyle;
// }
remove() {
super.remove()
this.editObj.destroy()
this.sdk.viewer.scene.primitives.remove(this.entity);
this.entity = null
if (this._DialogObject) {
this._DialogObject.close()
this._DialogObject = null
}
}
flyTo() {
super.flyTo()
}
on() {
return this.add()
}
setDefaultValue() {
super.setDefaultValue()
this.options.host = this.options.host || getHost()
this.options.url = this.options.url || ""
}
get position() {
let cartographic = Cesium.Cartographic.fromCartesian(this.entity.boundingSphere.center);
if (this.tileset.root.transform) {
cartographic = Cesium.Cartographic.fromCartesian({ x: this.tileset.root.transform[12], y: this.tileset.root.transform[13], z: this.tileset.root.transform[14] })
}
let lng = Cesium.Math.toDegrees(cartographic.longitude + 0.00000000663814);
let lat = Cesium.Math.toDegrees(cartographic.latitude + 0.00000025137835);
if (this.newData.lng && this.newData.lat && this.newData.height) {
return { lng: this.newData.lng, lat: this.newData.lat, height: this.newData.height }
}
else {
return { lng: lng, lat: lat, height: cartographic.height - 2.19104611043234 }
}
}
set position(p) {
}
/**
* @desc 打开模型旋转功能
* @param status {boolean}
* @methodOf Source
* */
set rotationEditing(status) {
if (!this.tileset.root.transform) {
if (window.ELEMENT) {
window.ELEMENT.Message.closeAll();
window.ELEMENT.Message({
message: '该模型不支持移动和旋转!',
type: 'warning',
duration: 1500
});
}
console.warn('该模型不支持移动和旋转!')
return
}
if (status) {
this.editObj.position = { lng: this.newData.lng, lat: this.newData.lat, alt: this.newData.height }
this.editObj.update()
this.editObj.editRtation()
}
else {
this.editObj.destroy()
}
}
/**
* @desc 获取模型旋转状态
* @method rotationEditing
* @return boolean
* @methodOf Source
* */
get rotationEditing() {
if (this.editObj.getActiveState() === 'rtation') {
return true
}
return false
}
/**@desc 打开平移模型功能
*
* @memberOf Source
*@param status {boolean}
*
* */
set positionEditing(status) {
if (!this.sdk || !this.sdk.viewer || !this.entity) {
return
}
if (!this.tileset.root.transform) {
if (window.ELEMENT) {
window.ELEMENT.Message.closeAll();
window.ELEMENT.Message({
message: '该模型不支持移动和旋转!',
type: 'warning',
duration: 1500
});
}
console.warn('该模型不支持移动和旋转!')
return
}
if (status) {
this.editObj.position = { lng: this.newData.lng, lat: this.newData.lat, alt: this.newData.height }
this.editObj.update()
this.editObj.editTranslational()
}
else {
this.editObj.destroy()
}
}
get positionEditing() {
if (this.editObj.getActiveState() === 'translational') {
return true
}
return false
}
//平移时,坐标信息变化的回调
set positionEditingCallBack(callback) {
return
}
get positionEditingCallBack() {
}
//旋转时,坐标信息变化的回调
set rotationEditingCallBack(callback) {
this._rotationEditingCallBack = callback
}
get rotationEditingCallBack() {
return (params, state) => {
this.lng = params.position.lng
this.lat = params.position.lat
this.height = params.position.alt
this.roll = params.rotate.x
this.heading = params.rotate.y
this.pitch = params.rotate.z
// this._rotationEditingCallBack && this._rotationEditingCallBack(this.editObj._params)
}
}
flicker() { }
// 编辑框
async edit(state) { }
get show() {
return this.options.show
}
set show(v) {
if (typeof v === "boolean") {
this.options.show = v
this.entity && (this.entity.show = v)
if (this._DialogObject && this._DialogObject.showBtn) {
this._DialogObject.showBtn.checked = v
}
if (this.options.label && this.options.label.show && this.label) {
this.label.show = v
}
setTimeout(() => {
let center = this.cartesian3Towgs84(this.entity.boundingSphere.center, this.sdk.viewer)
let circle = turf.circle([center.lng, center.lat], this.entity.boundingSphere.radius / 1000, { steps: 360, units: 'kilometers' });
for (let [key, entity] of this.sdk.entityMap) {
if (entity.type === 'BillboardObject' && entity.heightMode == 3) {
let pt = turf.point([entity.lng, entity.lat]);
if (turf.booleanPointInPolygon(pt, circle)) {
entity.updateHeight()
}
}
else {
if (entity.label) {
entity.label.show = entity.label.show
}
}
}
syncData(this.sdk, this.options.id)
syncSplitData(this.sdk, this.options.id)
}, 300);
} else {
console.error("参数必须为boolean")
}
}
}
export default BaseTileset

View File

@ -0,0 +1,45 @@
/**
* @name: index
* @author: Administrator
* @date: 2023-11-20 18:31
* @descriptionindex
* @update: 2023-11-20 18:31
*/
import Base from "../index";
import {getHost, getToken} from "../../../on";
import { setSplitDirection } from "../../../Global/SplitScreen";
class BaseSource extends Base {
constructor(sdk, options) {
super(sdk, options);
this.sdk.addIncetance(this.options.id, this)
if (this.options.show) {
setSplitDirection(0, this.options.id)
}
}
setDefaultValue() {
super.setDefaultValue();
this.options.host = this.options.host || getHost()
}
requestResource() {
let url = ""
if (this.options.host.endsWith("yjearth4.0"))
url = this.options.host + '/data/service/load-compact-service'
else
url = this.options.host + '/yjearth4.0/data/service/load-compact-service'
return fetch(url, {
method: 'post',
body: JSON.stringify({source_id: this.options.id}),
headers: {
'Content-Type': 'application/json',
"token": getToken(),
"Authorization": "Bearer " + getToken(),
}
})
}
}
export default BaseSource

View File

@ -0,0 +1,24 @@
function html() {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col add-type-box">
<span class="label" style="flex: 0 0 56px;">添加方式</span>
<div class="add-type"></div>
</div>
<div class="col">
<span class="label">间距</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="1" max="99999" @model="spacing">
<span class="unit">米</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,229 @@
import { attributeElm } from '../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">颜色</span>
<div class="color"></div>
</div>
<div class="col">
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div style="width: 46%;">
<div class="row add-type-box">
<div class="lable-left-line">添加方式
<div class="input input-select add-type" style="margin-left: 20px;"></div>
</div>
</div>
</div>
<div style="width: 50%;">
<div class="row" style="margin-bottom: 5px;">
<div class="col">
<span class="label">朝向偏移</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="0" max="360" @model="deviation">
<span class="unit">°</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
</div>
<h4>模型间隔</h4>
<div class="row">
<div class="col">
<div class="YJ-custom-checkbox-box" style="display: flex;align-items: center;cursor: pointer;">
<input type="checkbox" class="YJ-custom-checkbox">
<span style="margin-left: 10px; margin-bottom: 1px;user-select: none;">自定义距离</span>
</div>
</div>
<div class="col">
<div class="YJ-custom-checkbox-box" style="display: flex;align-items: center;cursor: pointer;">
<input type="checkbox" class="YJ-custom-checkbox">
<span style="margin-left: 10px; margin-bottom: 1px;user-select: none;">固定距离</span>
</div>
</div>
<div class="col">
<span class="label">模型间隔</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="0" max="360" @model="spacing">
<span class="unit">米</span>
<span class="arrow"></span>
</div>
</div>
</div>
<h4>线型选择</h4>
<div class="row">
<div class="col">
<div class="YJ-custom-checkbox-box" style="display: flex;align-items: center;cursor: pointer;">
<input type="checkbox" class="YJ-custom-checkbox">
<span style="margin-left: 10px; margin-bottom: 1px;user-select: none;">折线</span>
</div>
</div>
<div class="col">
<div class="YJ-custom-checkbox-box" style="display: flex;align-items: center;cursor: pointer;">
<input type="checkbox" class="YJ-custom-checkbox">
<span style="margin-left: 10px; margin-bottom: 1px;user-select: none;">曲线</span>
</div>
</div>
<div class="col">
<span class="label">线条数量</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="0" max="360" @model="lineNum">
<span class="unit">条</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">线条间隔</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="0" max="360" @model="lineSpacing">
<span class="unit">米</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="YJ-custom-checkbox-box" style="display: flex;align-items: center;cursor: pointer;">
<input type="checkbox" class="YJ-custom-checkbox">
<span style="margin-left: 10px; margin-bottom: 1px;user-select: none;">随机采样</span>
</div>
</div>
<div class="col">
<span class="label">随机数量</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="0" max="360" @model="lineNum">
<span class="unit">个</span>
<span class="arrow"></span>
</div>
</div>
<div class="col"></div>
</div>
<div class="row">
<div class="col">
<div class="YJ-custom-checkbox-box" style="display: flex;align-items: center;cursor: pointer;">
<input type="checkbox" class="YJ-custom-checkbox">
<span style="margin-left: 10px; margin-bottom: 1px;user-select: none;">网格采样</span>
</div>
</div>
<div class="col">
<span class="label">首边间隔</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="0" max="360" @model="fistLineSpacing">
<span class="unit">米</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">次边间隔</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="0" max="360" @model="secondLineSpacing">
<span class="unit">米</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="row">
<DIV-cy-tabs id="point-object-edit-tabs">
<DIV-cy-tab-pane label="空间信息">
<div class="row">
<div class="col height-mode-box">
<span class="label" style="flex: 0 0 56px;">高度模式</span>
<div class="height-mode"></div>
</div>
</div>
<div class="row">
<div style="width: 46%;">
<div class="row add-type-box">
<div class="lable-left-line">缩放
<div class="YJ-custom-checkbox-box" style="display: flex;align-items: center;cursor: pointer;">
<input type="checkbox" class="YJ-custom-checkbox">
<span style="margin-left: 10px; margin-bottom: 1px;user-select: none;">是否等比例缩放</span>
</div>
</div>
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
<div>
<div class="row" style="margin-bottom: 10px;">
<div class="col">
<span class="label">新增模型风格设置</span>
<button @click="openRichTextEditor">初始风格</button>
</div>
<div class="col">
<button @click="openRichTextEditor">当前风格</button>
</div>
</div>
<div class="row" style="margin-bottom: 10px;">
<div class="col" style="flex: 0 0 80px;">
<span class="label" style="flex: none;">显隐</span>
<input class="btn-switch" type="checkbox" @model="billboardShow">
</div>
<div class="col" style="flex: 0 0 90px;">
<span class="label" style="flex: none;">图标</span>
<div class="image-box" @click="clickChangeImage">
<img class="image" src="" alt="" @model="billboardImage">
</div>
</div>
<div class="col" style="flex: 0 0 90px;">
<span class="label" style="flex: none;">默认图标</span>
<div class="image-box" @click="clickChangeDefaultImage">
<img class="image" src="" alt="" @model="billboardDefaultImage">
</div>
</div>
<div class="col">
<span class="label">图标倍数</span>
<div class="input-number input-number-unit-2">
<input class="input" type="number" title="" min="0.1" max="99" @model="billboardScale">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<div>
<h4>文字设置</h4>
<div class="row">
<div class="col" style="flex: 0 0 80px;">
<span class="label" style="flex: none;">显隐</span>
<input class="btn-switch" type="checkbox" @model="labelShow">
</div>
<div class="col font-select-box">
<span class="label" style="flex: none;">字体选择</span>
<div class="input input-select font-select"></div>
</div>
<div class="col">
<span class="label">文字大小</span>
<div class="input-number input-number-unit-2">
<input class="input" type="number" title="" min="1" max="99" @model="labelFontSize" style="width: 70px;">
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">文字颜色</span>
<div class="labelColor"></div>
</div>
</div>
</div>
</DIV-cy-tab-pane>
</DIV-cy-tabs>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,92 @@
class eventBinding {
constructor() {
this.element = {}
}
static event = {}
getEvent(name) {
return eventBinding.event[name]
}
getEventAll() {
return eventBinding.event
}
setEvent(name, event) {
eventBinding.event[name] = event
}
on(that, elements) {
for (let i = 0; i < elements.length; i++) {
let Event = []
let isEvent = false
let removeName = []
if (!elements[i] || !elements[i].attributes) {
continue;
}
for (let m of elements[i].attributes) {
switch (m.name) {
case '@model': {
isEvent = true
if (elements[i].type == 'checkbox') {
Event.push((e) => { that[m.value] = e.target.checked })
elements[i].checked = that[m.value]
}
else {
Event.push((e) => {
let value = e.target.value
if (e.target.type == 'number') {
value = Number(value)
}
that[m.value] = value
})
if (elements[i].nodeName == 'IMG') {
elements[i].src = that[m.value]
}
else {
elements[i].value = that[m.value]
}
}
if (this.element[m.value]) {
this.element[m.value].push(elements[i])
}
else {
this.element[m.value] = [elements[i]]
}
removeName.push(m.name)
break;
}
case '@click': {
elements[i].addEventListener('click', (e) => {
if (typeof (that.Dialog[m.value]) === 'function') {
that.Dialog[m.value](e)
}
});
removeName.push(m.name)
// elements[i].attributes.removeNamedItem(m.name)
break;
}
}
// elements[i].attributes[m] = undefined
}
for (let n = 0; n < removeName.length; n++) {
elements[i].attributes.removeNamedItem(removeName[n])
}
if (isEvent) {
let ventType = 'input'
if (elements[i].tagName != 'INPUT' || elements[i].type == 'checkbox') {
ventType = 'change'
}
elements[i].addEventListener(ventType, (e) => {
for (let t = 0; t < Event.length; t++) {
Event[t](e)
}
});
}
}
}
}
const EventBinding = new eventBinding();
export default EventBinding;

View File

@ -0,0 +1,713 @@
/**
* @description 批量模型
*/
import Dialog from '../../Element/Dialog';
import { html } from "./_element";
import EventBinding from '../../Element/Dialog/eventBinding';
import Base from "../index";
import Tools from "../../../Tools";
import { syncData } from '../../../Global/MultiViewportMode'
import Model from '../BaseSource/BaseModel/Model'
import { legp } from '../../Element/datalist'
import DrawPolyline from '../../../Draw/drawPolyline'
import DrawPolygon from '../../../Draw/drawPolygon'
import DrawThreeRect from '../../../Draw/drawThreeRect'
import DrawPoint from '../../../Draw/drawPoint'
import { setActiveViewer, closeRotateAround, closeViewFollow, CesiumContainer } from '../../../Global/global'
import { setSplitDirection, syncSplitData, setActiveId } from '../../../Global/SplitScreen'
class BatchModel extends Base {
/**
* @constructor
* @param sdk
* @description 批量模型
* @param options {object} 批量模型属性
* @param options.name=未命名对象 {string} 名称
* @param options.type=polygon {string} 线类型(line,polygon)
* @param options.url=polygon {string} 线类型(line,polygon,point)
* @param options.spacing= {number} 间距
* @param options.show=true {boolean}
* @param Dialog {object} 弹框对象
* @param Dialog.confirmCallBack {function} 弹框确认时的回调
* */
constructor(sdk, options = {}, callback = null, _Dialog = {}) {
super(sdk, options);
this.viewer = this.sdk.viewer
this.options.name = options.name || '批量模型'
this.options.type = options.type || '面'
this.options.url = options.url || ''
this.options.spacing = options.spacing * 1 || 50
this.options.positions = options.positions || []
this.options.show = (options.show || options.show === false) ? options.show : true
this.callback = callback
this.Dialog = _Dialog
this._EventBinding = new EventBinding()
this._elms = {};
this.pointArr = []
this.sdk.addIncetance(this.options.id, this)
let tools = new Tools(sdk)
// BatchModel.computeDis(this)
// if (this.options.positions.length > 0 || this.options.positions.lng) {
if (this.options.spacing < 0 || options.spacing * 1 === 0) {
tools.message({ type: 'warning', text: '请输入正确的间距!' })
return;
}
if ((options.type && options.spacing != undefined) || options.type == '点') {
// BatchModel.computeDis(this)
let Draw
switch (options.type) {
case '点':
Draw = new DrawPoint(this.sdk)
break;
case '线':
Draw = new DrawPolyline(this.sdk)
break;
case '面':
Draw = new DrawThreeRect(this.sdk)
break;
default:
break;
}
Draw && Draw.start((a, positions) => {
this.options.positions = positions;
//判断范围是否过大
if (options.type == '面') {
let posi = positions.map(v => {
return Cesium.Cartesian3.fromDegrees(v.lng, v.lat)
})
let dis1 = Cesium.Cartesian3.distance(posi[0], posi[1])
let dis2 = Cesium.Cartesian3.distance(posi[1], posi[2])
let num1 = dis1 / this.options.spacing
let num2 = dis2 / this.options.spacing
if (num1 * num2 > 100) {
tools.message({ type: 'warning', text: '数量大于100请重新绘制' })
return;
}
} else if (options.type == '线') {
let posi = positions.map(v => {
return Cesium.Cartesian3.fromDegrees(v.lng, v.lat)
})
let dis = 0
for (let i = 0; i < posi.length - 2; i++) {
dis += Cesium.Cartesian3.distance(posi[i], posi[i + 1])
}
if (dis / this.options.spacing > 100) {
tools.message({ type: 'warning', text: '数量大于100请重新绘制' })
return;
}
}
// this.callback(this.options);
(this.options.positions.length || this.options.positions.lng) && BatchModel.computeDis(this)
})
} else {
this.edit(true)
}
}
// 计算距离
static async computeDis(that) {
let fromDegreesArray = []
let arr
let posiArr = []
let array = []
if (that.options.type == '面') {
that.options.positions.forEach(item => {
fromDegreesArray.push(item.lng, item.lat)
})
// arr = that.generateInterpolatedPoints(Cesium.Cartesian3.fromDegreesArray(fromDegreesArray), that.options.spacing)
arr = await that.computedArea(Cesium.Cartesian3.fromDegreesArray(fromDegreesArray), that.options.spacing)
array[0] = arr
array[1] = that.calculateRoadAngle(Cesium.Cartesian3.fromDegreesArray(fromDegreesArray)[0], Cesium.Cartesian3.fromDegreesArray(fromDegreesArray)[3])
arr.forEach((item, index) => {
const cartographic = Cesium.Cartographic.fromCartesian(
item // Cartesian3对象 {x, y, z}
);
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
posiArr.push({
lng: longitude,
lat: latitude,
alt: height
})
})
} else if (that.options.type == '线') {
that.options.positions.forEach(item => {
fromDegreesArray.push(item.lng, item.lat)
})
array = await that.linePoint(Cesium.Cartesian3.fromDegreesArray(fromDegreesArray), that.options.spacing)
arr = array[0]
that.pointArr = arr
arr.forEach((item, index) => {
const cartographic = Cesium.Cartographic.fromCartesian(
item // Cartesian3对象 {x, y, z}
);
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
posiArr.push({
lng: longitude,
lat: latitude,
alt: height
})
})
} else if (that.options.type == '点') {
let height = await that.getClampToHeight({ lng: that.options.positions.lng, lat: that.options.positions.lat })
posiArr = [{ lng: that.options.positions.lng, lat: that.options.positions.lat, alt: height }]
// posiArr = [that.options.positions]
that.pointArr = posiArr
}
let params = {
type: that.options.type,
positions: posiArr,
rotate: that.options.type == '点' ? undefined : array[1]
}
that.callback(params)
// posiArr.forEach((item, index) => {
// let model = new Model(that.sdk, {
// id: 'model' + index,
// show: that.options.show,
// url: that.options.url,
// position: item,
// rotate: that.options.type == '点' ? undefined : { x: 0, y: 0, z: array[1] && (array[1][index] || array[1]) }
// })
// that.pointArr.push(model)
// })
}
async linePoint(polygonPositions, spacing) {
let boundaryPoints = [];
let boundaryAngle = [];
for (let i = 0; i < polygonPositions.length - 1; i++) {
const start = polygonPositions[i];
const end = polygonPositions[(i + 1) % polygonPositions.length];
const segmentLength = Cesium.Cartesian3.distance(start, end);
const segments = Math.ceil(segmentLength / spacing);
for (let j = 0; j <= segments; j++) {
const ratio = j / segments;
let point = Cesium.Cartesian3.lerp(
start, end, ratio, new Cesium.Cartesian3()
);
const cartographic = Cesium.Cartographic.fromCartesian(
point // Cartesian3对象 {x, y, z}
);
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
let height = await this.getClampToHeight({ lng: longitude, lat: latitude })
point = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);
boundaryPoints.push(point);
if (j != segments || i == polygonPositions.length - 2) {
boundaryAngle.push(this.calculateRoadAngle(start, end))
}
}
}
return [[...new Set(boundaryPoints
.map(p => `${p.x},${p.y},${p.z}`))]
.map(str => {
const [x, y, z] = str.split(',').map(Number);
return new Cesium.Cartesian3(x, y, z);
}), boundaryAngle];
}
calculateRoadAngle(startPoint, endPoint) {
const normal = Cesium.Ellipsoid.WGS84.geodeticSurfaceNormal(startPoint);
const enuMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(startPoint, undefined, normal);
const inverseMatrix = Cesium.Matrix4.inverse(enuMatrix, new Cesium.Matrix4());
const localEnd = Cesium.Matrix4.multiplyByPoint(inverseMatrix, endPoint, new Cesium.Cartesian3());
const horizontalVec = new Cesium.Cartesian2(localEnd.x, localEnd.y);
Cesium.Cartesian2.normalize(horizontalVec, horizontalVec);
const north = new Cesium.Cartesian2(1, 0);
let angle = Cesium.Cartesian2.angleBetween(north, horizontalVec);
angle = Cesium.Math.toDegrees(angle)
const cross = Cesium.Cartesian2.cross(north, horizontalVec, new Cesium.Cartesian2());
// return cross < 0 ? angle : - angle;
return cross < 0 ? -angle : angle;
}
generateInterpolatedPoints(polygonPositions, spacing) {
// 1. 边界点插值
const boundaryPoints = [];
for (let i = 0; i < polygonPositions.length; i++) {
const start = polygonPositions[i];
const end = polygonPositions[(i + 1) % polygonPositions.length];
const segmentLength = Cesium.Cartesian3.distance(start, end);
const segments = Math.ceil(segmentLength / spacing);
for (let j = 0; j <= segments; j++) {
const ratio = j / segments;
const point = Cesium.Cartesian3.lerp(
start, end, ratio, new Cesium.Cartesian3()
);
boundaryPoints.push(point);
}
}
// 2. 内部网格生成
const extent = this.computePolygonExtent(polygonPositions);
let result = this.createGridFromBBox(extent, this.options.spacing)
// const extent = Cesium.Rectangle.fromCartesianArray(polygonPositions);
const gridPoints = [];
// const polygon = new Cesium.PolygonHierarchy(polygonPositions);
var polygon = []
this.options.positions.forEach(item => {
polygon.push([item.lng, item.lat])
})
polygon.push(polygon[0])
for (let x = extent.west; x <= extent.east; x += result.lonStep) {
for (let y = extent.south; y <= extent.north; y += result.latStep) {
const position = Cesium.Cartesian3.fromDegrees(x, y);
const point = turf.point([x, y]);
const polygonTurf = turf.polygon([polygon]);
const isInside = turf.booleanPointInPolygon(point, polygonTurf);
isInside && gridPoints.push(position)
}
}
// 3. 合并结果并去重
// return [...new Set([...boundaryPoints, ...gridPoints]
return [...new Set([...gridPoints]
.map(p => `${p.x},${p.y},${p.z}`))]
.map(str => {
const [x, y, z] = str.split(',').map(Number);
return new Cesium.Cartesian3(x, y, z);
});
}
createGridFromBBox(bbox, spacing) {
const earthRadius = 6378137; // WGS84椭球体长半轴
// 计算经度方向网格数
const lonDistance = Cesium.Cartesian3.distance(
Cesium.Cartesian3.fromDegrees(bbox.west, (bbox.south + bbox.north) / 2, 0),
Cesium.Cartesian3.fromDegrees(bbox.east, (bbox.south + bbox.north) / 2, 0)
);
const lonCount = Math.ceil(lonDistance / spacing);
// 计算纬度方向网格数
const latDistance = Cesium.Cartesian3.distance(
Cesium.Cartesian3.fromDegrees((bbox.west + bbox.east) / 2, bbox.south, 0),
Cesium.Cartesian3.fromDegrees((bbox.west + bbox.east) / 2, bbox.north, 0)
);
const latCount = Math.ceil(latDistance / spacing);
// 生成网格线
const lonStep = (bbox.east - bbox.west) / lonCount;
const latStep = (bbox.north - bbox.south) / latCount;
return { lonStep, latStep }
}
computePolygonExtent(positions) {
// 计算多边形经纬度范围
const cartographics = positions.map(p =>
Cesium.Cartographic.fromCartesian(p));
const lons = cartographics.map(c => Cesium.Math.toDegrees(c.longitude));
const lats = cartographics.map(c => Cesium.Math.toDegrees(c.latitude));
return {
west: Math.min(...lons),
east: Math.max(...lons),
south: Math.min(...lats),
north: Math.max(...lats)
};
}
async computedArea(polygonPositions, spacing) {
let dis12 = Cesium.Cartesian3.distance(polygonPositions[0], polygonPositions[1]);
let dis23 = Cesium.Cartesian3.distance(polygonPositions[1], polygonPositions[2]);
let vec12 = Cesium.Cartesian3.subtract(polygonPositions[1], polygonPositions[0], new Cesium.Cartesian3());
let vec23 = Cesium.Cartesian3.subtract(polygonPositions[2], polygonPositions[1], new Cesium.Cartesian3());
let num12 = Math.ceil(dis12 / spacing);
let num23 = Math.ceil(dis23 / spacing);
let line1 = []
for (let i = 0; i < num12; i++) {
line1.push(await this.calculatePointB(polygonPositions[0], polygonPositions[1], i * spacing))
}
let line2 = []
for (let i = 0; i < num12; i++) {
line2.push(await this.calculatePointB(polygonPositions[3], polygonPositions[2], i * spacing))
}
let allPoints = []
for (let i = 0; i < line1.length; i++) {
for (let j = 0; j < num23; j++) {
allPoints.push(await this.calculatePointB(line1[i], line2[i], j * spacing))
}
}
return allPoints
}
async calculatePointB(pointA, pointC, distance) {
// 将输入坐标转换为Cartesian3类型
// const pointA = Cesium.Cartesian3.fromDegrees(a.longitude, a.latitude, a.height);
// const pointC = Cesium.Cartesian3.fromDegrees(c.longitude, c.latitude, c.height);
// 计算向量AC
const vectorAC = Cesium.Cartesian3.subtract(pointC, pointA, new Cesium.Cartesian3());
// 计算向量AC的长度
const lengthAC = Cesium.Cartesian3.magnitude(vectorAC);
// 归一化向量AC
const unitVector = Cesium.Cartesian3.normalize(vectorAC, new Cesium.Cartesian3());
// 计算点B坐标
const scaledVector = Cesium.Cartesian3.multiplyByScalar(unitVector, distance, new Cesium.Cartesian3());
const pointB = Cesium.Cartesian3.add(pointA, scaledVector, new Cesium.Cartesian3());
const cartographic = Cesium.Cartographic.fromCartesian(
pointB // Cartesian3对象 {x, y, z}
);
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
let height = await this.getClampToHeight({ lng: longitude, lat: latitude })
let point = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);
// 转换回经纬度
// const cartographic = Cesium.Cartographic.fromCartesian(pointB);
// return {
// longitude: Cesium.Math.toDegrees(cartographic.longitude),
// latitude: Cesium.Math.toDegrees(cartographic.latitude),
// height: cartographic.height
// };
// return pointB
return point
}
get show() {
return this.options.show
}
set show(v) {
this.options.show = v
for (let i = 0; i < this.pointArr.length; i++) {
this.pointArr[i].show = v
}
}
get type() {
return this.options.type
}
set type(v) {
this.options.type = v
this._elms.type &&
this._elms.type.forEach(item => {
item.value = v
})
}
get spacing() {
return this.options.spacing
}
set spacing(v) {
this.options.spacing = v
this._elms.spacing &&
this._elms.spacing.forEach(item => {
item.value = v
})
}
/**
* @description 编辑框
* @param state=false {boolean} 状态: true打开, false关闭
*/
async edit(state = false) {
let _this = this
this.originalOptions = this.deepCopyObj(this.options)
// let elms = this.sdk.viewer._container.getElementsByClassName('YJ-custom-base-dialog')
// for (let i = elms.length - 1; i >= 0; i--) {
// this.sdk.viewer._container.removeChild(elms[i])
// }
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.name = '飞线'
}
let Draw
switch (this.options.type) {
case '点':
Draw = new DrawPoint(this.sdk)
break;
case '线':
Draw = new DrawPolyline(this.sdk)
break;
case '面':
Draw = new DrawThreeRect(this.sdk)
break;
default:
break;
}
Draw && Draw.start((a, positions) => {
this.options.positions = positions;
// this.callback(this.options);
(this.options.positions.length || this.options.positions.lng) && BatchModel.computeDis(this)
})
this.originalOptions = this.deepCopyObj(this.options)
this._DialogObject.close()
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(this.originalOptions)
syncData(this.sdk, this.options.id)
syncSplitData(this.sdk, this.options.id)
},
// resetCallBack: () => {
// this.reset()
// console.log('22222')
// this.Dialog.resetCallBack && this.Dialog.resetCallBack()
// },
// removeCallBack: () => {
// console.log('33333')
// this.Dialog.removeCallBack && this.Dialog.removeCallBack()
// },
closeCallBack: () => {
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()
},
addFootElm: [
{
tagName: 'button',
className: 'flipe-over-y',
innerHTML: '重置',
event: [
'click',
() => {
this.reset()
}
]
}
]
// showCallBack: (show) => {
// this.show = show
// this.Dialog.showCallBack && this.Dialog.showCallBack()
// }
}, true)
this._DialogObject._element.body.className = this._DialogObject._element.body.className + ' flow-line-surface'
let contentElm = document.createElement('div');
contentElm.innerHTML = html()
this._DialogObject.contentAppChild(contentElm)
// 颜色组件
// let waterColorPicker = new YJColorPicker({
// el: contentElm.getElementsByClassName("flowLine-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)'
// },//点击清空按钮事件回调
// })
let all_elm = contentElm.getElementsByTagName("*")
this._EventBinding.on(this, all_elm)
this._elms = this._EventBinding.element
let nameData = [
{
name: '点',
value: '点',
},
{
name: '线',
value: '线',
},
{
name: '面',
value: '面',
}
]
let nameDataLegpObject = legp(
this._DialogObject._element.content.getElementsByClassName(
'add-type-box'
)[0],
'.add-type'
)
if (nameDataLegpObject) {
nameDataLegpObject.legp_search(nameData)
let nameDataLegpElm = this._DialogObject._element.content
.getElementsByClassName('add-type')[0]
.getElementsByTagName('input')[0]
this._elms.type = [nameDataLegpElm]
nameDataLegpElm.value = this.options.type
for (let i = 0; i < nameData.length; i++) {
if (nameData[i].value === nameDataLegpElm.value) {
nameDataLegpObject.legp_searchActive(nameData[i].value)
break
}
}
nameDataLegpElm.addEventListener('input', () => {
for (let i = 0; i < nameData.length; i++) {
if (nameData[i].value === nameDataLegpElm.value) {
this.type = nameData[i].value
break
}
}
})
}
// this._elms.color = [waterColorPicker]
} 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
// }
}
}
drawArea() {
}
reset() {
this.name = this.originalOptions.name
this.type = this.originalOptions.type
this.spacing = this.originalOptions.spacing
this.show = this.originalOptions.show
this.options.spacing = this.originalOptions.spacing
}
/**
* 飞到对应实体
*/
async flyTo(options = {}) {
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 = { lng: 0, lat: 0 }
if (this.options.position) {
position = { ...this.options.position }
}
else if (this.options.positions) {
position = { ...this.options.positions[0] }
}
else if (this.options.center) {
position = { ...this.options.center }
}
else if (this.options.start) {
position = { ...this.options.start }
}
else {
if (this.options.hasOwnProperty('lng')) {
position.lng = this.options.lng
}
if (this.options.hasOwnProperty('lat')) {
position.lat = this.options.lat
}
if (this.options.hasOwnProperty('alt')) {
position.alt = this.options.alt
}
}
// 如果没有高度值,则获取紧贴高度计算
// 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 positionArray = []
if (this.options.positions.length > 0) {
for (let i = 0; i < this.options.positions.length; i++) {
let a = Cesium.Cartesian3.fromDegrees(
this.options.positions[i].lng,
this.options.positions[i].lat,
this.options.positions[i].alt
)
positionArray.push(a.x, a.y, a.z)
}
let BoundingSphere = Cesium.BoundingSphere.fromVertices(positionArray)
this.viewer.camera.flyToBoundingSphere(BoundingSphere, {
offset: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-20.0),
roll: Cesium.Math.toRadians(0.0)
}
})
} else if (this.options.positions.lng) {
let orientation = {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-60.0),
roll: Cesium.Math.toRadians(0.0)
}
this.sdk.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(this.options.positions.lng, this.options.positions.lat, this.options.positions.alt + 100),
// orientation: orientation
})
}
}
}
/**
* 删除
*/
async remove() {
for (let i = 0; i < this.pointArr.length; i++) {
this.pointArr[i].remove()
}
this.pointArr = []
this.positions = []
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)
}
flicker() { }
}
export default BatchModel

View File

@ -0,0 +1,335 @@
import { attributeElm } from '../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label" style="flex: unset;">名称</span>
<input class="input" type="text" @model="labelText">
</div>
<div class="col">
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div style="width: 46%;">
<div class="row">
<p class="lable-left-line">WGS84坐标</p>
</div>
<div class="row" style="margin-bottom: 5px;">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" min="-180" max="180" @model="lng">
</div>
</div>
<div class="row" style="margin-bottom: 5px;">
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-90" max="90" @model="lat">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">海拔高度</span>
<div class="input-number input-number-unit-1 alt-box">
<input class="input" type="number" title="" min="-9999999" max="999999999" @model="alt">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<div style="width: 50%;">
<div class="row coordinate-select-box">
<div class="lable-left-line">转换坐标选择
<div class="input input-select coordinate-select" style="margin-left: 20px;"></div>
</div>
</div>
<div class="row" style="margin-bottom: 5px;">
<div class="col">
<span class="label">X轴:</span>
<input style="border: none;background: none;" class="input convert-x" readonly="readonly">
</div>
</div>
<div class="row" style="margin-bottom: 5px;">
<div class="col">
<span class="label">Y轴:</span>
<input style="border: none;background: none;" class="input convert-y" readonly="readonly">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">Z轴:</span>
<input style="border: none;background: none;" class="input convert-z" readonly="readonly">
</div>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col" style="flex: 0 0 120px;">
<span class="label">视野缩放</span>
<input class="btn-switch" type="checkbox" @model="scaleByDistance">
</div>
<div class="col">
<span class="label">最近距离</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="1" max="99999999" @model="near">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">最远距离</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="1" max="99999999" @model="far">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<div class="row">
<DIV-cy-tabs id="point-object-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="空间信息">
<div class="row">
<div class="col height-mode-box">
<span class="label" style="flex: 0 0 56px;">高度模式</span>
<div class="height-mode"></div>
</div>
<div class="col height-box">
<span class="label" style="flex: 0 0 56px;">高度</span>
<div class="input-number input-number-unit-1">
<input class="input height" type="number" title="" min="-9999999" max="999999999">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="YJ-custom-checkbox-box" style="display: flex;align-items: center;cursor: pointer;">
<input type="checkbox" class="YJ-custom-checkbox">
<span style="margin-left: 10px; margin-bottom: 1px;user-select: none;">小数格式</span>
</div>
</div>
<div class="col">
<div class="YJ-custom-checkbox-box" style="display: flex;align-items: center;cursor: pointer;">
<input type="checkbox" class="YJ-custom-checkbox">
<span style="margin-left: 10px; margin-bottom: 1px;user-select: none;">度分格式</span>
</div>
</div>
<div class="col">
<div class="YJ-custom-checkbox-box" style="display: flex;align-items: center;cursor: pointer;">
<input type="checkbox" class="YJ-custom-checkbox">
<span style="margin-left: 10px; margin-bottom: 1px;user-select: none;">度分秒格式</span>
</div>
</div>
<div class="col">
</div>
</div>
<div class="row">
<div style="flex: 1;">
<div class="proj-input-box">
<div class="row">
<div class="col">
<span style="flex: 0 0 40px;">经度</span>
<input class="input lng" readonly="readonly">
</div>
<div class="col">
</div>
</div>
<div class="row">
<div class="col">
<span style="flex: 0 0 40px;">纬度</span>
<input class="input lat" readonly="readonly">
</div>
<div class="col">
</div>
</div>
</div>
<div class="proj-input-box" style="width: 56%;">
<div class="row">
<div class="col" style="flex-direction: column;">
<div class="row" style="margin-bottom: 15px;">
<span style="flex: 0 0 40px;">经度</span>
<input class="input lng-dm-d" style="flex: 1;" readonly="readonly">
<span class="label" style="flex: 0 0 14px;margin: 0 10px;">度</span>
<input class="input lng-dm-m" style="flex: 1;" readonly="readonly">
<span class="label" style="flex: 0 0 14px;margin: 0 10px;">分</span>
<span class="top-line"></span>
</div>
<div class="row">
<span style="flex: 0 0 40px;">纬度</span>
<input class="input lat-dm-d" style="flex: 1;" readonly="readonly">
<span class="label" style="flex: 0 0 14px;margin: 0 10px;">度</span>
<input class="input lat-dm-m" style="flex: 1;" readonly="readonly">
<span class="label" style="flex: 0 0 14px;margin: 0 10px;">分</span>
<span class="bottom-line"></span>
</div>
</div>
</div>
</div>
<div class="proj-input-box" style="width: 70%;">
<div class="row">
<div class="col" style="flex-direction: column;">
<div class="row" style="margin-bottom: 15px;">
<span style="flex: 0 0 40px;">经度</span>
<input class="input lng-dms-d" style="flex: 1;" readonly="readonly">
<span class="label" style="flex: 0 0 14px;margin: 0 10px;">度</span>
<input class="input lng-dms-m" style="flex: 1;" readonly="readonly">
<span class="label" style="flex: 0 0 14px;margin: 0 10px;">分</span>
<input class="input lng-dms-s" style="flex: 1;" readonly="readonly">
<span class="label" style="flex: 0 0 14px;margin: 0 10px;">秒</span>
<span class="top-line"></span>
</div>
<div class="row">
<span style="flex: 0 0 40px;">纬度</span>
<input class="input lat-dms-d" style="flex: 1;" readonly="readonly">
<span class="label" style="flex: 0 0 14px;margin: 0 10px;">度</span>
<input class="input lat-dms-m" style="flex: 1;" readonly="readonly">
<span class="label" style="flex: 0 0 14px;margin: 0 10px;">分</span>
<input class="input lat-dms-s" style="flex: 1;" readonly="readonly">
<span class="label" style="flex: 0 0 14px;margin: 0 10px;">秒</span>
<span class="bottom-line"></span>
</div>
</div>
</div>
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
<div>
<h4>图标设置</h4>
<div class="row" style="margin-bottom: 10px;">
<div class="col" style="flex: 0 0 80px;">
<span class="label" style="flex: none;">显隐</span>
<input class="btn-switch" type="checkbox" @model="billboardShow">
</div>
<div class="col" style="flex: 0 0 90px;">
<span class="label" style="flex: none;">图标</span>
<div class="image-box" @click="clickChangeImage">
<img class="image" src="" alt="" @model="billboardImage">
</div>
</div>
<div class="col" style="flex: 0 0 90px;">
<span class="label" style="flex: none;">默认图标</span>
<div class="image-box" @click="clickChangeDefaultImage">
<img class="image" src="" alt="" @model="billboardDefaultImage">
</div>
</div>
<div class="col">
<span class="label">图标倍数</span>
<div class="input-number input-number-unit-2">
<input class="input" type="number" title="" min="0.1" max="99" @model="billboardScale">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<div>
<h4>文字设置</h4>
<div class="row">
<div class="col" style="flex: 0 0 80px;">
<span class="label" style="flex: none;">显隐</span>
<input class="btn-switch" type="checkbox" @model="labelShow">
</div>
<div class="col font-select-box">
<span class="label" style="flex: none;">字体选择</span>
<div class="input input-select font-select"></div>
</div>
<div class="col">
<span class="label">文字大小</span>
<div class="input-number input-number-unit-2">
<input class="input" type="number" title="" min="1" max="99" @model="labelFontSize" style="width: 70px;">
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">文字颜色</span>
<div class="labelColor"></div>
</div>
</div>
</div>
</DIV-cy-tab-pane>
<!-- <DIV-cy-tab-pane label="效果">
<div>
<div class="row">
<div class="col">
<span class="label">扩散</span>
<input class="btn-switch" type="checkbox" @model="diffuseShow">
</div>
<div class="col">
<span class="label">半径</span>
<input class="input" type="number" title="" min="0" max="9999999" @model="diffuseRadius">
</div>
<div class="col">
<span class="label">时间</span>
<input class="input" type="number" title="" min="100" max="99999" @model="diffuseDuration">
</div>
<div class="col">
<span class="label">颜色</span>
<div class="diffuseColor"></div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">雷达</span>
<input class="btn-switch" type="checkbox" @model="scanShow">
</div>
<div class="col">
<span class="label">半径</span>
<input class="input" type="number" title="" min="0" max="9999999" @model="scanRadius">
</div>
<div class="col">
<span class="label">时间</span>
<input class="input" type="number" title="" min="100" max="99999" @model="scanDuration">
</div>
<div class="col">
<span class="label">颜色</span>
<div class="scanColor"></div>
</div>
</div>
</div>
</DIV-cy-tab-pane>-->
<!-- <DIV-cy-tab-pane label="灯光控制">-->
<!-- <div>-->
<!-- <div class="row">-->
<!-- <div class="col">-->
<!-- <span class="label">指令</span>-->
<!-- <input class="input" type="text" @model="instruct">-->
<!-- <button class="primary" @click="instructSubmit">提交</button>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </DIV-cy-tab-pane>-->
<!-- <DIV-cy-tab-pane label="设置操作点">-->
<!-- <div>-->
<!-- <div class="row">-->
<!-- <div class="col">-->
<!-- <span class="label">设置操作点</span>-->
<!-- <input class="input" type="text" @model="operatingPoint">-->
<!-- <button class="primary" @click="operatingPointSubmit">提交</button>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </DIV-cy-tab-pane>-->
</DIV-cy-tabs>
</div>
<span class="custom-divider"></span>
`
}
export { html }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,85 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col">
<span class="label">透明度</span>
<input type="range" min="0" max="1" step="0.01" @model="transparency">
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" min="-180" max="180" @model="lng">
</div>
<div class="col">
<span class="label">波纹层数</span>
<div class="input-number input-number-unit">
<input class="input" type="number" title="" min="1" max="10" @model="count">
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-180" max="180" @model="lat">
</div>
<div class="col">
<span class="label">扩散速度</span>
<div class="input-number input-number-unit">
<input class="input" type="number" title="" min="0" max="20" @model="speed">
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col input-radius-unit-box" style="margin: 0;">
<span class="label">半径单位</span>
<div class="input-radius-unit"></div>
</div>
<div class="col" style="margin: 0;">
</div>
<div class="col" style="margin: 0;">
</div>
</div>
<div class="row circle-content-box">
<div class="col">
<span class="label"></span>
<input class="input" type="number" title="" min="-180" max="180" @model="lat">
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<DIV-cy-tabs id="circle-diffuse-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
</DIV-cy-tabs>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,87 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../Element/elm_html'
function html(that) {
return `
<div class="row" style="align-items: flex-start;">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col" style="flex: 0 0 60%;">
<div class="row">
<div class="col input-select-unit-box">
<span class="label" style="margin-right: 0px;">投影面积:</span>
<input class="input input-text" readonly="readonly" type="text" @model="area">
<div class="input-select-unit"></div>
</div>
</div>
</div>
</div>
<div class="row">
<DIV-cy-tabs id="circle-object-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="空间信息">
<div class="row">
<div class="col height-mode-box">
<span class="label" style="flex: 0 0 56px;">高度模式</span>
<div class="height-mode"></div>
</div>
<div class="col">
<span class="label">Z值统一增加</span>
<div class="input-number input-number-unit-1 height-box">
<input class="input height" type="number" title="" min="-9999999" max="999999999">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
<button class="confirm height-confirm" style="margin-left: 5px;">确认</button>
</div>
</div>
<div class="row">
<div class="table spatial-info-table">
<div class="table-head">
<div class="tr">
<div class="th"></div>
<div class="th">经度X</div>
<div class="th">纬度Y</div>
<div class="th">高度Z</div>
</div>
</div>
<div class="table-body">
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="面风格">
<div class="row">
<div class="col">
<span class="label">面颜色</span>
<div class="color"></div>
</div>
<div class="col">
<span class="label">边线颜色</span>
<div class="lineColor"></div>
</div>
<div class="col">
<span class="label">边线宽度</span>
<div class="input-number input-number-unit-2" style="width: 80px;">
<input class="input" type="number" title="" min="0" max="99" @model="lineWidth">
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
</DIV-cy-tabs>
</div>
`
}
export { html }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,64 @@
// /**
// * 走廊
// */
// import Base from "../index";
// class Corridor extends Base {
// /**
// * @constructor
// * @param sdk
// * @param options {object} 线属性
// * @param options.name{string} 名称
// * @param options.image{string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} 指定 Image、URL、Canvas 或 Video 的属性
// * @param options.width=10{number} 宽度
// * @param options.height=0{number} 高度
// * */
// constructor(sdk, options = {}) {
// super(sdk, options);
// this.options.name = options.name || ''
// this.options.image = options.image
// this.options.width = options.width || 10
// this.options.height = options.height || 0
// }
// create(positions) {
// let fromDegreesArray = []
// for (let i = 0; i < positions.length; i++) {
// fromDegreesArray.push(positions[i].lng, positions[i].lat)
// }
// this.entity = this.sdk.viewer.scene.primitives.add(new Cesium.Primitive({//GroundPrimitive贴地
// geometryInstances: new Cesium.GeometryInstance({
// geometry: new Cesium.CorridorGeometry({
// positions: Cesium.Cartesian3.fromDegreesArray(fromDegreesArray),
// width: this.options.width,
// height: this.options.height,
// cornerType: Cesium.CornerType.MITERED,
// vertexFormat: Cesium.MaterialAppearance.MaterialSupport.ALL.vertexFormat
// }),
// attributes: {
// color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 1.0, 1.0, 0.5))
// }
// }),
// appearance: new Cesium.MaterialAppearance({
// material: Cesium.Material.fromType('Image', {
// image: this.options.image,
// repeat: new Cesium.Cartesian2(100, 1.0)
// }),
// faceForward: true,
// renderState: {
// blending: Cesium.BlendingState.ALPHA_BLEND
// }
// })
// }));
// }
// // 编辑框
// async edit(state) { }
// remove() {
// this.sdk.viewer.scene.primitives.remove(this.entity)
// this.entity = null
// }
// }
// export default Corridor

View File

@ -0,0 +1,167 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row" style="align-items: flex-start;">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col" style="flex: 0 0 56%;">
<div>
<div class="row">
<div class="col input-select-unit-box">
<div class="input-select-unit"></div>
<input class="input input-text" readonly="readonly" type="text" style="flex: 0 0 130px;" @model="length">
<div class="input-select-unit"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<DIV-cy-tabs id="polyline-object-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="空间信息">
<div class="row">
<div class="col height-mode-box">
<span class="label" style="flex: 0 0 56px;">高度模式</span>
<div class="height-mode"></div>
</div>
<div class="col">
<span class="label">Z值统一增加</span>
<div class="input-number input-number-unit-1 height-box">
<input class="input height" type="number" title="" min="-9999999" max="999999999">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
<button class="confirm height-confirm" style="margin-left: 5px;">确认</button>
</div>
</div>
<div class="row">
<div class="table spatial-info-table">
<div class="table-head">
<div class="tr">
<div class="th"></div>
<div class="th">经度X</div>
<div class="th">纬度Y</div>
<div class="th">高度Z</div>
</div>
</div>
<div class="table-body">
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="线条风格">
<div class="row">
<div class="col">
<span class="label">线条颜色</span>
<div class="color"></div>
</div>
<div class="col" style="flex: 0 0 33%;">
<span class="label">线条宽度</span>
<div class="input-number input-number-unit-1" style="width: 80px;">
<input class="input" type="number" title="" min="1" max="999" @model="lineWidth">
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
<div class="col input-select-line-type-box" style="flex: 0 0 37%;">
<span class="label">线条形式</span>
<div class="input-select-line-type"></div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">线段缓冲</span>
<input class="btn-switch" type="checkbox" @model="extend">
</div>
<div class="col" style="flex: 0 0 33%;">
<span class="label">缓冲宽度</span>
<div class="input-number input-number-unit-1" style="width: 80px;">
<input class="input" type="number" title="" min="0" data-min="0.01" max="999999" @model="extendWidth">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col" style="flex: 0 0 37%;">
<span class="label">缓冲颜色</span>
<div class="extendColor"></div>
</div>
</div>
<div class="row" id="dashTextureDom">
<div class="col">
<span class="label">动画顺向</span>
<input class="btn-switch" type="checkbox" @model="rotate">
</div>
<div class="col" style="flex: 0 0 33%;">
<span class="label">流动速率</span>
<div class="input-number input-number-unit-1" style="width: 80px;">
<input class="input" type="number" title="" min="0" max="999999" step="1" @model="speed">
<span class="arrow"></span>
</div>
</div>
<div class="col" style="flex: 0 0 37%;">
<span class="label lineSpace">间距</span>
<div class="input-number input-number-unit-1 lineSpace" style="width: 80px;">
<input class="input" type="number" title="" min="0" max="4.5" step="0.1" @model="space">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">首尾相连</span>
<input class="btn-switch" type="checkbox" @model="noseToTail">
</div>
<div class="col" style="flex: 0 0 33%;">
</div>
<div class="col" style="flex: 0 0 37%;">
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
<!-- <DIV-cy-tab-pane label="灯光控制">-->
<!-- <div>-->
<!-- <div class="row">-->
<!-- <div class="col">-->
<!-- <span class="label">指令</span>-->
<!-- <input class="input" type="text" @model="instruct">-->
<!-- <button class="primary" @click="instructSubmit">提交</button>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </DIV-cy-tab-pane>-->
<!-- <DIV-cy-tab-pane label="设置操作点">-->
<!-- <div>-->
<!-- <div class="row">-->
<!-- <div class="col">-->
<!-- <span class="label">设置操作点</span>-->
<!-- <input class="input" type="text" @model="operatingPoint">-->
<!-- <button class="primary" @click="operatingPointSubmit">提交</button>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </DIV-cy-tab-pane>-->
</DIV-cy-tabs>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,120 @@
class eventBinding {
constructor() {
this.element = {}
}
static event = {}
getEvent(name) {
return eventBinding.event[name]
}
getEventAll() {
return eventBinding.event
}
setEvent(name, event) {
eventBinding.event[name] = event
}
on(that, elements) {
for (let i = 0; i < elements.length; i++) {
let Event = []
let isEvent = false
let removeName = []
if (!elements[i] ||!elements[i].attributes) {
continue
}
for (let m of elements[i].attributes) {
switch (m.name) {
case '@model': {
isEvent = true
if (elements[i].type == 'checkbox') {
Event.push((e) => { that[m.value] = e.target.checked })
elements[i].checked = that[m.value]
}
else {
Event.push((e) => {
let value = e.target.value
if (e.target.type == 'number') {
if (e.data != '.' && (e.data != '-' || 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)
}
if((e.target.dataset.min) && value<Number(e.target.dataset.min)) {
value = Number(e.target.dataset.min)
}
that[m.value] = value
}
}
else {
that[m.value] = value
}
})
if(elements[i].nodeName=='IMG') {
elements[i].src = that[m.value]
}
else {
elements[i].value = that[m.value]
}
}
if(this.element[m.value]) {
this.element[m.value].push(elements[i])
}
else {
this.element[m.value] = [elements[i]]
}
removeName.push(m.name)
break;
}
case '@click': {
elements[i].addEventListener('click', (e) => {
if (typeof (that[m.value]) === 'function') {
that[m.value](e)
}
});
removeName.push(m.name)
// elements[i].attributes.removeNamedItem(m.name)
break;
}
case '@change': {
isEvent = true
Event.push((e) => {
let value = e.target.value
if(e.target.type == 'number' && value!='') {
value = Number(value)
e.target.value = value
}
if (typeof (that[m.value]) === 'function') {
that[m.value](e, value)
}
})
break;
}
}
// elements[i].attributes[m] = undefined
}
for(let n=0;n<removeName.length;n++) {
elements[i].attributes.removeNamedItem(removeName[n])
}
if (isEvent) {
let ventType = 'input'
if (elements[i].tagName != 'INPUT' || elements[i].type == 'checkbox') {
ventType = 'change'
}
elements[i].addEventListener(ventType, (e) => {
for (let t = 0; t < Event.length; t++) {
Event[t](e)
}
});
}
}
}
}
const EventBinding = new eventBinding();
export default EventBinding;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,87 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../Element/elm_html'
function html(that) {
return `
<div class="row" style="align-items: flex-start;">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col" style="flex: 0 0 60%;">
<div class="row">
<div class="col input-select-unit-box">
<span class="label" style="margin-right: 0px;">投影面积:</span>
<input class="input input-text" readonly="readonly" type="text" @model="area">
<div class="input-select-unit"></div>
</div>
</div>
</div>
</div>
<div class="row">
<DIV-cy-tabs id="circle-object-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="空间信息">
<div class="row">
<div class="col height-mode-box">
<span class="label" style="flex: 0 0 56px;">高度模式</span>
<div class="height-mode"></div>
</div>
<div class="col">
<span class="label">Z值统一增加</span>
<div class="input-number input-number-unit-1 height-box">
<input class="input height" type="number" title="" min="-9999999" max="999999999">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
<button class="confirm height-confirm" style="margin-left: 5px;">确认</button>
</div>
</div>
<div class="row">
<div class="table spatial-info-table">
<div class="table-head">
<div class="tr">
<div class="th"></div>
<div class="th">经度X</div>
<div class="th">纬度Y</div>
<div class="th">高度Z</div>
</div>
</div>
<div class="table-body">
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="面风格">
<div class="row">
<div class="col">
<span class="label">面颜色</span>
<div class="color"></div>
</div>
<div class="col">
<span class="label">边线颜色</span>
<div class="lineColor"></div>
</div>
<div class="col">
<span class="label">边线宽度</span>
<div class="input-number input-number-unit-2" style="width: 80px;">
<input class="input" type="number" title="" min="0" max="99" @model="lineWidth">
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
</DIV-cy-tabs>
</div>
`
}
export { html }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
function html() {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col">
<span class="label">随地图缩放</span>
<input class="btn-switch" type="checkbox" @model="scaleByDistance">
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" title="" min="-180" max="180" @model="lng">
</div>
<div class="col">
<span class="label">爆炸范围</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="1" max="999999" @model="size">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-90" max="90" @model="lat">
</div>
<div class="col">
<span class="label">高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="-9999999" max="999999999" @model="alt">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,391 @@
import Base from "../index";
import Dialog from '../../Element/Dialog';
import EventBinding from '../../Element/Dialog/eventBinding';
import { html } from "./_element";
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, getGroundCover} from '../../../Global/global'
class Explosion extends Base {
/**
* @constructor
* @description 爆炸
* @param sdk
* @param options {object} 爆炸属性
* @param options.id {string} 唯一标识
* @param options.show=true {boolean} 显隐
* @param options.name {string} 名称
* @param {object} options.position={} 位置
* @param {number} options.position.lng 经度
* @param {number} options.position.lat 纬度
* @param {number} options.position.alt 高度
* @param options.scaleByDistance=true {boolean} 是否开启跟随视野缩放
* @param options.size=80 {number} 大小(爆炸范围)
* */
constructor(sdk, options = {}, _Dialog = {}) {
super(sdk, options);
this.viewer = sdk.viewer
this.options.show = (options.show || options.show === false) ? options.show : true
this.options.name = this.options.name || '未命名对象'
this.options.size = (this.options.size || this.options.size === 0) ? this.options.size : 80
this.options.scaleByDistance = (options.scaleByDistance || options.scaleByDistance === false) ? options.scaleByDistance : true
this.event = new MouseEvent(this.sdk)
this.Dialog = _Dialog
this.operate = {}
this._elms = {};
this._EventBinding = new EventBinding()
this.sdk.addIncetance(this.options.id, this)
Explosion.create(this)
}
get type() {
return 'Explosion'
}
// 创建
static create(that) {
let img_bz = []
for (let i = 10001; i <= 10120; i++) {
let src = that.getSourceRootPath() + `/img/frameAnimation/explosion/b${i}.png`
img_bz.push(src)
}
let i = 0
let flyEntity = new Cesium.Entity({
id: that.options.id,
show: that.options.show,
position: new Cesium.CallbackProperty(() => {
return Cesium.Cartesian3.fromDegrees(that.options.position.lng, that.options.position.lat, that.options.position.alt)
}, false),
billboard: {
image: new Cesium.CallbackProperty(() => {
let img = img_bz[flyEntity.imgIndex]
flyEntity.imgIndex++
if (flyEntity.imgIndex >= img_bz.length) {
flyEntity.imgIndex = 0
}
return img
}, false),
// scale: that.options.size,
disableDepthTestDistance: new Cesium.CallbackProperty(function () {
return getGroundCover() ? undefined : Number.POSITIVE_INFINITY
}, false),
width: that.options.size,
height: that.options.size,
sizeInMeters: that.options.scaleByDistance,
pixelOffset: { x: 0, y: -20 }
},
});
flyEntity.imgIndex = 0
that.entity = that.viewer.entities.add(flyEntity)
syncData(that.sdk, that.options.id)
if(that.options.show) {
setSplitDirection(0, that.options.id)
}
}
// 编辑框
async edit(state) {
let _this = this
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.options, {
title: '爆炸属性', left: '180px', top: '100px',
confirmCallBack: (options) => {
this.name = this.name.trim()
if(!this.name) {
this.name = '未命名对象'
}
this.originalOptions = this.deepCopyObj(this.options)
this._DialogObject.close()
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(this.originalOptions)
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.reset()
this.positionEditing = false
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
},
showCallBack: (show) => {
this.options.show = show
this.originalOptions.show = show
this.show = show
this.Dialog.showCallBack && this.Dialog.showCallBack()
},
translationalCallBack: () => {
this.positionEditing = !this.positionEditing
},
})
this._DialogObject._element.body.className = this._DialogObject._element.body.className + ' explosion'
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
this.scaleByDistance = this.options.scaleByDistance
}
}
async flyTo(options = {}) {
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 = { lng: 0, lat: 0 }
if (this.options.position) {
position = { ...this.options.position }
}
else if (this.options.positions) {
position = { ...this.options.positions[0] }
}
else if (this.options.center) {
position = { ...this.options.center }
}
else if (this.options.start) {
position = { ...this.options.start }
}
else {
if (this.options.hasOwnProperty('lng')) {
position.lng = this.options.lng
}
if (this.options.hasOwnProperty('lat')) {
position.lat = this.options.lat
}
if (this.options.hasOwnProperty('alt')) {
position.alt = this.options.alt
}
}
// 如果没有高度值,则获取紧贴高度计算
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 {
this.sdk.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(this.options.position.lng, this.options.position.lat, this.options.position.alt + (this.options.size * 8)),
orientation: options.orientation || {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-85.0),
roll: Cesium.Math.toRadians(0.0)
},
})
}
}
reset() {
if (!this.entity) {
return
}
this.previous = null
this.options = this.deepCopyObj(this.originalOptions)
this.name = this.originalOptions.name
this.size = this.originalOptions.size
this.scaleByDistance = this.originalOptions.scaleByDistance
this.lng = this.options.position.lng
this.lat = this.options.position.lat
}
get scaleByDistance() {
return this.options.scaleByDistance
}
set scaleByDistance(v) {
this.options.scaleByDistance = v
this.entity.billboard.sizeInMeters = v
this._elms.scaleByDistance && this._elms.scaleByDistance.forEach((item) => {
item.checked = v
})
}
get lng() {
return this.options.position.lng
}
set lng(v) {
this.options.position.lng = v
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = v
})
}
get lat() {
return this.options.position.lat
}
set lat(v) {
this.options.position.lat = v
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = v
})
}
get alt() {
return this.options.position.alt
}
set alt(v) {
this.options.position.alt = v
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = v
})
}
get size() {
return this.options.size
}
set size(v) {
this.options.size = v
this.entity.billboard.width = this.options.size
this.entity.billboard.height = this.options.size
this._elms.size && this._elms.size.forEach((item) => {
item.value = v
})
}
/**@desc 打开平移功能
*
* @memberOf Source
* @param status {boolean}
*
* */
set positionEditing(status) {
if (YJ.Measure.GetMeasureStatus() || !this.sdk || !this.sdk.viewer || !this.entity) {
return
}
this.operate.positionEditing = status
if (status === true) {
this.tip && this.tip.destroy()
this.tip = new MouseTip('点击鼠标左键确认,右键取消', this.sdk)
this.previous = {
position: { ...this.options.position }
}
this.event.mouse_move((movement, cartesian) => {
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.lng = positions.lng
this.lat = positions.lat
this.alt = positions.alt
this.tip.setPosition(
cartesian,
movement.endPosition.x,
movement.endPosition.y
)
})
this.event.mouse_left((movement, cartesian) => {
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.lng = positions.lng
this.lat = positions.lat
this.alt = positions.alt
this.previous = {
position: { ...this.options.position }
}
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
this.event.gesture_pinck_start(() => { })
this.event.gesture_pinck_end(() => { })
this.positionEditing = false
})
this.event.mouse_right((movement, cartesian) => {
this.positionEditing = false
})
this.event.gesture_pinck_start((movement, cartesian) => {
let startTime = new Date()
this.event.gesture_pinck_end(() => {
let endTime = new Date()
if (endTime - startTime >= 500) {
this.positionEditing = false
}
else {
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.lng = positions.lng
this.lat = positions.lat
this.alt = positions.alt
this.previous = {
position: { ...this.options.position }
}
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
this.event.gesture_pinck_start(() => { })
this.event.gesture_pinck_end(() => { })
this.positionEditing = false
}
})
})
}
else {
if (this.event) {
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
this.event.gesture_pinck_start(() => { })
this.event.gesture_pinck_end(() => { })
}
this.tip && this.tip.destroy()
if (this.previous) {
this.lng = this.previous.position.lng
this.lat = this.previous.position.lat
this.alt = this.previous.position.alt
}
}
}
get positionEditing() {
return this.operate.positionEditing
}
/**
* 删除
*/
async remove() {
this.viewer.entities.remove(this.entity)
this.entity = null
if (this._DialogObject && !this._DialogObject.isDestroy) {
this._DialogObject.close()
this._DialogObject = null
}
this.tip && this.tip.destroy()
this.event && this.event.destroy()
await this.sdk.removeIncetance(this.options.id)
await syncData(this.sdk, this.options.id)
}
flicker() {}
}
export default Explosion

View File

@ -0,0 +1,76 @@
function html() {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col">
<span class="label">颜色</span>
<div class="flowLine-color"></div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">飞线数量</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="1" max="99999" @model="pointNumber">
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">飞线宽度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" max="99999" min="1" step="1" @model="width">
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">飞线高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="0" max="999999" step="1" @model="height">
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">飞线高度差</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" max="99999" min="0" step="1" @model="heightDifference">
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">单次运动时长s</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" max="999999999" min="1" step="1" @model="duration">
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">轨迹透明度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" max="1" min="0.01" step="0.01" @model="lineBackAlpha">
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,92 @@
class eventBinding {
constructor() {
this.element = {}
}
static event = {}
getEvent(name) {
return eventBinding.event[name]
}
getEventAll() {
return eventBinding.event
}
setEvent(name, event) {
eventBinding.event[name] = event
}
on(that, elements) {
for (let i = 0; i < elements.length; i++) {
let Event = []
let isEvent = false
let removeName = []
if (!elements[i] || !elements[i].attributes) {
continue;
}
for (let m of elements[i].attributes) {
switch (m.name) {
case '@model': {
isEvent = true
if (elements[i].type == 'checkbox') {
Event.push((e) => { that[m.value] = e.target.checked })
elements[i].checked = that[m.value]
}
else {
Event.push((e) => {
let value = e.target.value
if (e.target.type == 'number') {
value = Number(value)
}
that[m.value] = value
})
if (elements[i].nodeName == 'IMG') {
elements[i].src = that[m.value]
}
else {
elements[i].value = that[m.value]
}
}
if (this.element[m.value]) {
this.element[m.value].push(elements[i])
}
else {
this.element[m.value] = [elements[i]]
}
removeName.push(m.name)
break;
}
case '@click': {
elements[i].addEventListener('click', (e) => {
if (typeof (that.Dialog[m.value]) === 'function') {
that.Dialog[m.value](e)
}
});
removeName.push(m.name)
// elements[i].attributes.removeNamedItem(m.name)
break;
}
}
// elements[i].attributes[m] = undefined
}
for (let n = 0; n < removeName.length; n++) {
elements[i].attributes.removeNamedItem(removeName[n])
}
if (isEvent) {
let ventType = 'input'
if (elements[i].tagName != 'INPUT' || elements[i].type == 'checkbox') {
ventType = 'change'
}
elements[i].addEventListener(ventType, (e) => {
for (let t = 0; t < Event.length; t++) {
Event[t](e)
}
});
}
}
}
}
const EventBinding = new eventBinding();
export default EventBinding;

View File

@ -0,0 +1,504 @@
/**
* @description 水面
*/
import Dialog from '../../Element/Dialog';
import { html } from "./_element";
import EventBinding from '../../Element/Dialog/eventBinding';
import Base from "../index";
import { syncData } from '../../../Global/MultiViewportMode'
import DrawRect from '../../../Draw/drawRect'
import drawPolygon from '../../../Draw/drawPolygon'
import { setSplitDirection, syncSplitData, setActiveId } from '../../../Global/SplitScreen'
import { setActiveViewer, closeRotateAround, closeViewFollow } from '../../../Global/global'
import FlowLineMaterialProperty from "../../Materail/FlowLineMaterialProperty";
class FlowLine extends Base {
/**
* @constructor
* @param sdk
* @description 流光飞线
* @param options {object} 流光飞线属性
* @param options.name=未命名对象 {string} 名称
* @param options.pointNumber=300 {number} 线数量
* @param options.height=200 {number} 线高度
* @param options.heightDifference=3000 {number} 线高度差
* @param options.width=2 {number} 线宽
* @param options.duration=10.0 {number} 单次运动时间
* @param options.color=rgba(255,255,255,1) {string} 颜色
* @param options.lineBackAlpha=0.05 {number} 轨迹颜色不能为0
* @param Dialog {object} 弹框对象
* @param Dialog.confirmCallBack {function} 弹框确认时的回调
* */
constructor(sdk, options = {}, _Dialog = {}) {
super(sdk, options);
this.viewer = this.sdk.viewer
this.options.name = options.name || '飞线'
this.options.pointNumber = options.pointNumber || 200
this.options.height = options.height || 200
this.options.heightDifference = options.heightDifference || 3000
this.options.width = options.width || 2
this.options.duration = options.duration || 10.0
this.options.color = options.color || "rgba(255,255,255,1)"
this.options.lineBackAlpha = options.lineBackAlpha || 0.05
this.options.positions = options.positions || []
this.options.show = (options.show || options.show === false) ? options.show : true
this.Dialog = _Dialog
this._EventBinding = new EventBinding()
this._elms = {};
this.positionArea = []
this.positions = []
this.sdk.addIncetance(this.options.id, this)
// FlowLine.create(this)
FlowLine.drawLine(this)
}
// 创建水面
static create(that) {
// let Draw = new DrawRect(that.sdk)
// Draw.start((a, positions) => {
// that.positions = positions
// that.getLine(that, that.positions)
// that.edit(true)
// })
let Draw = new drawPolygon(that.sdk)
Draw.start((a, positions) => {
that.positionArea = positions
let posis = that.getRandomPointsInCesiumPolygon(positions, that.options.pointNumber)
that.positions = posis
that.getLine(that, posis)
that.edit(true)
})
}
static drawLine(that) {
that.positionArea = that.options.positions
let posis = that.getRandomPointsInCesiumPolygon(that.options.positions, that.options.pointNumber)
that.positions = posis
that.getLine(that, posis)
// that.edit(true)
}
getRandomPointsInCesiumPolygon(positions, count) {
let lons = [], lats = [], posi = []
positions.forEach(item => {
lons.push(item.lng)
lats.push(item.lat)
posi.push([item.lng, item.lat])
})
posi.push([posi[0][0], posi[0][1]])
const minLon = Math.min(...lons), maxLon = Math.max(...lons);
const minLat = Math.min(...lats), maxLat = Math.max(...lats);
const points = [];
let that = this
while (points.length < count) {
const lon = minLon + Math.random() * (maxLon - minLon);
const lat = minLat + Math.random() * (maxLat - minLat);
// const cartesian = Cesium.Cartesian3.fromDegrees(lon, lat);
let point = turf.point([lon, lat]);
const polygon = turf.polygon([
posi
]);
const isInside = turf.booleanPointInPolygon(point, polygon);
if (isInside) {
let posi = Cesium.Cartesian3.fromDegrees(lon, lat);
const cartographic = that.viewer.scene.globe.ellipsoid.cartesianToCartographic(posi);
const height = cartographic.height;
points.push([
lon,
lat,
height
]);
}
}
return points;
}
getLine(that, positions) {
let num = 0
let celiangEntity = null
if (that.viewer.entities.getById(that.options.id)) {
that.viewer.entities.getById(that.options.id)._children.forEach((item) => {
that.viewer.entities.remove(item);
});
that.viewer.entities.remove(that.viewer.entities.getById(that.options.id))
}
celiangEntity = that.viewer.entities.add(new Cesium.Entity({ id: that.options.id, show: that.options.show }))
positions.forEach((item, index) => {
let point = item
//根据点设置起始点位置
// let start = Cesium.Cartesian3.fromDegrees(point[0], point[1], 0)
let start = Cesium.Cartesian3.fromDegrees(point[0], point[1], point[2])
//根据点设置结束点位置
let end = Cesium.Cartesian3.fromDegrees(point[0], point[1], point[2] + that.options.height + Math.random() * that.options.heightDifference)
//创建线
that.viewer.entities.add({
parent: celiangEntity,
id: that.options.id + '-' + new Date().getTime() + index,
polyline: {
positions: [start, end],
width: that.options.width,
// material:Cesium.Color.RED
material: new Cesium.FlowLineMaterialProperty({
color: that.options.color,
duration: that.options.duration,
lineBackAlpha: that.options.lineBackAlpha,
num: num
})
}
})
});
}
get color() {
return this.options.color
}
set color(v) {
this.options.color = v
let entity = this.viewer.entities.getById(this.options.id)
if (entity) {
entity._children.forEach(item => {
item.polyline.material.color = Cesium.Color.fromCssColorString(v)
})
}
if (this._elms.color) {
this._elms.color.forEach((item, i) => {
let picker = 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] = picker
})
}
}
get pointNumber() {
return this.options.pointNumber
}
set pointNumber(v) {
this.options.pointNumber = v
let entity = this.viewer.entities.getById(this.options.id)
if (entity) {
let posis = this.getRandomPointsInCesiumPolygon(this.positionArea, this.options.pointNumber)
this.positions = posis
this.getLine(this, posis)
}
}
get height() {
return this.options.height
}
set height(v) {
this.options.height = v
let entity = this.viewer.entities.getById(this.options.id)
if (entity) {
this.getLine(this, this.positions)
}
}
get show() {
return this.options.show
}
set show(v) {
this.options.show = v
let entity = this.viewer.entities.getById(this.options.id)
if (entity) {
entity.show = v
}
}
get heightDifference() {
return this.options.heightDifference
}
set heightDifference(v) {
this.options.heightDifference = v
let entity = this.viewer.entities.getById(this.options.id)
if (entity) {
this.getLine(this, this.positions)
}
}
get width() {
return this.options.width
}
set width(v) {
this.options.width = v
let entity = this.viewer.entities.getById(this.options.id)
if (entity) {
entity._children.forEach(item => {
item.polyline.width = v
})
}
}
get duration() {
return this.options.duration
}
set duration(v) {
this.options.duration = v
let entity = this.viewer.entities.getById(this.options.id)
if (entity) {
entity._children.forEach(item => {
item.polyline.material.duration = v
})
}
}
get lineBackAlpha() {
return this.options.lineBackAlpha
}
set lineBackAlpha(v) {
this.options.lineBackAlpha = v
let entity = this.viewer.entities.getById(this.options.id)
if (entity) {
entity._children.forEach(item => {
item.polyline.material.lineBackAlpha = v
})
}
}
/**
* @description 编辑框
* @param state=false {boolean} 状态: true打开, false关闭
*/
async edit(state = false) {
let _this = this
this.originalOptions = this.deepCopyObj(this.options)
// let elms = this.sdk.viewer._container.getElementsByClassName('YJ-custom-base-dialog')
// for (let i = elms.length - 1; i >= 0; i--) {
// this.sdk.viewer._container.removeChild(elms[i])
// }
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.name = '飞线'
}
this.originalOptions = this.deepCopyObj(this.options)
this._DialogObject.close()
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(this.originalOptions)
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.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()
}
}, true)
this._DialogObject._element.body.className = this._DialogObject._element.body.className + ' flow-line-surface'
let contentElm = document.createElement('div');
contentElm.innerHTML = html()
this._DialogObject.contentAppChild(contentElm)
// 颜色组件
let waterColorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("flowLine-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)'
},//点击清空按钮事件回调
})
let all_elm = contentElm.getElementsByTagName("*")
this._EventBinding.on(this, all_elm)
this._elms = this._EventBinding.element
this._elms.color = [waterColorPicker]
} 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
// }
}
}
reset() {
if (!this.viewer.entities.getById(this.options.id)) {
return
}
this.name = this.originalOptions.name
this.pointNumber = this.originalOptions.pointNumber
this.height = this.originalOptions.height
this.heightDifference = this.originalOptions.heightDifference
this.width = this.originalOptions.width
this.duration = this.originalOptions.duration
this.color = this.originalOptions.color
this.lineBackAlpha = this.originalOptions.lineBackAlpha
}
/**
* 飞到对应实体
*/
async flyTo(options = {}) {
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 = { lng: 0, lat: 0 }
if (this.options.position) {
position = { ...this.options.position }
}
else if (this.options.positions) {
position = { ...this.options.positions[0] }
}
else if (this.options.center) {
position = { ...this.options.center }
}
else if (this.options.start) {
position = { ...this.options.start }
}
else {
if (this.options.hasOwnProperty('lng')) {
position.lng = this.options.lng
}
if (this.options.hasOwnProperty('lat')) {
position.lat = this.options.lat
}
if (this.options.hasOwnProperty('alt')) {
position.alt = this.options.alt
}
}
// 如果没有高度值,则获取紧贴高度计算
// 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 positionArray = []
for (let i = 0; i < this.positions.length; i++) {
let a = Cesium.Cartesian3.fromDegrees(
this.positions[i][0],
this.positions[i][1],
this.positions[i][2] + this.options.height + this.options.heightDifference / 2
)
positionArray.push(a.x, a.y, a.z)
}
let BoundingSphere = Cesium.BoundingSphere.fromVertices(positionArray)
this.viewer.camera.flyToBoundingSphere(BoundingSphere, {
offset: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-20.0),
roll: Cesium.Math.toRadians(0.0)
}
})
}
}
getSphere() {
return new Promise((resolve) => {
// entity没有加载完成时 state 不会等于0 所以设置定时器直到获取到为止
const interval = setInterval(() => {
const sphere = new Cesium.BoundingSphere()
const state = this.sdk.viewer._dataSourceDisplay.getBoundingSphere(
this.viewer.entities.getById(this.options.id),
false,
sphere
)
if (state === Cesium.BoundingSphereState.DONE) {
clearInterval(interval)
}
}, 1000)
})
}
/**
* 删除
*/
async remove() {
if (this.viewer.entities.getById(this.options.id)) {
this.viewer.entities.getById(this.options.id)._children.forEach((item) => {
this.viewer.entities.remove(item);
});
this.viewer.entities.remove(this.viewer.entities.getById(this.options.id))
}
this.positions = []
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)
}
flicker() { }
}
export default FlowLine

View File

@ -0,0 +1,67 @@
function html() {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" type="text" name="name">
</div>
<div class="col"></div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<input type="checkbox" name="isTotalTime" style="width: 16px; line-height: 15px; height: 15px; cursor: pointer; width: auto; margin-right: 5px;">
<span class="label">设置总时长</span>
<div class="input-number input-number-unit-3">
<input class="input total-time" type="number" title="" min="0" max="999999.99" step="0.01" name="totalTime" value="0">
<span class="unit" style="top: 6px;">秒(s)</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<input type="checkbox" name="repeat" style="width: 16px; line-height: 15px; height: 15px; cursor: pointer; width: auto; margin-right: 5px;">
<span class="label">是否循环播放</span>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<button class="add-point"><svg class="icon-add"><use xlink:href="#yj-icon-add"></use></svg>增加视点</button>
</div>
<div class="col">
<button class="modify-point"><svg class="icon-edit"><use xlink:href="#yj-icon-edit"></use></svg>调整视点</button>
</div>
<div class="col">
<button class="afreshPlay"><svg class="icon-play"><use xlink:href="#yj-icon-play"></use></svg>播放</button>
</div>
<div class="col">
<button class="cease"><svg class="icon-pause"><use xlink:href="#yj-icon-pause"></use></svg>结束</button>
</div>
</div>
<div class="table">
<div class="table-head">
<div class="tr">
<div class="th">序号</div>
<div class="th">时长(s)</div>
<div class="th">操作</div>
</div>
</div>
<div class="table-body">
<div class="table-empty">
<div class="empty-img"></div>
<p>暂无数据</p>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,438 @@
/**
* @description 飞行漫游
*/
import Dialog from '../../../BaseDialog';
import { html } from "./_element";
import Base from "../index";
import { setActiveViewer, closeRotateAround, closeViewFollow} from '../../../Global/global'
class FlyRoam extends Base {
#clickHandler = undefined
/**
* @constructor
* @param sdk
* @description 飞行漫游
* @param options {object}
* @param options.id {string} 标注id
* @param options.name {string} 名称
* @param options.repeat=0 {number} 重复次数
* @param options.points=[]] {array} 视点列表
* @param options.points[].position {object} 视点位置
* @param options.points[].position.lng {number} 经度
* @param options.points[].position.lat {number} 纬度
* @param options.points[].position.alt {number} 高度
* @param options.points[].orientation {object} 视点方向
* @param options.points[].orientation.heading=0 {number} 视点航向角
* @param options.points[].orientation.pitch=0 {number} 视点俯仰角
* @param options.points[].orientation.roll=0 {number} 视点翻滚角
* @param options.points[].duration=0 {number} 持续时间
**/
constructor(sdk, options = {}, _Dialog = {}) {
super(sdk, options)
this.options.id = options.id || this.randomString()
this.options.name = options.name || '漫游路径'
this.options.points = options.points || []
if(this.options.repeat) {
this.options.repeat = Number(this.options.repeat)
}
this.Dialog = _Dialog
}
get repeat() {
return this.options.repeat
}
/**设置循环次数 (Infinity: 无限循环)*/
set repeat(v) {
if (this.options.repeat != Number(v)) {
this.options.repeat = Number(v)
if (this._DialogObject && this._DialogObject._element && this._DialogObject._element.content) {
let repeatElm = this._DialogObject._element.content.querySelector("input[name='repeat']")
if (v === Infinity) {
repeatElm.checked = true
}
else {
repeatElm.checked = false
}
this.Dialog.changeRepeatStateCallBack && this.Dialog.changeRepeatStateCallBack(repeatElm.checked)
}
}
}
async edit(state) {
let _this = this
let viewer = this.sdk.viewer
let active = 0
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
if (state) {
this._DialogObject = await new Dialog(viewer._container, {
title: '飞行漫游', left: '180px', top: '100px',
closeCallBack: () => {
this.cease()
},
})
await this._DialogObject.init()
let contentElm = document.createElement('div');
contentElm.className = 'fly-roam'
contentElm.innerHTML = html()
this._DialogObject.contentAppChild(contentElm)
let all_elm = contentElm.getElementsByTagName("*")
// EventBinding(all_elm)
let tableBody = contentElm.getElementsByClassName('table-body')[0];
let tableEmpty = contentElm.getElementsByClassName('table-empty')[0]
let handler = {
set: function (target, prop, value) {
target[prop] = value;
if (target.length > 0) {
tableEmpty.style.display = 'none'
}
else {
tableEmpty.style.display = 'flex'
}
return true;
},
};
let i = 0
let points = new Proxy([], handler);
for (i = 0; i < this.options.points.length; i++) {
points.push(this.options.points[i])
addTrElm(this.options.points[i])
}
// let nameImputBoxElm = contentElm.getElementsByClassName('input-box')[0]
// check(nameImputBoxElm, { validator: 'notEmpty', message: '名称不能为空!', trigger: 'input' })
let nameElm = contentElm.querySelector("input[name='name']")
nameElm.value = this.name
nameElm.addEventListener('input', () => {
this.name = nameElm.value
})
let addListBtn = document.createElement('button');
addListBtn.innerHTML = '保存'
addListBtn.addEventListener('click', () => {
if (!this.name) {
this.name = '漫游路径'
nameElm.value = this.name
}
let newPoints = []
points.map((item) => {
newPoints.push(item)
})
this._DialogObject.close()
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(
{
id: this.options.id,
name: this.name,
points: newPoints,
repeat: this.repeat+''
}
)
})
this._DialogObject.footAppChild(addListBtn)
let endBtn = contentElm.getElementsByClassName('cease')[0]
endBtn.addEventListener('click', () => {
viewer.camera.cancelFlight()
})
let flyBtn = contentElm.getElementsByClassName('afreshPlay')[0]
flyBtn.addEventListener('click', () => {
if (points.length > 0) {
this.flyTo(0)
}
})
let addBtn = contentElm.getElementsByClassName('add-point')[0]
addBtn.addEventListener('click', () => {
let position = this.cartesian3Towgs84(viewer.camera.position, viewer)
let time = 0
let data = {
duration: time,
position: position,
orientation: {
heading: viewer.camera.heading,
pitch: viewer.camera.pitch,
roll: viewer.camera.roll
}
}
points.splice(active, 0, data)
this.options.points.splice(active, 0, data)
addTrElm(data)
i++
})
let modifyBtn = contentElm.getElementsByClassName('modify-point')[0]
modifyBtn.addEventListener('click', () => {
if (!active) {
return
}
let position = this.cartesian3Towgs84(viewer.camera.position, viewer)
this.options.points[active - 1].position = points[active - 1].position = position
this.options.points[active - 1].orientation = points[active - 1].orientation = {
heading: viewer.camera.heading,
pitch: viewer.camera.pitch,
roll: viewer.camera.roll
}
this.message({text: '操作成功'})
})
let totalTimeElm = contentElm.querySelector("input[name='totalTime']")
let isTotalTimeElm = contentElm.querySelector("input[name='isTotalTime']")
let repeatElm = contentElm.querySelector("input[name='repeat']")
isTotalTimeElm.addEventListener('change', () => {
let trList = tableBody.getElementsByClassName('tr')
if (isTotalTimeElm.checked && trList.length > 0) {
let time = Number((Number(totalTimeElm.value) / (trList.length - 1)).toFixed(2))
for (let i = 0; i < trList.length - 1; i++) {
points[i].duration = time
this.options.points[i].duration = time
trList[i].querySelector("input[name='time']").value = time
}
trList[trList.length - 1].querySelector("input[name='time']").value = 0
}
})
totalTimeElm.addEventListener('blur', () => {
let trList = tableBody.getElementsByClassName('tr')
totalTimeElm.value = Number(totalTimeElm.value)
if (totalTimeElm.value < 0) {
totalTimeElm.value = 0
}
if (isTotalTimeElm.checked && trList.length > 0) {
let time = Number((Number(totalTimeElm.value) / (trList.length - 1)).toFixed(2))
for (let i = 0; i < trList.length - 1; i++) {
points[i].duration = time
this.options.points[i].duration = time
trList[i].querySelector("input[name='time']").value = time
}
trList[trList.length - 1].querySelector("input[name='time']").value = 0
}
})
repeatElm.checked = (this.repeat === Infinity ? true : false)
repeatElm.addEventListener('change', () => {
if (repeatElm.checked) {
this.repeat = Infinity
}
else {
this.repeat = 0
}
})
// Object.defineProperty(options, 'points', {
// get() {
// return e_allArea.value
// },
// set(value) {
// e_allArea.value = value
// }
// })
function addTrElm(data) {
let trList = tableBody.getElementsByClassName('tr')
if (trList.length > 0) {
trList[trList.length - 1].querySelector("input[name='time']").disabled = undefined
}
let tr_active = tableBody.getElementsByClassName('tr active')[0]
tr_active && (tr_active.className = 'tr')
let tr = document.createElement('div');
tr.className = 'tr active'
tr.innerHTML = `
<div class="td" style="justify-content: center;">视点${i + 1}</div>
<div class="td">
<input class="input time" type="number" title="" min="0" max="999.99" step="0.01" name="time" value="${data.duration}">
</div>
<div class="td action">
<button class="play">播放</span>
<button class="delete">删除</span>
</div>
`
tr.addEventListener('click', (v) => {
if (v.target.parentNode === tr) {
let tr_active = tableBody.getElementsByClassName('tr active')[0]
tr_active && (tr_active.className = 'tr')
tr.className = 'tr active'
for (let m = 0; m < trList.length; m++) {
if (trList[m] === tr) {
active = m + 1
break
}
}
}
})
tr.addEventListener('dblclick', (v) => {
if (v.target.parentNode === tr) {
for (let m = 0; m < trList.length; m++) {
if (trList[m] === tr) {
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(points[m].position.lng, points[m].position.lat, points[m].position.alt),
orientation: points[m].orientation,
duration: 1
})
break
}
}
}
})
let e_play = tr.getElementsByClassName('play')[0]
let e_delete = tr.getElementsByClassName('delete')[0]
let e_time = tr.querySelector("input[name='time']")
e_play.addEventListener('click', () => {
for (let m = 0; m < trList.length; m++) {
if (trList[m] === e_delete.parentNode.parentNode) {
_this.flyTo(m)
}
}
})
e_delete.addEventListener("click", (v) => {
for (let m = 0; m < trList.length; m++) {
if (trList[m] === e_delete.parentNode.parentNode) {
points.splice(m, 1)
points[points.length-1].duration = 0
_this.options.points.splice(m, 1)
tableBody.removeChild(tr)
if (active > m + 1) {
active--
trList[active - 1].className = 'tr active'
}
else if (active == m + 1) {
if (trList.length == m) {
active -= 1
}
if (trList.length != 0) {
trList[active - 1].className = 'tr active'
}
}
// else if(active == m) {
// console.log(trList.length-1, active)
// if (trList.length == active-1) {
// trList[active-2].className = 'tr active'
// }
// else {
// trList[active-1].className = 'tr active'
// }
// }
if (trList.length > 0) {
let lastElm = trList[trList.length - 1].querySelector("input[name='time']")
lastElm.disabled = 'disabled'
lastElm.value = 0
}
break
}
}
// points.splice(i, 1)
// tableBody.removeChild(tr)
// if (trList.length > 0) {
// trList[trList.length - 1].querySelector("input[name='time']").disabled = 'disabled'
// }
})
e_time.addEventListener('input', (v) => {
isTotalTimeElm.checked = false
data.duration = Number(e_time.value)
if (data.duration < 0) {
data.duration = 0
}
})
e_time.addEventListener('blur', () => {
e_time.value = Number(Number(e_time.value).toFixed(2))
if (e_time.value < 0) {
e_time.value = 0
}
});
tableBody.insertBefore(tr, trList[active])
active++
trList[trList.length - 1].querySelector("input[name='time']").disabled = 'disabled'
}
}
}
flyTo(i = 0) {
setActiveViewer(0)
let _this = this
let points = this.options.points
let currentRepeat = this.repeat
closeRotateAround(_this.sdk)
const executeFlyTo = (index = 0, noStart) => {
if (this.#clickHandler) {
this.#clickHandler.destroy()
}
let _this = this
this.#clickHandler = new Cesium.ScreenSpaceEventHandler(_this.sdk.viewer.canvas)
this.#clickHandler.setInputAction((movement) => {
this.cease()
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
let viewer = _this.sdk.viewer
setActiveViewer(0)
viewer.camera.cancelFlight()
// function pauseExecution(seconds) {
// return new Promise(resolve => setTimeout(resolve, seconds * 1000));
// }
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(points[index].position.lng, points[index].position.lat, points[index].position.alt),
orientation: points[index].orientation,
duration: noStart ? points[index - 1].duration : 0.5,
maximumHeight: points[index].position.alt,
complete: async () => {
// if (!noStart) {
// // await pauseExecution(2)
// }
index++
if (this.repeat === Infinity) {
currentRepeat = Infinity
}
else if (currentRepeat === Infinity) {
currentRepeat = this.repeat
}
if (index <= points.length - 1) {
executeFlyTo(index, true)
}
else if (currentRepeat) {
currentRepeat--
executeFlyTo(0)
}
else {
if (this.#clickHandler) {
this.#clickHandler.destroy()
}
}
},
easingFunction: noStart ? Cesium.EasingFunction.LINEAR_NONE : Cesium.EasingFunction.EXPONENTIAL_OUT
})
}
executeFlyTo(i)
}
/** 停止 */
cease() {
this.sdk && this.sdk.viewer && this.sdk.viewer.camera.cancelFlight()
if (this.#clickHandler) {
this.#clickHandler.destroy()
}
}
remove() {
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
else {
this.cease()
}
}
}
export default FlyRoam

View File

@ -0,0 +1,216 @@
/**
* @name: index
* @author: Administrator
* @date: 2023-03-04 10:39
* @descriptionindex
* @update: 2023-03-04 10:39
*/
import { getHost, getToken } from "../../../on";
import Base from '../index'
import Tools from '../../../Tools'
import { syncSplitData } from "../../../Global/SplitScreen";
import { syncData, getSdk as get2DSdk } from '../../../Global/MultiViewportMode'
import { setActiveViewer, closeRotateAround, closeViewFollow} from '../../../Global/global'
class GeoJson extends Base {
/**
* @constructor
* @param sdk
* @param options {object} 参数
* @param options.id {string} id
* @param options.url {string} geojson地址
* @param [options.color=#ef0606] {string} 线条颜色
* @param [options.width=1] {number} 线条宽度
* @example new YJ.Obj.GeoJson(earth,{id:"123",url:""})
* */
constructor(sdk, options = {}) {
super(sdk, options)
this.primitive = undefined
this.positions = []
this.loading = true
}
setDefaultValue() {
super.setDefaultValue()
this.options.host = this.options.host || getHost()
// let url = this.options.url
// if (this.options.host) {
// let o = new URL(this.options.url, this.options.host)
// url = o.href
// }
// this.options.url = url
this.options.color = this.options.color || 'rgb(239, 6, 6, 1)'
this.options.width = this.options.width || 1
}
get show() {
return this.options.show
}
// set show(status) {
// let sdkD = get2DSdk().sdkD
// if (!this.isShowView || !sdkD) {
// this.options.show = status
// }
// if (this.entity) {
// if (!this.showView || this.showView == 3 || !sdkD) {
// for (let i = 0; i < this.entity.entities.values.length; i++) {
// this.entity.entities.values[i].show = this.options.show
// }
// }
// else {
// for (let i = 0; i < this.entity.entities.values.length; i++) {
// this.entity.entities.values[i].show = false
// }
// }
// }
// syncData(this.sdk, this.options.id)
// syncSplitData(this.sdk, this.options.id)
// this.isShowView = false
// }
set show(status) {
this.options.show = status
if (this.entity) {
for (let i = 0; i < this.entity.entities.values.length; i++) {
this.entity.entities.values[i].show = status
}
}
}
async on() {
let url = ""
if (this.options.host.endsWith("yjearth4.0"))
url = this.options.host + '/data/service/getFile'
else
url = this.options.host + '/yjearth4.0/data/service/getFile'
url = url + '?path=' + encodeURIComponent(this.options.url)
let rsp = await fetch(url, {
method: 'get',
headers: {
'Content-Type': 'application/json',
"token": getToken(),
"Authorization": "Bearer " + getToken(),
}
})
let json = await rsp.json()
this.geojson = json
// this.sdk.addIncetance(this.options.id, this)
return GeoJson.addDataToGlobe(this, json.features)
}
/*geojosn暂时只用线的形式*/
static addDataToGlobe(that) {
const geoJsonDataSource = new Cesium.GeoJsonDataSource();
let geojson = that.deepCopyObj(that.geojson)
for (let i = 0; i < geojson.features.length; i++) {
if (!geojson.features[i].id) {
geojson.features[i].id = that.options.id + '_' + i
}
}
// console.log(geojson)
let promise = geoJsonDataSource.load(geojson, {
clampToGround: true,
});
return promise.then(datasource => {
that.entity = datasource
datasource.entities.values.forEach(enetity => {
// console.log(enetity)
let color = Cesium.Color.fromCssColorString(that.options.color)
let colorPolygon = color.withAlpha(0.2)
enetity.show = that.options.show
that.sdk.viewer.entities.add(enetity)
if (enetity.billboard) {
enetity.billboard.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND
enetity.point = new Cesium.PointGraphics({
show: true,
color: color, // 点的颜色
pixelSize: 10, // 点的大小
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
disableDepthTestDistance: Number.POSITIVE_INFINITY // 不应用深度测试
})
}
if (enetity.polyline) {
enetity.polyline.material = color
enetity.polyline.zIndex = that.sdk._entityZIndex
that.sdk._entityZIndex++
}
if (enetity.polygon) {
enetity.polygon.perPositionHeight = false
enetity.polygon.material = colorPolygon
enetity.polygon.zIndex = that.sdk._entityZIndex
enetity.polyline = new Cesium.PolylineGraphics({
positions: enetity.polygon.hierarchy._value.positions,
width: 1,
clampToGround: true,
material: color,
zIndex: that.sdk._entityZIndex
})
that.sdk._entityZIndex++
}
})
that.loading = false
})
}
remove() {
if (this.entity) {
this.entity.entities.values.forEach(enetity => {
this.sdk.viewer.entities.remove(enetity)
})
this.entity = null
this.geojson = {}
}
}
async flyTo() {
if (!this.loading) {
if (this.geojson) {
setActiveViewer(0)
closeRotateAround(this.sdk)
closeViewFollow(this.sdk)
let range = turf.bbox(this.geojson);
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 = { lng: range[0], lat: range[1] }
// 如果没有高度值,则获取紧贴高度计算
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 {
this.viewer.camera.flyTo({
destination: Cesium.Rectangle.fromDegrees(...range)
});
}
}
}
}
flicker() { }
}
export default GeoJson

View File

@ -0,0 +1,145 @@
/**
* @name: index
* @author: Administrator
* @date: 2023-03-04 10:39
* @descriptionindex
* @update: 2023-03-04 10:39
*/
import { getHost } from "../../../on";
import Base from '../index'
import Tools from '../../../Tools'
class GeoJson extends Base {
/**
* @constructor
* @param sdk
* @param options {object} 参数
* @param options.id {string} id
* @param options.url {string} geojson地址
* @param [options.color=#ef0606] {string} 线条颜色
* @param [options.width=1] {number} 线条宽度
* @example new YJ.Obj.GeoJson(earth,{id:"123",url:""})
* */
constructor(sdk, options = {}) {
super(sdk, options)
this.primitive = undefined
this.positions = []
this.loading = true
}
setDefaultValue() {
super.setDefaultValue()
this.options.host = this.options.host || getHost()
let url = this.options.url
if(this.options.host) {
let o = new URL(this.options.url, this.options.host)
url = o.href
}
this.options.url = url
this.options.color = this.options.color || '#ef0606'
this.options.width = this.options.width || 1
}
get show() {
if (this.primitive) return this.primitive.show
return undefined
}
set show(status) {
if (this.primitive) {
this.primitive.show = status
}
}
async on() {
let rsp = await fetch(this.options.url)
let json = await rsp.json()
return GeoJson.addDataToGlobe(this, json.features)
}
/*geojosn暂时只用线的形式*/
static addDataToGlobe(that, features) {
const instances = []
for (let i = 0; i < features.length; i++) {
let positions = []
if ('LineString' === features[i].geometry.type) {
features[i].geometry.coordinates.forEach(c => {
that.positions.push({ lng: c[0], lat: c[1] })
positions.push(c[0], c[1])
})
}
if ('Polygon' === features[i].geometry.type) {
features[i].geometry.coordinates.forEach(polygon => {
polygon.forEach(c => {
that.positions.push({ lng: c[0], lat: c[1] })
positions.push(c[0], c[1])
})
})
}
const polyline = new Cesium.GroundPolylineGeometry({
positions: Cesium.Cartesian3.fromDegreesArray(positions),
width: that.options.width //线宽
// vertexFormat: Cesium.PolylineColorAppearance.VERTEX_FORMAT
})
// let geometry = Cesium.PolylineGeometry.createGeometry(polyline)
instances.push(
new Cesium.GeometryInstance({
geometry: polyline
// attributes: {
// color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.BLUE),
// },
})
)
}
that.primitive = new Cesium.GroundPolylinePrimitive({
geometryInstances: instances,
// appearance: new Cesium.PerInstanceColorAppearance({ // 为每个instance着色
// translucent: true,
// closed: false
// }),
appearance: new Cesium.PolylineMaterialAppearance({
material: Cesium.Material.fromType('Color', {
color: Cesium.Color.fromCssColorString(that.options.color)
})
}),
asynchronous: false, // 确定基元是异步创建还是阻塞直到准备就绪
show: that.options.show ?? true
})
that.viewer.scene.primitives.add(that.primitive)
that.loading = false
}
remove() {
if (this.primitive) {
super.remove()
this.viewer.scene.primitives.remove(this.primitive)
this.primitive = null
}
}
flyTo() {
if (!this.loading) {
if (this.positions) {
let arr = new Tools().cal_envelope(this.positions)
var rectangle = new Cesium.Rectangle.fromDegrees(
arr[0][0],
arr[0][1],
arr[2][0],
arr[2][1]
)
this.viewer.camera.flyTo({
destination: rectangle
})
}
}
}
flicker() {}
}
export default GeoJson

View File

@ -0,0 +1,185 @@
/**
* @name: index
* @author: Administrator
* @date: 2023-03-04 10:39
* @descriptionindex
* @update: 2023-03-04 10:39
*/
import { getHost } from "../../../on";
import Base from '../index'
import Tools from '../../../Tools'
class GeoJson extends Base {
/**
* @constructor
* @param sdk
* @param options {object} 参数
* @param options.id {string} id
* @param options.url {string} geojson地址
* @param [options.color=#ef0606] {string} 线条颜色
* @param [options.width=1] {number} 线条宽度
* @example new YJ.Obj.GeoJson(earth,{id:"123",url:""})
* */
constructor(sdk, options = {}) {
super(sdk, options)
this.primitive = undefined
this.positions = []
this.loading = true
}
setDefaultValue() {
super.setDefaultValue()
this.options.host = this.options.host || getHost()
let url = this.options.url
if (this.options.host) {
let o = new URL(this.options.url, this.options.host)
url = o.href
}
this.options.url = url
this.options.color = this.options.color || 'rgb(239, 6, 6, 0.2)'
this.options.width = this.options.width || 1
}
get show() {
if (this.primitive) return this.primitive.show
return undefined
}
set show(status) {
if (this.primitive) {
this.primitive.show = status
}
}
async on() {
let rsp = await fetch(this.options.url)
let json = await rsp.json()
this.geojson = json
return GeoJson.addDataToGlobe(this, json.features)
}
/*geojosn暂时只用线的形式*/
static addDataToGlobe(that, features) {
const instancesList = []
const instancesPolygon = []
for (let i = 0; i < features.length; i++) {
let color = Cesium.Color.fromRandom().withAlpha(0.2)
if(features[i].geometry.type === 'LineString' || features[i].geometry.type === 'MultiLineString') {
let coordinates = features[i].geometry.coordinates
if(features[i].geometry.type === 'LineString') {
coordinates = [features[i].geometry.coordinates]
}
for (let m = 0; m < coordinates.length; m++) {
let item = coordinates[i]
let positions = []
item.forEach(c => {
positions.push(c[0], c[1])
})
const polyline = new Cesium.GroundPolylineGeometry({
positions: Cesium.Cartesian3.fromDegreesArray(positions),
width: that.options.width //线宽
})
instancesList.push(
new Cesium.GeometryInstance({
geometry: polyline
})
)
}
}
if(features[i].geometry.type === 'Polygon' || features[i].geometry.type === 'MultiPolygon') {
let coordinates = features[i].geometry.coordinates
if(features[i].geometry.type === 'Polygon') {
coordinates = [features[i].geometry.coordinates]
}
for (let m = 0; m < coordinates.length; m++) {
let item = coordinates[m]
item.forEach(p => {
let positions = []
p.forEach(c => {
positions.push(c[0], c[1])
})
let polygon = new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray(positions)),
});
instancesPolygon.push(
new Cesium.GeometryInstance({
geometry: polygon,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
Cesium.Color.fromRandom().withAlpha(0.2)
),
show: new Cesium.ShowGeometryInstanceAttribute(that.options.show ?? true), //显示或者隐藏
},
})
)
const polyline = new Cesium.GroundPolylineGeometry({
positions: Cesium.Cartesian3.fromDegreesArray(positions),
width: 2
})
instancesList.push(
new Cesium.GeometryInstance({
geometry: polyline
})
)
})
}
}
}
if (instancesList.length > 0) {
that.primitive = new Cesium.GroundPolylinePrimitive({
geometryInstances: instancesList,
appearance: new Cesium.PolylineMaterialAppearance({
material: Cesium.Material.fromType('Color', {
color: Cesium.Color.fromCssColorString(that.options.color)
})
}),
asynchronous: false, // 确定基元是异步创建还是阻塞直到准备就绪
show: that.options.show ?? true
})
that.viewer.scene.primitives.add(that.primitive)
}
if (instancesPolygon.length > 0) {
that.primitive = new Cesium.GroundPrimitive({
geometryInstances: instancesPolygon,
appearance: new Cesium.PerInstanceColorAppearance({
translucent: true, //false时透明度无效
closed: false,
}),
asynchronous: false, // 确定基元是异步创建还是阻塞直到准备就绪
show: that.options.show ?? true
})
that.viewer.scene.primitives.add(that.primitive)
}
that.loading = false
}
remove() {
if (this.primitive) {
super.remove()
this.viewer.scene.primitives.remove(this.primitive)
this.primitive = null
}
}
flyTo() {
if (!this.loading) {
if(this.geojson) {
let range = turf.bbox(this.geojson);
this.viewer.camera.flyTo({
destination: Cesium.Rectangle.fromDegrees(...range)
});
}
}
}
flicker() { }
}
export default GeoJson

View File

@ -0,0 +1,22 @@
function html() {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">涂鸦颜色</span>
<div class="color"></div>
</div>
<div class="col">
<span class="label">线条宽度</span>
<div class="input-number input-number-unit-2" style="width: 80px;">
<input class="input" type="number" title="" min="1" max="99" step="1" @model="width">
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
`
}
export { html }

View File

@ -0,0 +1,227 @@
/**
* 涂鸦
*/
import Draw from '../../../Draw/draw'
import MouseTip from '../../../MouseTip'
import MouseEvent from '../../../Event'
import Dialog from '../../../BaseDialog';
import EventBinding from '../../Element/Dialog/eventBinding';
import { html } from "./_element";
import { CameraController } from '../../../Global/global'
class Graffiti extends Draw {
/**
* @constructor
* @param sdk
* @description 涂鸦
* @param options {object} 线属性
* @param options.width=10{number} 宽度
* @param options.color=#ff0000{string} 宽度
* */
constructor(sdk, options = {}) {
super(sdk, options);
this.options.width = options.width || 1
this.options.color = options.color || '#ff0000'
this._elms = {};
this._EventBinding = new EventBinding()
Graffiti.edit(this, true)
}
get color() {
return this.options.color
}
set color(v) {
if(!this.options.color) {
return
}
this.options.color = v
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
})
}
}
get width() {
return this.options.width
}
set width(v) {
this.options.width = v
this._elms.width && this._elms.width.forEach((item) => {
item.value = v
})
}
// 编辑框
static async edit(that, state) {
if (state) {
that._DialogObject = await new Dialog(that.sdk.viewer._container, {
title: '涂鸦参数',
})
await that._DialogObject.init()
let contentElm = document.createElement('div');
contentElm.innerHTML = html()
that._DialogObject.contentAppChild(contentElm)
// 颜色组件
let colorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("color")[0],
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: that.color,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
that.color = color
},//点击确认按钮事件回调
clear: () => {
that.color = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
that._DialogObject._element.body.className = that._DialogObject._element.body.className + ' graffiti'
let all_elm = contentElm.getElementsByTagName("*")
that._EventBinding.on(that, all_elm)
that._elms = that._EventBinding.element
that._elms.color = [colorPicker]
let confirmBtn = document.createElement('button');
confirmBtn.className = 'confirm';
confirmBtn.innerHTML = '确认'
that._DialogObject.footAppChild(confirmBtn)
confirmBtn.addEventListener('click', () => {
that.start()
Graffiti.edit(that, false)
});
}
else {
if (that._DialogObject && that._DialogObject.close) {
that._DialogObject.close()
that._DialogObject = null
}
}
}
/**
* @desc 开始动态获绘制线
* @method start
* })
* */
start() {
let _this = this
if (YJ.Measure.GetMeasureStatus()) {
console.log('上一次测量未结束')
} else {
let viewer = this.sdk.viewer
CameraController(this.sdk, false)
super.start()
YJ.Measure.SetMeasureStatus(true)
this.tip = new MouseTip('长按左键,拖动鼠标进行涂鸦,右键结束涂鸦', this.sdk)
this.event = new MouseEvent(this.sdk)
this.positions = []
this.points_ids = [] //存放左键点击时临时添加的point的id
let polylineArray = []
let positions = []
this.event.mouse_left_down((movement, cartesian) => {
positions = []
let line = this.sdk.viewer.entities.add({
name: '涂鸦',
polyline: {
positions: new Cesium.CallbackProperty(function () {
return positions
}, false),
width: this.width,
clampToGround: true,
material: Cesium.Color.fromCssColorString(this.color),
zIndex: 99999999
}
})
polylineArray.push(line)
this.event.mouse_move((movement, cartesian) => {
this.tip.setPosition(
cartesian,
movement.endPosition.x,
movement.endPosition.y
)
positions.push(cartesian)
})
})
this.event.mouse_left_up((movement, cartesian) => {
polylineArray[polylineArray.length-1].polyline.positions = positions
this.event.mouse_move((movement, cartesian) => {
this.tip.setPosition(
cartesian,
movement.endPosition.x,
movement.endPosition.y
)
})
})
this.event.mouse_move((movement, cartesian) => {
this.tip.setPosition(
cartesian,
movement.endPosition.x,
movement.endPosition.y
)
})
this.event.mouse_right((movement, cartesian) => {
this.end()
})
this.event.gesture_pinck_start((movement, cartesian) => {
let startTime = new Date()
this.event.gesture_pinck_end(() => {
let endTime = new Date()
if (endTime - startTime >= 500) {
// 长按取消
this.end()
}
})
})
}
}
/**
* @desc 结束制线
* @method end
* })
* */
end() {
YJ.Measure.SetMeasureStatus(false)
this.event && this.event.destroy()
this.event = undefined
this.tip && this.tip.destroy()
this.tip = undefined
CameraController(this.sdk, true)
}
remove() {
this.end()
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
let entities = this.sdk.viewer.entities.values
for (let i = entities.length - 1; i >= 0; i--) {
if (entities[i].name === '涂鸦') {
this.sdk.viewer.entities.remove(entities[i])
}
}
}
flicker() {}
}
export default Graffiti

View File

@ -0,0 +1,119 @@
function html() {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col"></div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<button class="anchor btn">调整锚点</button>
</div>
<div class="col mode-box">
<span class="label" style="flex: unset;">军标模式</span>
<div class="mode"></div>
</div>
</div>
<div class="row" mode="0">
<div class="col">
<span class="label">旋转角度</span>
<input type="range" max="360" min="0" step="0.1" @model="angle">
<div class="input-number input-number-unit" style="width: 100px;flex: 0 0 100px;margin-left: 10px;">
<input class="input" type="number" title="" min="0" max="360" step="0.1" @model="angle">
<span class="unit">°</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row" mode="0">
<div class="col">
<span class="label">调整大小</span>
<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="40000" step="0.1" @model="scale">
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row" mode="1">
<div class="col height-mode-box" style="flex: 0 0 155px;margin-right: 10px;">
<span class="label" style="flex: 0 0 56px;">高度模式</span>
<div class="height-mode"></div>
</div>
<div class="col" style="margin: 0 10px;">
<div class="height-box" style="display: flex; align-items: center;">
<span class="label" style="flex: 0 0 56px;">高度</span>
<div class="input-number input-number-unit-1">
<input class="input height" type="number" title="" min="-9999999" max="999999999">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="col" style="margin-left: 10px;">
<span class="label">图标倍数</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" data-min="0.1" max="99" @model="billboardScale">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row" mode="1">
<div class="col" style="flex: 0 0 155px;margin-right: 10px;">
<span class="label">视野缩放</span>
<input class="btn-switch" type="checkbox" @model="billboardScaleByDistance">
</div>
<div class="col" style="margin: 0 10px;">
<span class="label">最近距离</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="1" max="99999999" @model="billboardNear">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col" style="margin-left: 10px;">
<span class="label">最远距离</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="1" max="99999999" @model="billboardFar">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
<h4 mode="1">文字设置</h4>
<div class="row" mode="1">
<div class="col" style="flex: 0 0 80px;margin: 0 10px;">
<span class="label" style="flex: none;">显隐</span>
<input class="btn-switch" type="checkbox" @model="labelShow">
</div>
<div class="col font-select-box" style="margin: 0 0px;flex: 0 0 150px;">
<span class="label" style="flex: none;">字体选择</span>
<div class="input input-select font-select"></div>
</div>
<div class="col" style="margin: 0 10px;">
<span class="label">文字大小</span>
<div class="input-number input-number-unit-2">
<input class="input" type="number" title="" min="1" max="99" @model="labelFontSize" style="width: 70px;">
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
<div class="col" style="margin-left: 10px;">
<span class="label">文字颜色</span>
<div class="labelColor"></div>
</div>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,113 @@
import { attributeElm } from '../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col">
<span class="label">颜色</span>
<div class="color"></div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">旋转角度</span>
<input type="range" max="360" min="0" step="0.1" @model="angle">
<div class="input-number input-number-unit" style="width: 100px;flex: 0 0 100px;margin-left: 10px;">
<input class="input" type="number" title="" min="0" max="360" step="0.1" @model="angle">
<span class="unit">°</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col x-scale">
<span class="label">X 轴大小</span>
<input type="range" max="200" min="0.001" step="0.001">
<div class="input-number" style="width: 100px;flex: 0 0 100px;margin-left: 10px;">
<input class="input" type="number" title="" min="0.001" max="200" step="0.001">
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col y-scale">
<span class="label">Y 轴大小</span>
<input type="range" max="200" min="0.001" step="0.001">
<div class="input-number" style="width: 100px;flex: 0 0 100px;margin-left: 10px;">
<input class="input" type="number" title="" min="0.001" max="200" step="0.001">
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col" style="flex: 5;">
<span class="label">文字内容</span>
<input class="input" type="text" @model="textValue" maxlength="30">
</div>
<div class="col">
<button class="btn" @click="textPosPick">设置位置</span>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">文字开关</span>
<input class="btn-switch" type="checkbox" @model="textShow">
</div>
<div class="col">
<span class="label">字体颜色</span>
<div class="textColor"></div>
</div>
<div class="col">
<span class="label">字体大小</span>
<div class="input-number input-number-unit-2">
<input class="input" type="number" title="" min="1" max="99" @model="textFontSize">
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">视野缩放</span>
<input class="btn-switch" type="checkbox" @model="textScaleByDistance">
</div>
<div class="col">
<span class="label">最近距离</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="1" max="99999999" @model="textNear">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">最远距离</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="1" max="99999999" @model="textFar">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item attribute-info">
<div class="row">
${attributeElm(that)}
</div>
</div>
`
}
export { html }

View File

@ -0,0 +1,792 @@
import Base from "../index";
import * as THREE from '../../../../static/3rdparty/three/three.module.min.js';
import { SVGLoader } from '../../../../static/3rdparty/three/jsm/loaders/SVGLoader.js';
// 合并图形,统一颜色
class GroundSvg extends Base {
#loadEvent=void 0
constructor(sdk, options = {}) {
super(sdk, options);
this.options.angle = this.options.angle || 0
this.options.color = this.options.color || '#ff0000'
this.loaded = 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.hierarchys = []
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.init()
}
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()
}
get color() {
return this.options.color
}
set color(v) {
this.options.color = v
for (let i = 0; i < this.entity.values.length; i++) {
this.entity.values[i].polygon.material = Cesium.Color.fromCssColorString(this.options.color || '#ff0000')
}
}
get angle() {
return this.options.angle
}
set angle(v) {
this.options.angle = v
this.update()
}
get scale() {
return this.options.scale
}
set scale(scale) {
this.options.scale.x = scale.x
this.options.scale.y = scale.y
this.update()
}
init() {
this.hierarchys = []
let geometryArray = []
const loader = new SVGLoader();
loader.load(this.options.url, (data) => {
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(mesh.geometry)
}
}
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(mesh.geometry)
}
}
}
}
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];
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++) {
let positions = []
let position = []
geometryArray[key].scale(scale, scale, 1)
geometryArray[key].rotateX(THREE.MathUtils.degToRad(180))
let geometry = geometryArray[key];
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 (geojson) {
geojson = turf.union(geojson, polygon);
}
else {
geojson = polygon
}
}
}
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
geojson = JSON.parse(JSON.stringify(this.geojson))
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)
this.hierarchys.push(hierarchy)
}
}
else {
let hierarchy = this.getHierarchyPolygon(geojson)
this.hierarchys.push(hierarchy)
}
this.entity = new Cesium.EntityCollection()
for (let i = 0; i < this.hierarchys.length; i++) {
this.entity.add(this.sdk.viewer.entities.add({
polygon: {
hierarchy: new Cesium.CallbackProperty(() => {
let hierarchy = this.hierarchys[i]
let holes = []
for (let m = 0; m < hierarchy.holes.length; m++) {
holes.push({
positions: hierarchy.holes[m]
})
}
return {
positions: hierarchy.positions,
holes: holes
}
}, false),
material: Cesium.Color.fromCssColorString(this.color),
zIndex: 1
}
}))
}
this.scale = this.scale
this.loaded = true
if (this.#loadEvent) {
this.#loadEvent()
}
})
}
drag() {
this.createControlPoints()
this.update()
}
getHierarchyPolygon(geojson, key) {
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' });
positions.push(Cesium.Cartesian3.fromDegrees(...destination.geometry.coordinates))
}
if (i === 0) {
hierarchy.positions = positions
}
else {
holes.push(positions)
}
}
hierarchy.holes = holes
return hierarchy
}
createControlPoints() {
if (this.ScreenSpaceEventHandler) {
this.ScreenSpaceEventHandler.destroy()
this.ScreenSpaceEventHandler = null
}
this.ScreenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler(
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 = sdk.viewer.scene.pickPosition(movement.endPosition)
if (!eCartesian) {
const ray = sdk.viewer.camera.getPickRay(movement.endPosition);
eCartesian = sdk.viewer.scene.globe.pick(ray, sdk.viewer.scene);
}
if (!sCartesian || !eCartesian) {
return
}
let position1 = this.cartesian3Towgs84(sCartesian, sdk.viewer)
let position2 = this.cartesian3Towgs84(eCartesian, 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;
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);
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
}
if ((angleH > -360 && angleH < -90) || (angleH < 360 && angleH > 90)) {
angleH = angleH + 180
}
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 = w / 3.5
this.scale.y = 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
}
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
}
if ((angleH > -360 && angleH < -90) || (angleH < 360 && angleH > 90)) {
angleH = angleH + 180
}
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 = w / 3.5
this.scale.y = 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
}
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
}
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) {
scale.y = 0
}
if (scale.x > 200) {
scale.x = 200
}
if (scale.x < 0) {
scale.x = 0
}
this.scale = { ...scale }
}
else {
let pickedObjectArray = 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 = 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(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(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.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)
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
for (let i = 0; i < this.controlPoints.length; i++) {
let color = '#00ff0a'
if (i === 5) {
color = '#ffff00'
}
if (i === 0) {
color = '#ff0000'
}
let entity = sdk.viewer.entities.getOrCreateEntity('svg-control-points_' + i)
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, // 点的大小
disableDepthTestDistance: Number.POSITIVE_INFINITY // 不应用深度测试
})
this.pointEntityCollection.add(entity)
}
}
_updateGeojson(data, x, y) {
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() {
let point = turf.point([this.position.lng, this.position.lat]);
let options = { units: 'kilometers' };
let hierarchys = []
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 geojson = JSON.parse(JSON.stringify(this.geojson))
this._updateGeojson(geojson.geometry.coordinates, x, y)
geojson = turf.transformRotate(geojson, this.angle, { pivot: [0, 0] });
let 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 angle2 = turf.rhumbBearing(point1, point2);
array2.push(
{
origin: geojson.geometry.coordinates[i][m][n],
distance: distance,
angle: angle2
}
)
}
array.push(array2)
}
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 array2 = []
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 angle2 = turf.rhumbBearing(point1, point2);
array.push({
origin: geojson.geometry.coordinates[i][m],
distance: distance,
angle: angle2
})
}
directionDistance.push(array)
}
}
geojson.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)
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 (geojson.geometry.type === 'MultiPolygon') {
for (let i = 0; i < geojson.geometry.coordinates.length; i++) {
let hierarchy = this.getHierarchyPolygon(geojson, i)
hierarchys.push(hierarchy)
}
}
else {
let hierarchy = this.getHierarchyPolygon(geojson)
hierarchys.push(hierarchy)
}
this.hierarchys = hierarchys
}
load(callback) {
if(this.loaded) {
callback();
}
else {
this.#loadEvent = callback
}
}
}
export default GroundSvg

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,131 @@
// import Tools from '../../Tools'
import Base from "../index";
export default class HeatMap extends Base {
/**
* @constructor
* @param sdk
* @description 热力图
* @param options {object} 属性
* @param options.id {string} 唯一标识
* @param options.show=true {boolean} 显示/隐藏
* @param options.name {string} 名称
* @param options.gradient {object} 渐变色
* @param {Array.<object>} options.positions 经纬度和高度的列表,值交替 [{lon,lat,alt},...]
* @param {Array.<object>} options.data 热力图数据 [{lon,lat,value},...]
* */
constructor(sdk, options) {
super(sdk, options)
this.viewer = sdk.viewer
this.options.show = (options.show || options.show === false) ? options.show : true
this.options.positions = this.options.positions || []
this.options.data = this.options.data
this.options.gradient = options.gradient || {
'0.9': 'red',
'0.8': 'orange',
'0.7': 'yellow',
'0.5': 'blue',
'0.3': 'green'
}
this.entity = {
id: this.options.id
}
if (!this.options.positions || this.options.positions.length < 3) {
this._error = '最少需要三个坐标!'
console.warn(this._error)
window.ELEMENT && window.ELEMENT.Message({
message: this._error,
type: 'warning',
duration: 1500
});
}
else {
let array = []
for (let i = 0; i < this.options.positions.length; i++) {
array.push([this.options.positions[i].lng, this.options.positions[i].lat])
}
let line = turf.lineString(array);
let bbox = turf.bbox(line);
this.bounds = {
west: bbox[0], south: bbox[1], east: bbox[2], north: bbox[3]
}
HeatMap.add(this)
}
}
static add(that) {
let arr = []
that.options.positions.forEach(item => {
arr.push(item.lng, item.lat)
})
let data = HeatMap.getData(that)
let heatMap = that.createHeatMap(data.max, data.data)
that.entity = new Cesium.Entity({
id: that.options.id,
show: that.options.show,
polygon: {
hierarchy: new Cesium.PolygonHierarchy(
Cesium.Cartesian3.fromDegreesArray(arr)
),
material: heatMap._heatmap._renderer.canvas,
zIndex: that.sdk._entityZIndex
}
})
that.sdk._entityZIndex ++
that.viewer.entities.add(that.entity)
}
remove() {
this.viewer.entities.remove(this.entity)
this.entity = null
}
static getData(that) {
let len = 1000
let data = []
if (that.options.data && Array.isArray(that.options.data)) {
let max = that.options.data[0].value
for (let i = 0; i < that.options.data.length; i++) {
let val = that.options.data[i].value
max = Math.max(max, val)
data.push({
x: that.options.data[i].lng,
y: that.options.data[i].lat,
value: val
})
}
return { max: max, data: data }
}
else {
//构建一些随机数据点
let max = 0
while (len--) {
let val = Math.floor(Math.random() * 1000)
max = Math.max(max, val)
let point = {
x: Math.random() * (that.bounds.east - that.bounds.west) + that.bounds.west,
y: Math.random() * (that.bounds.north - that.bounds.south) + that.bounds.south,
value: val
}
data.push(point)
}
return { max: max, data: data }
}
}
createHeatMap(max, data) {
let heatMap = CesiumHeatmap.create(
this.bounds, // 矩形坐标
{ // heatmap相应参数
backgroundColor: "rgba(0,0,0,0)",
radius: 20,
maxOpacity: .5,
minOpacity: 0,
blur: .75,
gradient: this.options.gradient
}
)
heatMap.setWGS84Data(0, max, data);
return heatMap
}
}

View File

@ -0,0 +1,247 @@
// /**
// * @description 动态线
// */
// import FlowPictureMaterialProperty from '../../Materail/FlowPictureMaterialProperty'
// import Dialog from '../../Element/Dialog';
// import cy_slider from "../../Element/cy_html_slider";
// import Base from "../index";
// class ItineraryMove extends Base {
// /**
// * @constructor
// * @param sdk
// * @param options {object} 线属性
// * @param options.name{string} 名称
// * @param options.image{string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} 指定 Image、URL、Canvas 或 Video 的属性
// * @param options.width=10{number} 线宽
// * @param options.duration=500{number} 移动速度
// * @param {Array.<number>} options.positions 经度、纬度和高度的列表[{经度,纬度,高度},{经度,纬度,高度}...]
// * */
// constructor(sdk, options = {}) {
// super(sdk, options);
// this.options.name = options.name || ''
// this.options.image = options.image || this.getSourceRootPath() + '/img/arrowRoad.jpg'
// this.options.width = (options.width || options.width === 0) ? options.width : 10
// this.options.space = (options.space || options.space === 0) ? options.space : 1
// this.options.backgroundColor = options.backgroundColor || "#ff000000"
// this.options.duration = options.duration || options.duration === 0 || 500
// ItineraryMove.create(this)
// }
// static create(that) {
// let positions = that.options.positions
// let fromDegreesArray = []
// for (let i = 0; i < positions.length; i++) {
// fromDegreesArray.push(positions[i].lng, positions[i].lat)
// }
// const canvasEle = document.createElement('canvas');
// const ctx = canvasEle.getContext('2d')
// const myImg = new Image()
// myImg.src = that.options.image
// myImg.onload = function () {
// canvasEle.width = myImg.width * (that.options.space + 1)
// canvasEle.height = myImg.height
// ctx.drawImage(myImg, myImg.width * (that.options.space / 2), 0)
// that.entity = new Cesium.EntityCollection();
// let imgEntity = that.sdk.viewer.entities.add({
// name: 'imgEntity',
// polyline: {
// positions: Cesium.Cartesian3.fromDegreesArray(fromDegreesArray),
// // height: 1,
// width: that.options.width,
// clampToGround: true,
// material: new FlowPictureMaterialProperty({
// image: canvasEle,
// repeat: new Cesium.CallbackProperty(function () {
// var positionProperty = imgEntity.polyline.positions;
// var positions = positionProperty.getValue(that.sdk.viewer.clock.currentTime);
// if (!Cesium.defined(positions)) {
// return new Cesium.Cartesian2(1.0, 1.0);
// }
// var distance = 0;
// for (var i = 0; i < positions.length - 1; ++i) {
// distance += Cesium.Cartesian3.distance(positions[i], positions[i + 1]);
// }
// var repeatX = distance / imgEntity.polyline.width.getValue();
// // 根据地图缩放程度调整repeatX
// var cameraHeight = that.sdk.viewer.camera.positionCartographic.height;
// var boundingSphere = new Cesium.BoundingSphere(
// new Cesium.Cartesian3(-1000000, 0, 0), // 中心点坐标
// 500000 // 半径(距离)
// );
// // 获取绘图缓冲区的宽度和高度(通常是屏幕的分辨率)
// var drawingBufferWidth = that.sdk.viewer.canvas.clientWidth;
// var drawingBufferHeight = that.sdk.viewer.canvas.clientHeight;
// // 使用 getPixelSize 方法获取包围球在屏幕上的像素大小
// var groundResolution = that.sdk.viewer.scene.camera.getPixelSize(boundingSphere, drawingBufferWidth, drawingBufferHeight)
// repeatX *= groundResolution / cameraHeight / (that.options.space * (canvasEle.width / canvasEle.height * 5) + 1);
// // if (repeatX < 3) {
// // repeatX = 3
// // }
// return new Cesium.Cartesian2(repeatX, 1.0);
// }, false),
// duration: that.options.duration,
// zIndex: that.sdk._entityZIndex,
// })
// // material: new Cesium.ImageMaterialProperty(
// // {
// // image: this.options.image,
// // repeat: new Cesium.CallbackProperty(function () {
// // var positionProperty = _this.entity.polyline.positions;
// // var positions = positionProperty.getValue(_this.sdk.viewer.clock.currentTime);
// // if (!Cesium.defined(positions)) {
// // return new Cesium.Cartesian2(1.0, 1.0);
// // }
// // var distance = 0;
// // for (var i = 0; i < positions.length - 1; ++i) {
// // distance += Cesium.Cartesian3.distance(positions[i], positions[i + 1]);
// // }
// // var repeatX = distance / _this.entity.polyline.width.getValue();
// // // 根据地图缩放程度调整repeatX
// // var cameraHeight = _this.sdk.viewer.camera.positionCartographic.height;
// // var boundingSphere = new Cesium.BoundingSphere(
// // new Cesium.Cartesian3(-1000000, 0, 0), // 中心点坐标
// // 500000 // 半径(距离)
// // );
// // // 获取绘图缓冲区的宽度和高度(通常是屏幕的分辨率)
// // var drawingBufferWidth = _this.sdk.viewer.canvas.clientWidth;
// // var drawingBufferHeight = _this.sdk.viewer.canvas.clientHeight;
// // // 使用 getPixelSize 方法获取包围球在屏幕上的像素大小
// // var groundResolution = _this.sdk.viewer.scene.camera.getPixelSize(boundingSphere, drawingBufferWidth, drawingBufferHeight);
// // repeatX *= groundResolution / cameraHeight / (Math.abs(_this.sdk.viewer.camera.pitch) + 1);
// // if (repeatX < 3) {
// // repeatX = 3
// // }
// // return new Cesium.Cartesian2(repeatX, 1.0);
// // }, false),
// // }
// // )
// },
// })
// that.sdk._entityZIndex ++
// let lineEntity = that.sdk.viewer.entities.add({
// name: 'lineEntity',
// polyline: {
// positions: Cesium.Cartesian3.fromDegreesArray(fromDegreesArray),
// width: that.options.width,
// clampToGround: true,
// material: Cesium.Color.fromCssColorString(that.options.backgroundColor),
// zIndex: that.sdk._entityZIndex,
// },
// })
// that.sdk._entityZIndex ++
// // let geojson = {
// // type: "FeatureCollection",
// // features: [
// // {
// // type: "Feature",
// // geometry: {
// // type: "LineString",
// // coordinates: [
// // [100.0, 40],
// // [110.0, 40],
// // [120.0, 40],
// // ],
// // },
// // properties: { color: '#00c311' }
// // },
// // {
// // type: "Feature",
// // geometry: {
// // type: "LineString",
// // coordinates: [
// // [120.0, 70],
// // [130.0, 70],
// // [140.0, 40],
// // ],
// // },
// // properties: { color: '#ff0000' }
// // }
// // ]
// // }
// // var positions = [];
// // var colors = [];
// // for (var i = 0; i < geojson.features.length; i++) {
// // for(let m = 0; m<geojson.features[i].geometry.coordinates.length;m++) {
// // positions.push(Cesium.Cartesian3.fromDegrees(...geojson.features[i].geometry.coordinates[m]));
// // colors.push(Cesium.Color.fromCssColorString(geojson.features[i].properties.color));
// // }
// // }
// // this.entity = this.sdk.viewer.scene.primitives.add(new Cesium.Primitive({//GroundPrimitive贴地
// // geometryInstances: new Cesium.GeometryInstance({
// // geometry: new Cesium.CorridorGeometry({
// // positions: Cesium.Cartesian3.fromDegreesArray(fromDegreesArray),
// // width: this.options.width,
// // height: this.options.height,
// // cornerType: Cesium.CornerType.MITERED,
// // vertexFormat: Cesium.MaterialAppearance.MaterialSupport.ALL.vertexFormat
// // }),
// // attributes: {
// // color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 1.0, 1.0, 0.5))
// // }
// // }),
// // appearance: new Cesium.MaterialAppearance({
// // material: Cesium.Material.fromType('Image', {
// // image: this.options.image,
// // repeat: new Cesium.Cartesian2(100, 1.0)
// // }),
// // faceForward: true,
// // renderState: {
// // blending: Cesium.BlendingState.ALPHA_BLEND
// // }
// // })
// // }));
// // const instance = new Cesium.GeometryInstance({
// // geometry : new Cesium.GroundPolylineGeometry({
// // positions : Cesium.Cartesian3.fromDegreesArray([
// // -112.1340164450331, 36.05494287836128,
// // -112.08821010582645, 36.097804071380715
// // ]),
// // width : 4.0
// // }),
// // id : 'object returned when this instance is picked and to get/set per-instance attributes'
// // });
// // _this.sdk.viewer.scene.groundPrimitives.add(new Cesium.GroundPolylinePrimitive({
// // geometryInstances: new Cesium.GeometryInstance({
// // geometry: new Cesium.GroundPolylineGeometry({
// // positions: positions,
// // width: 40.0,
// // colors : colors
// // })
// // }),
// // appearance: new Cesium.PolylineMaterialAppearance()
// // }));
// // console.log('entity', _this.entity)
// that.entity.add(imgEntity)
// that.entity.add(lineEntity)
// that.sdk.viewer.entities.add(that.entity)
// }
// }
// /**
// * 删除
// */
// remove() {
// for (let i = 0; i < this.entity.values.length; i++) {
// this.sdk.viewer.entities.remove(this.entity.values[i])
// }
// this.entity.removeAll()
// this.entity = null
// }
// }
// export default ItineraryMove

136
src/Obj/Base/KML/index.js Normal file
View File

@ -0,0 +1,136 @@
/**
* @name: kml
* @author: Administrator
* @date: 2023-07-19 09:25
* @descriptionkml
* @update: 2023-07-19 09:25
*/
import Base from '../index'
import { setActiveViewer, closeRotateAround, closeViewFollow} from '../../../Global/global'
class KML extends Base {
constructor(sdk, options = {}) {
super(sdk, options)
this.source = new Cesium.CustomDataSource(this.options.id)
// this.source = new Cesium.CompositeEntityCollection([])
this.detail = []
// this.load()
}
get show() {
return this.options.show
}
set show(val) {
if (this.source) {
this.source.show = val
this.options.show = val
}
}
setDefaultValue() {
this.options.id = this.options.id || Cesium.createGuid()
this.options.url = this.options.url || ''
this.options.show = this.options.show ?? true
}
async flyTo(duration = 3) {
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)
this.sdk.viewer.camera.flyTo({
destination: destination,
orientation: orientation,
duration
})
}
else {
if (this.source) this.viewer.flyTo(this.source, { duration })
}
}
remove() {
super.remove()
this.viewer.dataSources.remove(this.source)
this.source = null
}
async on() {
this.show = this.options.show
let source = await Cesium.KmlDataSource.load(this.options.url, {
camera: this.viewer.scene.camera,
canvas: this.viewer.scene.canvas
// clampToGround: true
})
source.entities.values.forEach((entity, index) => {
this.detail.push({ name: entity.name, id: entity.id })
if (entity.label) {
let scale = 1
if (entity.billboard) {
scale = entity.billboard.scale._value
}
entity.label.pixelOffset = new Cesium.Cartesian2(0, -32 * scale - 15)
entity.label.horizontalOrigin = Cesium.HorizontalOrigin.CENTER
entity.label.disableDepthTestDistance = Number.POSITIVE_INFINITY
}
if (entity.polygon) {
//polygon需要重写不然无法贴地
let polygon = {
hierarchy: entity.polygon.hierarchy.getValue().positions,
material: entity.polygon.material,
classificationType: Cesium.ClassificationType.BOTH
}
//拆分边线,因为边线不能贴地,需要改为polyline但是有可能存在entity本身就有polyline所以需要单独创建一个entity
if (entity.polygon.outline.getValue()) {
let positions = entity.polygon.hierarchy.getValue().positions
let entity2 = new Cesium.Entity({
id: this.getOutlineId(entity.id),
polyline: {
positions,
width: entity.polygon.outlineWidth.getValue(),
material: entity.polygon.outlineColor.getValue(),
clampToGround: true,
zIndex: this.sdk._entityZIndex
}
})
this.source.entities.add(entity2)
}
entity.polygon = polygon
}
if (entity.billboard) {
entity.billboard.heightReference =
Cesium.HeightReference.CLAMP_TO_GROUND
}
if (entity.polyline) {
entity.polyline = {
positions: entity.polyline.positions.getValue(),
material: entity.polyline.material,
clampToGround: true,
width: entity.polyline.width ? entity.polyline.width.getValue() : 1
}
//这里在设置贴地的时候需要单独创建polyline部分kml的polyline设置贴地会导致引擎崩溃原因暂未查询到
}
entity.show = true
this.source.entities.add(entity)
})
await this.viewer.dataSources.add(this.source)
}
getOutlineId(id) {
return [id, 'outline'].join('_')
}
}
export default KML

View File

@ -0,0 +1,98 @@
// /**
// * @name: kml
// * @author: Administrator
// * @date: 2023-07-19 09:25
// * @descriptionkml
// * @update: 2023-07-19 09:25
// */
// class KML2 {
// constructor(options = {}) {
// this.options = {...options}
// this.viewer = YJ.getEarth().czm.viewer
// this.setDefaultValue()
// this.source = new Cesium.CustomDataSource(this.options.id)
// this.billboardsCollection = this.viewer.scene.primitives.add(new Cesium.BillboardCollection());
// this.labelCollection = this.viewer.scene.primitives.add(new Cesium.LabelCollection());
// // this.source = new Cesium.CompositeEntityCollection([])
// this.detail = []
// this.labelAttrs = ["show", "position", "text", "font", "fillColor"]
// this.load()
// }
// get show() {
// return this.options.show
// }
// set show(val) {
// if (this.source) {
// this.source.show = val
// this.options.show = val
// }
// }
// setDefaultValue() {
// this.options.id = this.options.id || Cesium.createGuid()
// this.options.url = this.options.url || ""
// this.options.show = this.options.show ?? true
// }
// flyTo(duration = 3) {
// if (this.source)
// this.viewer.flyTo(this.source, {duration})
// }
// remove() {
// this.viewer.dataSources.remove(this.source);
// this.source = null
// }
// async load() {
// this.show = this.options.show
// let source = await Cesium.KmlDataSource.load(this.options.url,
// {
// camera: this.viewer.scene.camera,
// canvas: this.viewer.scene.canvas,
// // clampToGround: true
// })
// let types = ["label", "billboard", "polyline", "polygon"]//kml暂时只考虑这几种
// source.entities.values.forEach((entity, index) => {
// if (entity.label) {
// this.dealLabel(entity)
// }
// if (entity.billboard) {
// this.addBillboard(entity)
// }
// })
// // await this.viewer.dataSources.add(this.source);
// }
// getOutlineId(id) {
// return [id, "outline"].join("_")
// }
// addBillboard(entity) {
// this.billboardsCollection.add({
// position: entity.position.getValue(),
// image: entity.billboard.image.getValue() //图片存储路径
// });
// }
// dealLabel(entity) {
// let config = {
// pixelOffset: new Cesium.Cartesian2(0, -32),
// position: entity.position.getValue(),
// }
// this.labelAttrs.forEach(key => {
// if (entity.label[key]) {
// config[key] = entity.label[key].getValue()
// }
// })
// this.labelCollection.add(config);
// }
// }
// export default KML2

View File

@ -0,0 +1,594 @@
/**
* 标注
*/
import Base from '../index'
import MouseEvent from '../../../Event/index'
import {
getGroundCover
} from '../../../Global/global'
import { getFontFamily } from '../../Element/fontSelect'
import {
addCluster,
remove_entity_from_cluster
} from '../../../Global/cluster/cluster'
class LabelObject extends Base {
#updateBillboardImageTimeout
#canvas = document.createElement('canvas')
#canvas2 = document.createElement('canvas')
constructor(sdk, options = {}, model) {
super(sdk, options)
this.model = model
this.options.near = options.near || options.near === 0 ? options.near : 2000
this.options.far = options.far || options.far === 0 ? options.far : 100000
this.options.scaleByDistance = options.scaleByDistance || false
this.options.show =
options.show || options.show === false ? options.show : true
this.options.text = options.text
let textArray = this.options.text.split('\n')
for (let i = 0; i < textArray.length; i++) {
if (textArray[i].length > 40) {
textArray[i] = textArray[i].slice(0, 40 - textArray[i].length)
}
}
if (textArray.length > 10) {
textArray.splice(10 - textArray.length)
}
this.options.text = textArray.join('\n')
this.options.fontFamily = options.fontFamily || 0
this.font = getFontFamily(this.options.fontFamily) || 'SimHei'
this.options.fontSize = options.fontSize || 20
this.options.lineWidth = options.lineWidth || 4
this.options.lineColor = options.lineColor || '#00ffff80'
this.options.color = options.color || '#ffffff'
this.options.ground =
options.ground || options.ground === false ? options.ground : true
this.options.pixelOffset =
options.pixelOffset || options.pixelOffset === 0
? options.pixelOffset
: 20
this.options.backgroundColor = options.backgroundColor || [
'#00ffff80',
'#00ffff80'
]
this.event = new MouseEvent(this.sdk)
this.entity
this.create(this.options.position)
this.picking = true
}
async create() {
let _this = this
if (!this.options.position[2] && this.options.position[2] !== 0) {
this.options.position[2] = await this.getClampToHeight({
lng: this.options.position[0],
lat: this.options.position[1]
})
}
this.originalOptions = copyObj(this.options)
let id = this.options.id + '-label'
let oldEntity = this.sdk.viewer.entities.getById(id)
if(oldEntity) {
this.sdk.viewer.entities.remove(oldEntity)
}
this.entity = this.sdk.viewer.entities.add({
show: this.options.show,
id: this.options.id + '-label',
position: new Cesium.CallbackProperty(function () {
if (_this.model) {
// return Cesium.Cartesian3.fromDegrees(_this.options.position[0], _this.options.position[1], _this.model.originalBoundingSphereRadius*2*_this.model.customScale.z + _this.options.position[2])
if (_this.model.isMove) {
let scale = _this.model.customScale.x
if (_this.model.customScale.y > scale) {
scale = _this.model.customScale.y
}
if (_this.model.customScale.z > scale) {
scale = _this.model.customScale.z
}
let point1 = Cesium.Cartesian3.fromDegrees(
_this.options.position[0],
_this.options.position[1],
_this.options.position[2] +
(_this.model.originalBoundingSphereRadius || 1) *
2 *
(scale || 0.01)
)
// 点2的位置也使用经纬高表示
let point2 = Cesium.Cartesian3.fromDegrees(
_this.options.position[0],
_this.options.position[1],
_this.options.position[2] -
(_this.model.originalBoundingSphereRadius || 1) *
2 *
(scale || 0.01)
)
let direction = Cesium.Cartesian3.subtract(
point2,
point1,
new Cesium.Cartesian3()
)
let c = Cesium.Cartesian3.normalize(direction, direction)
let ray = new Cesium.Ray(point1, c)
let pickedObjects = _this.viewer.scene.drillPickFromRay(ray, 5)
for (let i = 0; i < pickedObjects.length; i++) {
if (
pickedObjects[i].object &&
pickedObjects[i].object.id &&
pickedObjects[i].object.id === _this.model.id
) {
let pos84 = _this.cartesian3Towgs84(pickedObjects[i].position, _this.sdk.viewer)
_this.options.position[0] = pos84.lng
_this.options.position[1] = pos84.lat
_this.options.position[2] = pos84.alt
break
}
}
}
return Cesium.Cartesian3.fromDegrees(
_this.options.position[0],
_this.options.position[1],
_this.options.position[2]
)
} else {
return Cesium.Cartesian3.fromDegrees(..._this.options.position)
}
}, false),
billboard: {
image: this.getcanvas(),
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
disableDepthTestDistance: new Cesium.CallbackProperty(function () {
return getGroundCover() ? undefined : Number.POSITIVE_INFINITY
}, false),
scaleByDistance: this.options.scaleByDistance
? new Cesium.NearFarScalar(this.options.near, 1, this.options.far, 0)
: undefined,
pixelOffsetScaleByDistance: this.options.scaleByDistance
? new Cesium.NearFarScalar(this.options.near, 1, this.options.far, 0)
: undefined
}
// label: {
// show: this.options.show,
// text: new Cesium.CallbackProperty(function () {
// return _this.options.text
// }, false),
// font: this.options.fontSize + "px Helvetica",
// fillColor: Cesium.Color.fromCssColorString(this.options.color),
// pixelOffset: new Cesium.Cartesian2(0, -this.options.pixelOffset),
// outlineColor: Cesium.Color.BLACK,
// backgroundColor: Cesium.Color.fromCssColorString('#42c6ef'),
// backgroundPadding: new Cesium.Cartesian2(12, 12),
// showBackground: true,
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
// outlineWidth: 1,
// style: Cesium.LabelStyle.FILL_AND_OUTLINE,
// },
})
}
get position() {
return this.options.position
}
set position(v) {
// console.log(v)
this.options.position = v
if (!v[2] && v[2] !== 0) {
let objectsToExclude = [...this.sdk.viewer.entities.values]
this.getClampToHeight({
lng: v[0],
lat: v[1]
}, objectsToExclude).then(height => {
v[2] = height
this.options.position = [...v]
})
// let point1 = Cesium.Cartesian3.fromDegrees(this.options.position[0], this.options.position[1], 0);
// let point2 = Cesium.Cartesian3.fromDegrees(this.options.position[0], this.options.position[1], 10000000);
// let direction = Cesium.Cartesian3.subtract(point2, point1, new Cesium.Cartesian3());
// let c = Cesium.Cartesian3.normalize(direction, direction);
// let ray = new Cesium.Ray(point1, c);
// let r = {}
// let pickedObjects = this.sdk.viewer.scene.drillPickFromRay(ray);
// for (let i = 0; i < pickedObjects.length; i++) {
// if (pickedObjects[i].position) {
// r = pickedObjects[i]
// break
// }
// }
// if (r && r.position) {
// this.options.position[2] = this.cartesian3Towgs84(r.position, this.sdk.viewer).alt
// }
// else {
// try {
// let promise = Cesium.sampleTerrainMostDetailed(this.sdk.viewer.terrainProvider, [Cesium.Cartographic.fromDegrees(this.options.position[0], this.options.position[1])]);
// promise.then((p) => {
// this.options.position[2] = p[0].height
// }).catch((e)=>{
// })
// } catch (error) {
// }
// }
} else {
this.options.position = [...v]
}
}
get show() {
return this.options.show
}
set show(v) {
this.options.show = v
if (!this.entity) {
return
}
this.entity.show = v
if (this.model) {
// return Cesium.Cartesian3.fromDegrees(this.options.position[0], this.options.position[1], this.model.originalBoundingSphereRadius*2*this.model.customScale.z + this.options.position[2])
let scale = this.model.customScale.x
if (this.model.customScale.y > scale) {
scale = this.model.customScale.y
}
if (this.model.customScale.z > scale) {
scale = this.model.customScale.z
}
let point1 = Cesium.Cartesian3.fromDegrees(
this.options.position[0],
this.options.position[1],
this.options.position[2] +
(this.model.originalBoundingSphereRadius || 1) *
2 *
(scale || 0.01)
)
// 点2的位置也使用经纬高表示
let point2 = Cesium.Cartesian3.fromDegrees(
this.options.position[0],
this.options.position[1],
this.options.position[2] -
(this.model.originalBoundingSphereRadius || 1) *
2 *
(scale || 0.01)
)
let direction = Cesium.Cartesian3.subtract(
point2,
point1,
new Cesium.Cartesian3()
)
let c = Cesium.Cartesian3.normalize(direction, direction)
let ray = new Cesium.Ray(point1, c)
let pickedObjects = this.viewer.scene.drillPickFromRay(ray, 5)
for (let i = 0; i < pickedObjects.length; i++) {
if (
pickedObjects[i].object &&
pickedObjects[i].object.id &&
pickedObjects[i].object.id === this.model.id
) {
let pos84 = this.cartesian3Towgs84(pickedObjects[i].position, this.sdk.viewer)
this.options.position[0] = pos84.lng
this.options.position[1] = pos84.lat
this.options.position[2] = pos84.alt
break
}
}
}
else if (this.options.ground) {
let objectsToExclude = [...this.sdk.viewer.entities.values]
this.getClampToHeight({
lng: this.options.position[0],
lat: this.options.position[1]
}, objectsToExclude).then(height => {
this.options.position[2] = height
})
}
}
get text() {
return this.options.text
}
set text(v) {
this.options.text = v
let textArray = this.options.text.split('\n')
for (let i = 0; i < textArray.length; i++) {
if (textArray[i].length > 40) {
textArray[i] = textArray[i].slice(0, 40 - textArray[i].length)
}
}
if (textArray.length > 10) {
textArray.splice(10 - textArray.length)
}
this.options.text = textArray.join('\n')
this.entity && (this.updateBillboardImage())
}
get color() {
return this.options.color
}
set color(v) {
this.options.color = v
this.entity && (this.entity.billboard.image = this.getcanvas())
}
get scaleByDistance() {
return this.options.scaleByDistance
}
set scaleByDistance(v) {
this.options.scaleByDistance = v
if (!this.entity) {
return
}
if (this.options.scaleByDistance) {
this.entity.billboard.scaleByDistance = new Cesium.NearFarScalar(
this.options.near,
1,
this.options.far,
0
)
this.entity.billboard.pixelOffsetScaleByDistance = new Cesium.NearFarScalar(
this.options.near,
1,
this.options.far,
0
)
} else {
this.entity.billboard.scaleByDistance = undefined
this.entity.billboard.pixelOffsetScaleByDistance = undefined
}
}
get near() {
return this.options.near
}
set near(v) {
let near = v
if (near > this.far) {
near = this.far
}
this.options.near = near
if (!this.entity) {
return
}
if (this.options.scaleByDistance) {
this.entity.billboard.scaleByDistance = new Cesium.NearFarScalar(
this.options.near,
1,
this.options.far,
0
)
this.entity.billboard.pixelOffsetScaleByDistance = new Cesium.NearFarScalar(
this.options.near,
1,
this.options.far,
0
)
} else {
this.entity.billboard.scaleByDistance = undefined
this.entity.billboard.pixelOffsetScaleByDistance = undefined
}
}
get far() {
return this.options.far
}
set far(v) {
let far = v
if (far < this.near) {
far = this.near
}
this.options.far = far
if (!this.entity) {
return
}
if (this.options.scaleByDistance) {
this.entity.billboard.scaleByDistance = new Cesium.NearFarScalar(
this.options.near,
1,
this.options.far,
0
)
this.entity.billboard.pixelOffsetScaleByDistance = new Cesium.NearFarScalar(
this.options.near,
1,
this.options.far,
0
)
} else {
this.entity.billboard.scaleByDistance = undefined
this.entity.billboard.pixelOffsetScaleByDistance = undefined
}
}
get fontSize() {
return this.options.fontSize
}
set fontSize(v) {
this.options.fontSize = Number(v)
if (!this.entity) {
return
}
this.updateBillboardImage()
}
get fontFamily() {
return this.options.fontFamily
}
set fontFamily(v) {
this.options.fontFamily = v || 0
this.font = getFontFamily(this.options.fontFamily) || 'SimHei'
this.updateBillboardImage()
}
get lineWidth() {
return this.options.lineWidth
}
set lineWidth(v) {
this.options.lineWidth = ((Number(v) || Number(v) === 0) ? Number(v) : 4)
if (!this.entity) {
return
}
this.updateBillboardImage()
}
get pixelOffset() {
return this.options.pixelOffset
}
set pixelOffset(v) {
this.options.pixelOffset = Number(v)
if (!this.entity) {
return
}
this.updateBillboardImage()
}
updateBillboardImage() {
this.entity.billboard.image = this.getcanvas()
// clearTimeout(this.#updateBillboardImageTimeout)
// this.#updateBillboardImageTimeout = setTimeout(() => {
// clearTimeout(this.#updateBillboardImageTimeout)
// this.entity.billboard.image = this.getcanvas()
// }, 500)
}
get lineColor() {
return this.options.pixelOffset
}
set lineColor(v) {
this.options.lineColor = v || '#00ffff80'
if (!this.entity) {
return
}
this.entity.billboard.image = this.getcanvas()
}
get backgroundColor() {
return this.options.backgroundColor
}
set backgroundColor(v) {
this.options.backgroundColor = v
if (!this.entity) {
return
}
this.entity.billboard.image = this.getcanvas()
}
get ground() {
return this.options.ground
}
set ground(v) {
this.options.ground = v
}
// get backgroundColorStart() {
// return this.options.backgroundColor[0]
// }
// set backgroundColorStart(v) {
// this.options.backgroundColor[0] = v
// this.entity.billboard.image = this.getcanvas()
// }
// get backgroundColorEnd() {
// return this.options.backgroundColor[1]
// }
// set backgroundColorEnd(v) {
// this.options.backgroundColor[1] = v
// this.entity.billboard.image = this.getcanvas()
// }
getcanvas() {
const ctx = this.#canvas.getContext('2d')
ctx.clearRect(0, 0, this.#canvas.width, this.#canvas.height);
ctx.font = this.options.fontSize + 'px ' + this.font
let texts = this.options.text.split('\n')
let canvasWidth = 0
let canvasHeight = 0
for (let i = 0; i < texts.length; i++) {
const text = texts[i]
const width = ctx.measureText(text).width
if (width > canvasWidth) {
canvasWidth = width
}
canvasHeight += this.options.fontSize
}
canvasHeight = canvasHeight + 20 + (texts.length - 1) * 5
canvasWidth = canvasWidth + 30
if (canvasWidth < this.options.lineWidth) {
canvasWidth = this.options.lineWidth
}
this.#canvas.width = canvasWidth
this.#canvas.height = this.options.pixelOffset + canvasHeight
const linearGradient = ctx.createLinearGradient(
0,
0,
canvasWidth,
canvasHeight + 20
)
linearGradient.addColorStop(0, this.options.backgroundColor[0])
linearGradient.addColorStop(1, this.options.backgroundColor[1])
ctx.fillStyle = linearGradient
ctx.fillRect(0, 0, canvasWidth, canvasHeight)
ctx.fillStyle = this.options.color
ctx.font = this.options.fontSize + 'px ' + this.font
let maxWidth = 0
for (let i = 0; i < texts.length; i++) {
let width = ctx.measureText(texts[i]).width
if (maxWidth < width) {
maxWidth = width
}
}
maxWidth = maxWidth + 30
let centerDistance = (canvasWidth - maxWidth) / 2
for (let i = 0; i < texts.length; i++) {
const text = texts[i]
if (this.options.fontSize < 10) {
ctx.fillText(text, 15 + centerDistance, this.options.fontSize * (i + 1) + 10 + i * 5)
} else {
ctx.fillText(
text,
15 + centerDistance,
this.options.fontSize * (i + 1) +
(10 * 10) / this.options.fontSize +
i * 5
)
}
}
// 虚线
ctx.strokeStyle = this.options.lineColor
ctx.setLineDash([4, 4]) //设置虚线长度4间隔为4
ctx.lineWidth = this.options.lineWidth
ctx.beginPath()
ctx.moveTo(canvasWidth / 2, canvasHeight)
ctx.lineTo(canvasWidth / 2, canvasHeight + this.options.pixelOffset)
ctx.stroke()
ctx.closePath()
const ctx2 = this.#canvas2.getContext('2d')
this.#canvas2.width = this.#canvas.width + 10
this.#canvas2.height = this.#canvas.height + 10
ctx2.drawImage(this.#canvas, 5, 5);
// const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// ctx.putImageData(imageData, 40, 40);
return this.#canvas2.toDataURL("image/png")
}
remove() {
this.sdk.viewer.entities.remove(this.entity)
this.entity = null
}
flicker() { }
}
export default LabelObject
const copyObj = (obj = {}) => {
//变量先置空
let newobj = null
//判断是否需要继续进行递归
if (typeof obj == 'object' && obj !== null) {
newobj = obj instanceof Array ? [] : {} //进行下一层递归克隆
for (var i in obj) {
newobj[i] = copyObj(obj[i])
} //如果不是对象直接赋值
} else newobj = obj
return newobj
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,105 @@
function html() {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input name" type="text" @model="name">
</div>
<div class="col">
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" min="-180" max="180" @model="lng">
</div>
<div class="col">
<span class="label">海拔高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="-9999999" max="999999999" step="0.01" @model="alt">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-90" max="90" @model="lat">
</div>
<div class="col">
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="lable-left-line">
<span>缩放</span>
<div class="checkbox-box" style="display: flex;align-items: center;margin-left: 20px;">
<input type="checkbox" style="width: 14px;height: 14px;margin-top: 2px;margin-right: 5px;cursor: pointer;">
<span>是否等比例缩放</span>
</div>
</div>
</div>
<div class="row no-equal" style="display: none;">
<div class="row">
<div class="col">
<span class="label">x 轴</span>
<input class="scale-x" style="flex: 1;margin-right: 15px;" type="range" max="99" min="0.0001" step="0.01" @model="scaleX">
<div class="input-number input-number-unit-1" style="width: auto;">
<input class="scale-x" style="width: 100px;" type="number" title="" min="0" max="99" step="0.01" @model="scaleX">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">y 轴</span>
<input class="scale-y" style="flex: 1;margin-right: 15px;" type="range" max="99" min="0.0001" step="0.01" @model="scaleY">
<div class="input-number input-number-unit-1" style="width: auto;">
<input class="scale-y" style="width: 100px;" type="number" title="" min="0" max="99" step="0.01" @model="scaleY">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">z 轴</span>
<input class="scale-z" style="flex: 1;margin-right: 15px;" type="range" max="99" min="0.0001" step="0.01" @model="scaleZ">
<div class="input-number input-number-unit-1" style="width: auto;">
<input class="scale-z" style="width: 100px;" type="number" title="" min="0" max="99" step="0.01" @model="scaleZ">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<div class="row equal" style="display: none;">
<div class="row">
<div class="col">
<span class="label">等比例缩放</span>
<input class="scale-all" style="flex: 1;margin-right: 15px;" type="range" max="99" min="0.0001" step="0.01">
<div class="input-number input-number-unit-1" style="width: auto;">
<input class="scale-all" style="width: 100px;" type="number" title="" min="0" max="99" step="0.01">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,35 @@
class flvplayer {
constructor(dom, options) {
this.dom = dom
this.playerUrl = options.url
this.init()
}
init() {
this.flvPlayer = flvjs.createPlayer({
type: 'flv',
url: this.playerUrl,
isLive: true,
hasAudio: false,
hasVideo: true
},{
enableWorker: true,
enableStashBuffer: false,
stashInitialSize: 128
});
this.flvPlayer.attachMediaElement(this.dom);
this.flvPlayer.load();
// this.flvPlayer.play();
}
on(type, Events, cd) {
this.flvPlayer.on(flvjs[type][Events], cd)
}
destroy() {
this.flvPlayer.destroy()
this.flvPlayer = null
}
}
export default flvplayer

View File

@ -0,0 +1,700 @@
import { getHost, getToken } from "../../../on";
import tools from '../../../Tools'
import { html } from "./_element";
import Dialog from '../../Element/Dialog';
import EventBinding from '../../Element/Dialog/eventBinding';
import ControllerObject from '../../../Controller'
import { setActiveViewer, closeRotateAround, closeViewFollow} from '../../../Global/global'
export default class LoadObjModel extends tools {
constructor(sdk, options, _Dialog = {}) {
super()
// eslint-disable-next-line no-undef
this.sdk = sdk
this.viwer = sdk.viewer
this.options = { ...options }
this.options.host = options.host || getHost()
this.options.name = options.name || '未命名对象'
this.options.show = (options.show || options.show === false) ? options.show : true
if (typeof options.scale === 'number') {
this.options.scale = {}
this.options.scale.x = options.scale
this.options.scale.y = options.scale
this.options.scale.z = options.scale
}
else {
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.scale.z = (this.options.scale.z || this.options.scale.z === 0) ? this.options.scale.z : 1
}
this.primitive = null
this._loadEvent = void 0
this._loaded = false
this._elms = {};
this.Dialog = _Dialog
this._EventBinding = new EventBinding()
LoadObjModel.setDefaultValue(this)
this.requestResource()
this.ControllerObject = new ControllerObject(this.sdk, {
position: { ...this.options.position },
rotate: {
x: (360 + (this.options.roll % 360)) % 360,
y: (360 + (-this.options.pitch % 360)) % 360,
z: (360 + (-this.options.heading % 360)) % 360
},
})
this.ControllerObject.controllerCallBack = this.controllerCallBack
this.HeadingPitchRollCallBack = this.Dialog.HeadingPitchRollCallBack
// this.viwer.camera.moveEnd.addEventListener(() => {
// if (this.options.show && this.primitive && this.primitive.video && this.primitive.video.player && this.options.position) {
// const position1 = Cesium.Cartesian3.fromDegrees(this.options.position.lng, this.options.position.lat, this.options.position.alt);
// const position2 = this.viwer.camera.position
// const distance = Cesium.Cartesian3.distance(position1, position2);
// if (this.options.playDistance && distance > this.options.playDistance) {
// this.primitive.video.player.getVueInstance().pause()
// }
// else {
// this.primitive.video.player.getVueInstance().play()
// }
// }
// })
}
requestResource() {
this.addResource().then(r => { })
}
static setDefaultValue(that) {
that.options.id = that.options.id || that.randomString()
that.options.position = that.options.position
that.options.objUrl = that.options.objUrl || ''
that.options.videoUrl = that.options.videoUrl || ''
that.options.xmlURL = that.options.xmlURL || ''
that.options.heading = that.options.heading || 0
that.options.pitch = that.options.pitch || 0
that.options.roll = that.options.roll || 0
}
async addResource() {
let that = this
that.options.xmlURL = that.options.objUrl.replace('.obj', '.xml')
if (that.options.xmlURL !== '') {
const xml = await fetch(that.options.xmlURL)
if (xml.ok) {
const xmlString = await xml.text()
const parser = new DOMParser()
const xmlDoc = parser.parseFromString(xmlString, 'text/xml')
// console.log('xmlDocxmlDocxmlDoc', xmlDoc)
const position = xmlDoc
.getElementsByTagName('Position')[0]
.textContent.split(',')
// const bbox = xmlDoc.getElementsByTagName('bbox')[0]
const crs = xmlDoc.getElementsByTagName('Crs')[0].textContent
const result = that.convert(
[{ x: position[0], y: position[1], z: position[2] }],
crs,
'EPSG:4326'
)
that.options.position = that.options.position || { lng: result.points[0].x, lat: result.points[0].y, alt: result.points[0].z }
that.ControllerObject.position = that.options.position
const scene = that.viwer.scene
const origin = Cesium.Cartesian3.fromDegrees(
that.options.position.lng,
that.options.position.lat,
that.options.position.alt
)
const obj_modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(
origin,
new Cesium.HeadingPitchRoll(
Cesium.Math.toRadians(0.85),
Cesium.Math.toRadians(0),
Cesium.Math.toRadians(0)
)
)
let obj = await window.objLoader.Load(that.options.objUrl)
obj.show = that.options.show
obj.modelMatrix = obj_modelMatrix
obj.setFlvVideo(that.options.videoUrl)
scene.primitives.add(obj)
that.primitive = obj
that.controllerCallBack({
rotate: { x: that.options.roll, y: -that.options.pitch, z: -that.options.heading },
position: { ...that.options.position }
})
this.loaded = true
this._loaded = true
if (this._loadEvent) {
this._loadEvent()
}
}
} else {
// eslint-disable-next-line no-console
console.error('请填写xml路径')
return
}
if (that.options.objUrl === '') {
// eslint-disable-next-line no-console
console.error('请填写obj模型路径')
return
}
}
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 = { lng: 0, lat: 0 }
if (this.options.position) {
position = { ...this.options.position }
}
else if (this.options.positions) {
position = { ...this.options.positions[0] }
}
else if (this.options.center) {
position = { ...this.options.center }
}
else if (this.options.start) {
position = { ...this.options.start }
}
else {
if (this.options.hasOwnProperty('lng')) {
position.lng = this.options.lng
}
if (this.options.hasOwnProperty('lat')) {
position.lat = this.options.lat
}
if (this.options.hasOwnProperty('alt')) {
position.alt = this.options.alt
}
}
// 如果没有高度值,则获取紧贴高度计算
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 a = 100 * Math.tan(60)
let latitude = a / 111319.55
this.sdk.viewer.camera.flyTo({
destination: new Cesium.Cartesian3.fromDegrees(
this.options.position.lng,
this.options.position.lat - latitude,
this.options.position.alt + 100
),
orientation: options.orientation || {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-60.0),
roll: Cesium.Math.toRadians(0.0)
}
})
}
}
async edit(state = false) {
let equal = false
this.originalOptions = this.deepCopyObj(this.options)
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
this._DialogObject = await new Dialog(this.sdk, this.options, {
title: '编辑属性', left: '180px', top: '100px',
confirmCallBack: (options) => {
this.name = this.name.trim()
if (!this.name) {
this.name = '未命名对象'
}
this.originalOptions = this.deepCopyObj(this.options)
this._DialogObject.close()
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(this.originalOptions)
},
// resetCallBack: () => {
// this.name = this.originalOptions.name
// this.Dialog.resetCallBack && this.Dialog.resetCallBack()
// },
resetCallBack: () => {
this.reset()
this.Dialog.resetCallBack && this.Dialog.resetCallBack()
},
removeCallBack: () => {
this.Dialog.removeCallBack && this.Dialog.removeCallBack()
},
closeCallBack: () => {
this.reset()
this.positionEditing = false
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
},
rotateCallBack: () => {
if (this.rotationEditing) {
this.rotationEditing = false
}
else {
this.rotationEditing = true
}
},
translationalCallBack: () => {
if (this.positionEditing) {
this.positionEditing = false
}
else {
this.positionEditing = true
}
}
}, true)
let contentElm = document.createElement('div')
contentElm.style.width = '448px'
contentElm.innerHTML = html()
this._DialogObject.contentAppChild(contentElm)
let equalSwitchElm = this._DialogObject._element.content.getElementsByClassName('checkbox-box')[0].querySelector('input')
let equalBoxElm = this._DialogObject._element.content.getElementsByClassName('equal')[0]
let noEqualBoxElm = this._DialogObject._element.content.getElementsByClassName('no-equal')[0]
equalSwitchElm.checked = equal
equalSwitchElm.addEventListener('change', (e) => {
equal = e.target.checked
if (equal) {
equalBoxElm.style.display = 'flex'
noEqualBoxElm.style.display = 'none'
}
else {
equalBoxElm.style.display = 'none'
noEqualBoxElm.style.display = 'flex'
}
})
let equalElms = equalBoxElm.getElementsByTagName('input')
equalElms[0].value = this.scaleX
equalElms[1].value = this.scaleX
equalElms[0].addEventListener('input', (e) => {
this.scaleX = e.target.value
this.scaleY = e.target.value
this.scaleZ = e.target.value
})
equalElms[1].addEventListener('input', (e) => {
this.scaleX = e.target.value
this.scaleY = e.target.value
this.scaleZ = e.target.value
})
if (equal) {
equalBoxElm.style.display = 'flex'
noEqualBoxElm.style.display = 'none'
}
else {
equalBoxElm.style.display = 'none'
noEqualBoxElm.style.display = 'flex'
}
setTimeout(() => {
if (this._DialogObject._element.foot) {
let translationalElm = this._DialogObject._element.foot.getElementsByClassName('rotate')[0]
if (translationalElm) {
translationalElm.style.position = 'absolute'
translationalElm.style.left = '100px'
}
}
}, 0);
let all_elm = contentElm.getElementsByTagName("*")
for (let i = 0; i < all_elm.length; i++) {
all_elm[i].addEventListener('input', (e) => {
if (e.target.value === '0' && e.target.min === '0') {
switch (e.target.className) {
case 'scale-x':
this.scaleX = 0.0001
break;
case 'scale-y':
this.scaleY = 0.0001
break;
case 'scale-z':
this.scaleZ = 0.0001
case 'scale-all':
this.scaleX = 0.0001
this.scaleY = 0.0001
this.scaleZ = 0.0001
break;
case 3:
}
}
})
}
this._EventBinding.on(this, all_elm)
this._elms = this._EventBinding.element
this._elms.scaleX.push(equalElms[0], equalElms[1])
}
reset() {
this.ControllerObject.destroy()
this.options = this.deepCopyObj(this.originalOptions)
this.name = this.options.name
if (!this.primitive) {
return
}
let m = Cesium.Transforms.eastNorthUpToFixedFrame(
new Cesium.Cartesian3.fromDegrees(this.options.position.lng, this.options.position.lat, this.options.position.alt)
)
this.primitive.modelMatrix = m
// 旋转
this.primitive.modelMatrix = Cesium.Matrix4.multiplyByMatrix3(
this.primitive.modelMatrix,
Cesium.Matrix3.fromHeadingPitchRoll(
Cesium.HeadingPitchRoll.fromDegrees(this.options.heading, this.options.pitch, this.options.roll)
),
this.primitive.modelMatrix
)
// 缩放
let scaleX = this.options.scale.x
let scaleY = this.options.scale.y
let scaleZ = this.options.scale.z
if (scaleX === 0) {
scaleX = 0.00001
}
if (scaleY === 0) {
scaleY = 0.00001
}
if (scaleZ === 0) {
scaleZ = 0.00001
}
Cesium.Matrix4.multiplyByScale(this.primitive.modelMatrix, new Cesium.Cartesian3(scaleX, scaleY, scaleZ), this.primitive.modelMatrix)
}
remove() {
this.sdk.viewer.scene.primitives.remove(this.primitive)
this.primitive = null
if (this._DialogObject && !this._DialogObject.isDestroy) {
this._DialogObject.close()
this._DialogObject = null
}
}
set controllerCallBack(callback) {
this._controllerCallBack = callback
}
get controllerCallBack() {
return params => {
this.options.heading = -params.rotate.z
this.options.pitch = -params.rotate.y
this.options.roll = params.rotate.x
this.HeadingPitchRollCallBack && this.HeadingPitchRollCallBack(params)
let lng = Number(Number(params.position.lng).toFixed(8))
let lat = Number(Number(params.position.lat).toFixed(8))
let alt = Number(Number(params.position.alt).toFixed(2))
this.options.position = { lng, lat, alt }
// 平移
let m = Cesium.Transforms.eastNorthUpToFixedFrame(
new Cesium.Cartesian3.fromDegrees(params.position.lng, params.position.lat, params.position.alt)
)
this.primitive.modelMatrix = m
// 旋转
Cesium.Matrix4.multiplyByMatrix3(
this.primitive.modelMatrix,
Cesium.Matrix3.fromHeadingPitchRoll(
Cesium.HeadingPitchRoll.fromDegrees(-params.rotate.z, -params.rotate.y, params.rotate.x)
),
this.primitive.modelMatrix
)
// 缩放
let scaleX = this.options.scale.x
let scaleY = this.options.scale.y
let scaleZ = this.options.scale.z
if (scaleX === 0) {
scaleX = 0.00001
}
if (scaleY === 0) {
scaleY = 0.00001
}
if (scaleZ === 0) {
scaleZ = 0.00001
}
Cesium.Matrix4.multiplyByScale(this.primitive.modelMatrix, new Cesium.Cartesian3(scaleX, scaleY, scaleZ), this.primitive.modelMatrix)
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = this.options.position.lng
})
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = this.options.position.lat
})
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = this.options.position.alt
})
}
}
get name() {
return this.options.name
}
set name(v) {
this.options.name = v
this._elms.name && this._elms.name.forEach((item) => {
item.value = v
})
}
/**
* @desc 打开模型旋转功能
* @param status {boolean}
* @methodOf Source
* */
set rotationEditing(status) {
if (status) {
this.ControllerObject.editRtation()
} else {
this.ControllerObject.destroy()
}
}
get scaleX() {
return this.options.scale.x
}
set scaleX(v) {
this.options.scale.x = Number(Number(v).toFixed(4))
this.controllerCallBack(
{
position: { ...this.options.position },
rotate: {
x: (360 + (this.options.roll % 360)) % 360,
y: (360 + (-this.options.pitch % 360)) % 360,
z: (360 + (-this.options.heading % 360)) % 360
},
}
)
this._elms.scaleX && this._elms.scaleX.forEach((item) => {
item.value = this.options.scale.x
})
}
get scaleY() {
return this.options.scale.y
}
set scaleY(v) {
this.options.scale.y = Number(Number(v).toFixed(4))
this.controllerCallBack(
{
position: { ...this.options.position },
rotate: {
x: (360 + (this.options.roll % 360)) % 360,
y: (360 + (-this.options.pitch % 360)) % 360,
z: (360 + (-this.options.heading % 360)) % 360
},
}
)
this._elms.scaleY && this._elms.scaleY.forEach((item) => {
item.value = this.options.scale.y
})
}
get scaleZ() {
return this.options.scale.z
}
set scaleZ(v) {
this.options.scale.z = Number(Number(v).toFixed(4))
this.controllerCallBack(
{
position: { ...this.options.position },
rotate: {
x: (360 + (this.options.roll % 360)) % 360,
y: (360 + (-this.options.pitch % 360)) % 360,
z: (360 + (-this.options.heading % 360)) % 360
},
}
)
this._elms.scaleZ && this._elms.scaleZ.forEach((item) => {
item.value = this.options.scale.z
})
}
/**
* @desc 获取模型旋转状态
* @method rotationEditing
* @return boolean
* @methodOf Source
* */
get rotationEditing() {
if (this.ControllerObject.getActiveState() === 'rtation') {
return true
}
return false
}
/**@desc 打开平移模型功能
*
* @memberOf Source
*@param status {boolean}
*
* */
set positionEditing(status) {
if (!this.sdk || !this.sdk.viewer || !this.ControllerObject) {
return
}
if (status) {
this.ControllerObject.editTranslational()
} else {
this.ControllerObject.destroy()
}
}
get positionEditing() {
if (this.ControllerObject.getActiveState() === 'translational') {
return true
}
return false
}
get lng() {
return this.options.position.lng
}
set lng(v) {
this.options.position.lng = v
this.ControllerObject.position = {lng: this.options.position.lng, lat: this.options.position.lat, alt: this.options.position.alt}
this.controllerCallBack(
{
position: { ...this.options.position },
rotate: {
x: (360 + (this.options.roll % 360)) % 360,
y: (360 + (-this.options.pitch % 360)) % 360,
z: (360 + (-this.options.heading % 360)) % 360
},
}
)
}
get lat() {
return this.options.position.lat
}
set lat(v) {
this.options.position.lat = v
this.ControllerObject.position = {lng: this.options.position.lng, lat: this.options.position.lat, alt: this.options.position.alt}
this.controllerCallBack(
{
position: { ...this.options.position },
rotate: {
x: (360 + (this.options.roll % 360)) % 360,
y: (360 + (-this.options.pitch % 360)) % 360,
z: (360 + (-this.options.heading % 360)) % 360
},
}
)
}
get alt() {
return this.options.position.alt
}
set alt(v) {
this.options.position.alt = v
this.ControllerObject.position = {lng: this.options.position.lng, lat: this.options.position.lat, alt: this.options.position.alt}
this.controllerCallBack(
{
position: { ...this.options.position },
rotate: {
x: (360 + (this.options.roll % 360)) % 360,
y: (360 + (-this.options.pitch % 360)) % 360,
z: (360 + (-this.options.heading % 360)) % 360
},
}
)
}
get show() {
return this.options.show
}
set show(v) {
if (typeof v === "boolean") {
this.options.show = v
this.primitive.show = v
} else {
console.error("参数必须为boolean")
}
}
get playDistance() {
return this.options.playDistance
}
set playDistance(v) {
this.options.playDistance = v
// this._elms.playDistance && this._elms.playDistance.forEach((item) => {
// item.value = this.options.playDistance
// })
// if (this.options.show && this.primitive && this.primitive.video && this.primitive.video.player && this.options.position) {
// const position1 = Cesium.Cartesian3.fromDegrees(this.options.position.lng, this.options.position.lat, this.options.position.alt);
// const position2 = this.viwer.camera.position
// const distance = Cesium.Cartesian3.distance(position1, position2);
// if (this.options.playDistance && distance > this.options.playDistance) {
// this.primitive.video.player.getVueInstance().pause()
// }
// else {
// this.primitive.video.player.getVueInstance().play()
// }
// }
}
flicker() { }
load(callback) {
if (this._loaded) {
callback();
}
else {
this._loadEvent = callback
}
}
get customView() {
this.options.customView
}
// 设置视角
setCustomView(val) {
if (val) {
this.options.customView = val
}
else {
let camera = this.sdk.viewer.camera
this.options.customView = {
orientation: { heading: camera.heading, pitch: camera.pitch, roll: camera.roll },
position: { x: camera.position.x, y: camera.position.y, z: camera.position.z }
}
this.originalOptions && (this.originalOptions.customView = this.options.customView)
}
}
// 重置视角
resetCustomView() {
this.options.customView = undefined
}
}

View File

@ -0,0 +1,63 @@
class jessibucaPlayer {
constructor(dom, options) {
this.dom = dom
this.url = options.url
this.init()
}
init() {
this.player = new Jessibuca({
container: this.dom,
decoder:this.getSourceRootPath() + '/3rdparty/jessibuca/decoder.js',
timeout: 30,
heartTimeout: 30,
heartTimeoutReplay: false,
loadingTimeout: 30,
loadingTimeoutReplay: false,
wasmDecodeErrorReplay: false,
videoBuffer: 0.2, // 缓存时长
isResize: false,
text: "",
loadingText: "",
useMSE: false,
debug: true,
showBandwidth: false, // 显示网速
operateBtns: {
fullscreen: false,
screenshot: false,
play: false,
audio: false,
recorder: false
},
forceNoOffscreen: false,
isNotMute: false,
},);
this.player.play(this.url);
}
on(Events, cd) {
this.player.on(Events, cd)
}
destroy() {
this.player.destroy()
this.player = null
}
getSourceRootPath() {
let sdkName = 'YJEarth.min.js'
let scripts = document.querySelectorAll('script')
let prefix = ''
scripts.forEach((item) => {
if (item.src && item.src.indexOf(sdkName) > -1) {
let arr = item.src.split('/')
arr.pop()
prefix = arr.join('/')
}
})
return prefix
}
}
export default jessibucaPlayer

View File

@ -0,0 +1,50 @@
import Tools from "../../../Tools";
function _element() {
let tools = new Tools()
let elm = document.createElement('div');
elm.className = 'locate-current-bubble-box'
elm.innerHTML = `
<div style="display: flex;justify-content: space-between;margin: 6px;margin-top: 0;">
<div class="lng" style="display: flex;align-items: center;">
<i style="display: inline-block;width: 20px;height: 20px;flex: 0 0 20px;margin-right: 10px;background: url(${tools.getSourceRootPath() + '/img/bubble/lng.png'}) no-repeat 100% 100%;"></i>
<span style="white-space: nowrap;">经度:</span>
<span></span>
</div>
</div>
<div style="display: flex;justify-content: space-between;margin: 6px;margin-top: 0;">
<div class="lat" style="display: flex;align-items: center;">
<i style="display: inline-block;width: 20px;height: 20px;flex: 0 0 20px;margin-right: 10px;background: url(${tools.getSourceRootPath() + '/img/bubble/lat.png'}) no-repeat 100% 100%;"></i>
<span style="white-space: nowrap;">纬度:</span>
<span></span>
</div>
</div>
<div style="display: flex;justify-content: space-between;margin: 6px;margin-top: 0;">
<div class="height" style="display: flex;align-items: center;">
<i style="display: inline-block;width: 20px;height: 20px;flex: 0 0 20px;margin-right: 10px;background: url(${tools.getSourceRootPath() + '/img/bubble/h.png'}) no-repeat 100% 100%;"></i>
<span style="white-space: nowrap;">海拔:</span>
<span></span>
</div>
</div>
<div style="display: flex;justify-content: space-between;margin: 6px;margin-top: 0;">
<div class="satellite" style="display: flex;align-items: center;">
<i style="display: inline-block;width: 20px;height: 20px;flex: 0 0 20px;margin-right: 10px;background: url(${tools.getSourceRootPath() + '/img/bubble/satellite.png'}) no-repeat 100% 100%;"></i>
<span style="white-space: nowrap;">卫星:</span>
<span></span>
</div>
</div>
`
elm.style.position = 'absolute'
elm.style.background = `url(${tools.getSourceRootPath() + '/img/bubble/bubble.png'}) no-repeat 100% 100%`;
elm.style.backgroundSize = '100% 100%'
elm.style.width = '220px'
elm.style.height = '140px'
elm.style.color = '#ffffff'
elm.style.padding = '10px'
elm.style.boxSizing = 'border-box'
elm.style.fontSize = '14px'
elm.style.pointerEvents = 'none'
document.body.appendChild(elm)
return elm
}
export { _element }

View File

@ -0,0 +1,58 @@
import Tools from "../../../Tools";
function _element() {
let tools = new Tools()
let elm = document.createElement('div');
elm.className = 'locate-current-bubble-box'
elm.innerHTML = `
<div style="display: flex;justify-content: space-between;margin: 6px;margin-top: 0;">
<div class="lng" style="display: flex;align-items: center;width: 48%;">
<i style="display: inline-block;width: 20px;height: 20px;flex: 0 0 20px;margin-right: 10px;background: url(${tools.getSourceRootPath() + '/img/bubble/lng.png'}) no-repeat 100% 100%;"></i>
<span style="white-space: nowrap;">经度:</span>
<span></span>
</div>
<div class="ew" style="display: flex;align-items: center;width: 48%;">
<i style="display: inline-block;width: 20px;height: 20px;flex: 0 0 20px;margin-right: 10px;background: url(${tools.getSourceRootPath() + '/img/bubble/e.png'}) no-repeat 100% 100%;"></i>
<span style="white-space: nowrap;">东经:</span>
<span></span>
</div>
</div>
<div style="display: flex;justify-content: space-between;margin: 6px;margin-top: 0;">
<div class="lat" style="display: flex;align-items: center;width: 48%;">
<i style="display: inline-block;width: 20px;height: 20px;flex: 0 0 20px;margin-right: 10px;background: url(${tools.getSourceRootPath() + '/img/bubble/lat.png'}) no-repeat 100% 100%;"></i>
<span style="white-space: nowrap;">纬度:</span>
<span></span>
</div>
<div class="sn" style="display: flex;align-items: center;width: 48%;">
<i style="display: inline-block;width: 20px;height: 20px;flex: 0 0 20px;margin-right: 10px;background: url(${tools.getSourceRootPath() + '/img/bubble/s.png'}) no-repeat 100% 100%;"></i>
<span style="white-space: nowrap;">南纬:</span>
<span></span>
</div>
</div>
<div style="display: flex;justify-content: space-between;margin: 6px;margin-top: 0;">
<div class="height" style="display: flex;align-items: center;width: 48%;">
<i style="display: inline-block;width: 20px;height: 20px;flex: 0 0 20px;margin-right: 10px;background: url(${tools.getSourceRootPath() + '/img/bubble/h.png'}) no-repeat 100% 100%;"></i>
<span style="white-space: nowrap;">高程:</span>
<span></span>
</div>
<div class="satellite" style="display: flex;align-items: center;width: 48%;">
<i style="display: inline-block;width: 20px;height: 20px;flex: 0 0 20px;margin-right: 10px;background: url(${tools.getSourceRootPath() + '/img/bubble/satellite.png'}) no-repeat 100% 100%;"></i>
<span style="white-space: nowrap;">卫星:</span>
<span></span>
</div>
</div>
`
elm.style.position = 'absolute'
elm.style.background = `url(${tools.getSourceRootPath() + '/img/bubble/bubble.png'}) no-repeat 100% 100%`;
elm.style.backgroundSize = '100% 100%'
elm.style.width = '400px'
elm.style.height = '115px'
elm.style.color = '#ffffff'
elm.style.padding = '10px'
elm.style.boxSizing = 'border-box'
elm.style.fontSize = '14px'
elm.style.pointerEvents = 'none'
document.body.appendChild(elm)
return elm
}
export { _element }

View File

@ -0,0 +1,210 @@
import { getHost } from "../../../on";
import Tools from "../../../Tools";
import { getGroundCover } from '../../../Global/global'
import { setActiveViewer, closeRotateAround, closeViewFollow} from '../../../Global/global'
class LocateCurrent {
#canvas = null
#img = {
bgimg: null,
img1: null,
img2: null,
img3: null,
img4: null,
}
constructor(sdk, options = {}, callback) {
this.sdk = sdk
this.options = options
this.data = {}
this._webSocketCallback = callback
this._tools = new Tools(this.sdk)
this.requestResource()
}
requestResource() {
this.options.host = this.options.host || getHost()
let url = ""
url = this.options.host + '/yjearth4.0/api/v1/gps/state'
this.reconnecting = new ReconnectingWebSocket('ws://' + url, [], { maxReconnectAttempts: 8 })
this.reconnecting.onopen = (event) => {
this.reconnecting.onmessage = async (event) => {
this.data = JSON.parse(event.data)
if (this.data && this.data.rmc) {
let height = await this._tools.getClampToHeight(this.data.rmc)
this.position = new Cesium.Cartesian3.fromDegrees(this.data.rmc.lng, this.data.rmc.lat, height);
this.create()
}
this._webSocketCallback && this._webSocketCallback(this.data)
}
}
// let _this = this
// this.data = {
// rmc: {
// lng: 116.397428,
// lat: 39.90923,
// alt: 100
// }
// }
// this.position = new Cesium.Cartesian3.fromDegrees(this.data.rmc.lng, this.data.rmc.lat, 0);
// setInterval(() => {
// _this.create()
// console.log(1111)
// }, 50);
}
create() {
this.getcanvas()
if (this.data && this.data.rmc && !this.entity) {
this.entity = new Cesium.CustomDataSource();
this.sdk.viewer.dataSources.add(this.entity);
let point = new Cesium.Entity({
position: new Cesium.CallbackProperty(() => {
let c3 = this.position
return c3
}, false),
billboard: {
image: this._tools.getSourceRootPath() + '/img/locate2.png',
scale: 1,
disableDepthTestDistance: new Cesium.CallbackProperty(function () {
return getGroundCover() ? undefined : 100000000
}, false),
width: 31,
height: 36,
pixelOffset: new Cesium.Cartesian2(0, -15),
},
})
let lable = new Cesium.Entity({
position: new Cesium.CallbackProperty(() => {
let c3 = this.position
return c3
}, false),
billboard: {
image: new Cesium.CallbackProperty(() => {
return this.lableCanvas
}),
scale: 1,
disableDepthTestDistance: new Cesium.CallbackProperty(function () {
return getGroundCover() ? undefined : 100000000
}, false),
width: 220,
height: 140,
pixelOffset: new Cesium.Cartesian2(0, -110),
},
})
this.entity.entities.add(point)
this.entity.entities.add(lable)
}
}
loaded(cd) {
let data
Object.defineProperty(this, 'data', {
get() {
return data
},
set(value) {
data = value
if (cd) {
cd()
cd = undefined
}
}
})
}
getcanvas() {
const data = [
{
images: this._tools.getSourceRootPath() + '/img/bubble/lng.png',
text: '经度:' + parseFloat(this.data.rmc.lng.toFixed(10))
},
{
images: this._tools.getSourceRootPath() + '/img/bubble/lat.png',
text: '纬度:' + parseFloat(this.data.rmc.lat.toFixed(10))
},
{
images: this._tools.getSourceRootPath() + '/img/bubble/h.png',
text: '海拔:' + parseFloat(this.data.rmc.alt.toFixed(10))
},
{
images: this._tools.getSourceRootPath() + '/img/bubble/satellite.png',
text: '卫星:' + this.data.satellites || 0
}
]
if (this.#canvas) {
const ctx = this.#canvas.getContext('2d')
ctx.clearRect(0, 0, this.#canvas.width, this.#canvas.height);
ctx.drawImage(this.#img.bgimg, 0, 0, this.#canvas.width, this.#canvas.height);
let imagesLoaded = 0
data.forEach((item, index) => {
ctx.drawImage(this.#img['img' + (index + 1)], 12, 12 + (index * 26));
ctx.fillStyle = "#fff";
ctx.font = "16px Arial";
ctx.fillText(item.text, 44, 28 + (index * 26));
imagesLoaded++;
if (imagesLoaded === data.length) {
this.lableCanvas = this.#canvas.toDataURL()
}
})
}
else {
this.#canvas = document.createElement('canvas');
const ctx = this.#canvas.getContext('2d')
this.#canvas.width = 220
this.#canvas.height = 140
let img = new Image();
this.#img.bgimg = img
img.src = this._tools.getSourceRootPath() + '/img/bubble/bubble.png';
let imagesLoaded = 0
img.onload = () => {
ctx.drawImage(img, 0, 0, this.#canvas.width, this.#canvas.height);
data.forEach((item, index) => {
const img = new Image();
this.#img['img' + (index + 1)] = img
img.src = item.images;
img.onload = () => {
ctx.drawImage(img, 12, 12 + (index * 26));
ctx.fillStyle = "#fff";
ctx.font = "16px Arial";
ctx.fillText(item.text, 44, 28 + (index * 26));
imagesLoaded++;
if (imagesLoaded === data.length) {
this.lableCanvas = this.#canvas.toDataURL()
}
};
})
};
}
}
async flyTo(options = {}) {
if (this.data && this.data.rmc) {
let height = await this._tools.getClampToHeight(this.data.rmc)
setActiveViewer(0)
closeRotateAround(this.sdk)
closeViewFollow(this.sdk)
this.sdk.viewer.camera.flyTo({
orientation: options.orientation || {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
},
destination: Cesium.Cartesian3.fromDegrees(this.data.rmc.lng, this.data.rmc.lat, height + (options.height || 500)),
})
}
}
remove() {
this.#canvas = null
this.#img = {}
this.reconnecting && this.reconnecting.close()
this.sdk.viewer.dataSources.remove(this.entity)
this.entity = null
}
flicker() { }
}
export default LocateCurrent

View File

@ -0,0 +1,111 @@
function html() {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col">
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" min="-180" max="180" @model="lng">
</div>
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-90" max="90" @model="lat">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="-9999999" max="999999999" @model="alt">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<div class="row">
<div class="col">
<span class="label">起始颜色</span>
<div class="start_color"></div>
</div>
<div class="col" style="margin: 0;justify-content: flex-end;">
<span class="label">结束颜色</span>
<div class="end_color"></div>
</div>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<div class="row">
<span>最小初速度</span>
<input type="range" max="100" min="0" step="1" @model="minimumSpeed">
</div>
</div>
<div class="col">
<div class="row">
<span>最大初速度</span>
<input type="range" max="100" min="0" step="1" @model="maximumSpeed">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>最小存在时间</span>
<input type="range" max="100" min="0.01" step="0.1" @model="minimumParticleLife">
</div>
</div>
<div class="col">
<div class="row">
<span>最大存在时间</span>
<input type="range" max="100" min="0.01" step="0.1" @model="maximumParticleLife">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>起始比例</span>
<input type="range" max="10" min="0" step="0.1" @model="startScale">
</div>
</div>
<div class="col">
<div class="row">
<span>结束比例</span>
<input type="range" max="10" min="0" step="0.1" @model="endScale">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>发射速率(个/秒)</span>
<input type="range" max="100" min="0" step="1" @model="emissionRate">
</div>
</div>
<div class="col">
<div class="row">
<span>尺寸(像素)</span>
<input type="range" max="100" min="0" step="1" @model="particleSize">
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,92 @@
class eventBinding {
constructor() {
this.element = {}
}
static event = {}
getEvent(name) {
return eventBinding.event[name]
}
getEventAll() {
return eventBinding.event
}
setEvent(name, event) {
eventBinding.event[name] = event
}
on(that, elements) {
for (let i = 0; i < elements.length; i++) {
let Event = []
let isEvent = false
let removeName = []
if (!elements[i] ||!elements[i].attributes) {
continue
}
for (let m of elements[i].attributes) {
switch (m.name) {
case '@model': {
isEvent = true
if (elements[i].type == 'checkbox') {
Event.push((e) => { that[m.value] = e.target.checked })
elements[i].checked = that[m.value]
}
else {
Event.push((e) => {
let value = e.target.value
if(e.target.type == 'number' || e.target.type == 'range') {
value = Number(value)
}
that[m.value] = value
})
if(elements[i].nodeName=='IMG') {
elements[i].src = that[m.value]
}
else {
elements[i].value = that[m.value]
}
}
if(this.element[m.value]) {
this.element[m.value].push(elements[i])
}
else {
this.element[m.value] = [elements[i]]
}
removeName.push(m.name)
break;
}
case '@click': {
elements[i].addEventListener('click', (e) => {
if (typeof (that.Dialog[m.value]) === 'function') {
that.Dialog[m.value](e)
}
});
removeName.push(m.name)
// elements[i].attributes.removeNamedItem(m.name)
break;
}
}
// elements[i].attributes[m] = undefined
}
for(let n=0;n<removeName.length;n++) {
elements[i].attributes.removeNamedItem(removeName[n])
}
if (isEvent) {
let ventType = 'input'
if (elements[i].tagName != 'INPUT' || elements[i].type == 'checkbox') {
ventType = 'change'
}
elements[i].addEventListener(ventType, (e) => {
for (let t = 0; t < Event.length; t++) {
Event[t](e)
}
});
}
}
}
}
const EventBinding = new eventBinding();
export default EventBinding;

View File

@ -0,0 +1,743 @@
/**
* 火焰特效
*/
import Dialog from '../../../Element/Dialog';
import { html } from "./_element";
import EventBinding from './eventBinding'
import Base from "../../index";
import MouseEvent from '../../../../Event/index'
import { syncPrimitives } from '../../../../Global/MultiViewportMode'
import { syncData, getSdk as get2DSdk } from '../../../../Global/MultiViewportMode'
import MouseTip from '../../../../MouseTip'
import { setSplitDirection, syncSplitData, setActiveId } from '../../../../Global/SplitScreen'
import { setActiveViewer, closeRotateAround, closeViewFollow} from '../../../../Global/global'
class Flame extends Base {
/**
* @constructor
* @description 火焰特效
* @param sdk
* @param options {object} 粒子属性
* @param options.id {string} 标注id
* @param options.show=true {boolean} 显示/隐藏
* @param options.name {string} 名称
* @param options.url {string} 贴图地址
* @param options.startColor="#ff0000" {string} 起始颜色
* @param options.endColor="#fff000" {string} 结束颜色
* @param options.startScale=0.5 {number} 初始比例
* @param options.endScale=2 {number} 结束比例
* @param options.minimumSpeed=1 {number} 最小初速度
* @param options.maximumSpeed=30 {number} 最大初速度
* @param options.minimumParticleLife=1 {number} 最小存在时间(秒)
* @param options.maximumParticleLife=2 {number} 最大存在时间(秒)
* @param options.emissionRate=60 {number} 发射速率(个/每秒)
* @param options.particleSize=10 {number} 粒子尺大小
* @param options.lng 经度
* @param options.lat 纬度
* @param options.alt 高度
* @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} 高度
* */
constructor(sdk, options, _Dialog = {}) {
super(sdk, options);
this.options.url = options.url
this.options.startColor = options.startColor || "#ff0000"
this.options.endColor = options.endColor || "#fff000"
this.options.startScale = options.startScale || 0.5
this.options.endScale = options.endScale || 2
this.options.minimumParticleLife = options.minimumParticleLife || 1
this.options.maximumParticleLife = options.maximumParticleLife || 2
this.options.minimumSpeed = options.minimumSpeed || 1
this.options.maximumSpeed = options.maximumSpeed || 30
this.options.emissionRate = options.emissionRate || 60
this.options.particleSize = options.particleSize || 10
this.options.show = options.show === false ? false : true
this.positionCallBack = null
this.rotationCallback = null
this.onClickCallback = null
this._DialogObject = null
this._element = null
this.particleSystem
this.sdk.addIncetance(this.options.id, this)
this.add()
this.operate = {}
this._elms = {};
this.previous = {
positions: {
lng: this.options.lng,
lat: this.options.lat,
alt: this.options.alt,
}
}
this.Dialog = _Dialog
this.event = new MouseEvent(this.sdk)
}
get type() {
return "ParticleEffects"
}
get show() {
return this.options.show
}
set show(v) {
if (typeof v === "boolean") {
let sdkD = get2DSdk().sdkD
if (!this.isShowView || !sdkD) {
this.options.show = v
}
if (!this.showView || this.showView == 3 || !sdkD) {
if (this.entity && this.sdk.viewer.camera.positionCartographic.height < 10000000) {
this.entity.show = this.options.show
}
if (this.options.label && this.options.label.show) {
this.label.show = this.options.show
}
}
else {
if (this.entity && this.sdk.viewer.camera.positionCartographic.height < 10000000) {
this.entity.show = false
}
if (this.options.label && this.options.label.show) {
this.label.show = false
}
}
if (this._DialogObject && this._DialogObject.showBtn) {
this._DialogObject.showBtn.checked = v
}
syncData(this.sdk, this.options.id)
syncSplitData(this.sdk, this.options.id)
this.isShowView = false
} else {
console.error("参数必须为boolean")
}
}
async add() {
this.originalOptions = this.deepCopyObj(this.options)
const scene = this.sdk.viewer.scene;
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
let matrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
Cesium.Matrix4.multiplyByScale(matrix, new Cesium.Cartesian3(1, 1, 1), matrix)
let cameraHeight = this.sdk.viewer.camera.positionCartographic.height
this.particleSystem = scene.primitives.add(
new Cesium.ParticleSystem({
show: (cameraHeight >= 10000000) ? false : this.options.show,
image: this.options.url || (this.getSourceRootPath() + '/img/particlesystem/smoke.png'),
startColor: Cesium.Color.fromCssColorString(this.options.startColor), //粒子出生时的颜色
endColor: Cesium.Color.fromCssColorString(this.options.endColor), //当粒子死亡时的颜色
startScale: this.options.startScale, //粒子出生时的比例
endScale: this.options.endScale, //粒子在死亡时的比例
minimumParticleLife: this.options.minimumParticleLife, //设置粒子寿命的可能持续时间的最小界限(以秒为单位)
maximumParticleLife: this.options.maximumParticleLife, //设置粒子寿命的可能持续时间的最大界限(以秒为单位)
minimumSpeed: this.options.minimumSpeed,//设置以米/秒为单位的最小界限,超过该最小界限,随机选择粒子的实际速度。
maximumSpeed: this.options.maximumSpeed,//设置以米/秒为单位的最大界限,超过该最大界限,随机选择粒子的实际速度。
// imageSize: new Cesium.Cartesian2( //如果设置该属性,将会覆盖 minimumImageSize和maximumImageSize属性以像素为单位缩放image的大小
// this.options.imageSize || 10,
// this.options.imageSize || 10
// ),
minimumImageSize: new Cesium.Cartesian2(
this.options.particleSize,
this.options.particleSize
),
maximumImageSize: new Cesium.Cartesian2(
this.options.particleSize,
this.options.particleSize
),
sizeInMeters: true,
emissionRate: this.options.emissionRate, //每秒发射的粒子数。
lifetime: 0.5,
loop: true,
emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(30.0)),
modelMatrix: matrix,
updateCallback: (r) => {
r._billboard.id = this.options.id
}
})
);
// this.entity.modelMatrix
this.particleSystem.id = this.options.id
this.entity = this.particleSystem
// this.entity.modelMatrix = Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(100.0, 20.0)), new Cesium.Cartesian3(0.0, 0.0, 10000.0), new Cesium.Matrix4())
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
// this.editObj = new EditParticle(this.sdk, this.entity)
syncData(this.sdk, this.options.id)
if(this.options.show) {
setSplitDirection(0, this.options.id)
}
// 监听相机高度
this.sdk.viewer.camera.changed.addEventListener(() => {
if (this.entity && this.show) {
let cameraHeight = this.sdk.viewer.camera.positionCartographic.height;
if (cameraHeight >= 10000000) {
this.entity.show = false
}
else {
this.entity.show = true
}
}
});
}
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 = { lng: 0, lat: 0 }
if (this.options.position) {
position = { ...this.options.position }
}
else if (this.options.positions) {
position = { ...this.options.positions[0] }
}
else if (this.options.center) {
position = { ...this.options.center }
}
else {
if (this.options.hasOwnProperty('lng')) {
position.lng = this.options.lng
}
if (this.options.hasOwnProperty('lat')) {
position.lat = this.options.lat
}
if (this.options.hasOwnProperty('alt')) {
position.alt = this.options.alt
}
}
// 如果没有高度值,则获取紧贴高度计算
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 {
this.sdk.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(this.options.lng, this.options.lat, this.options.alt + 500),
orientation: options.orientation || {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
}
})
}
}
get startColor() {
return this.options.startColor
}
set startColor(v) {
this.options.startColor = v
this.particleSystem.startColor = Cesium.Color.fromCssColorString(v)
if (this._elms.startColor) {
this._elms.startColor.forEach((item, i) => {
let picker = new YJColorPicker({
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: v,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (c) => {
this.startColor = c
},//点击确认按钮事件回调
clear: () => {
this.startColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
this._elms.startColor[i] = picker
})
}
}
get endColor() {
return this.options.endColor
}
set endColor(v) {
this.options.endColor = v
this.particleSystem.endColor = Cesium.Color.fromCssColorString(v)
if (this._elms.endColor) {
this._elms.endColor.forEach((item, i) => {
let picker = new YJColorPicker({
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: v,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (c) => {
this.endColor = c
},//点击确认按钮事件回调
clear: () => {
this.endColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
this._elms.endColor[i] = picker
})
}
}
get minimumSpeed() {
return this.options.minimumSpeed
}
set minimumSpeed(v) {
this.options.minimumSpeed = v
this.particleSystem.minimumSpeed = v
this._elms.minimumSpeed && this._elms.minimumSpeed.forEach((item) => {
item.value = v
})
}
get maximumSpeed() {
return this.options.maximumSpeed
}
set maximumSpeed(v) {
this.options.maximumSpeed = v
this.particleSystem.maximumSpeed = v
this._elms.maximumSpeed && this._elms.maximumSpeed.forEach((item) => {
item.value = v
})
}
get minimumParticleLife() {
return this.options.minimumParticleLife
}
set minimumParticleLife(v) {
this.options.minimumParticleLife = v
this.particleSystem.minimumParticleLife = v
this._elms.minimumParticleLife && this._elms.minimumParticleLife.forEach((item) => {
item.value = v
})
}
get maximumParticleLife() {
return this.options.maximumParticleLife
}
set maximumParticleLife(v) {
this.options.maximumParticleLife = v
this.particleSystem.maximumParticleLife = v
this._elms.maximumParticleLife && this._elms.maximumParticleLife.forEach((item) => {
item.value = v
})
}
get startScale() {
return this.options.startScale
}
set startScale(v) {
this.options.startScale = v
this.particleSystem.startScale = v
this._elms.startScale && this._elms.startScale.forEach((item) => {
item.value = v
})
}
get endScale() {
return this.options.endScale
}
set endScale(v) {
this.options.endScale = v
this.particleSystem.endScale = v
this._elms.endScale && this._elms.endScale.forEach((item) => {
item.value = v
})
}
get emissionRate() {
return this.options.emissionRate
}
set emissionRate(v) {
this.options.emissionRate = v
this.particleSystem.emissionRate = v
this._elms.emissionRate && this._elms.emissionRate.forEach((item) => {
item.value = v
})
}
get particleSize() {
return this.options.particleSize
}
set particleSize(v) {
this.options.particleSize = v
this.particleSystem.minimumImageSize = new Cesium.Cartesian2(v, v)
this.particleSystem.maximumImageSize = new Cesium.Cartesian2(v, v)
this._elms.particleSize && this._elms.particleSize.forEach((item) => {
item.value = v
})
}
get lng() {
return this.options.lng
}
set lng(v) {
this.options.lng = v
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = v
})
}
get lat() {
return this.options.lat
}
set lat(v) {
this.options.lat = v
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = v
})
}
get alt() {
return this.options.alt
}
set alt(v) {
this.options.alt = v
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = v
})
}
/**
* @description 编辑框
* @param state=false {boolean} 状态: true打开, false关闭
*/
async edit(state = false) {
let _this = this
this.originalOptions = this.deepCopyObj(this.options)
// let elms = this.sdk.viewer._container.getElementsByClassName('YJ-custom-base-dialog')
// for (let i = elms.length - 1; i >= 0; i--) {
// this.sdk.viewer._container.removeChild(elms[i])
// }
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.originalOptions = this.deepCopyObj(this.options)
this._DialogObject.close()
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(this.originalOptions)
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.reset()
// this.entity.style = new Cesium.Cesium3DTileStyle({
// color: "color('rgba(255,255,255," + this.newData.transparency + ")')",
// show: true,
// });
this.positionEditing = false
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
},
showCallBack: (show) => {
this.show = show
this.Dialog.showCallBack && this.Dialog.showCallBack()
},
translationalCallBack: () => {
this.positionEditing = !this.positionEditing
}
}, true)
this._DialogObject._element.body.className = this._DialogObject._element.body.className + ' particle-effects'
let contentElm = document.createElement('div');
contentElm.innerHTML = html()
this._DialogObject.contentAppChild(contentElm)
// 颜色组件
let startColorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("start_color")[0],
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.startColor,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.startColor = color
},//点击确认按钮事件回调
clear: () => {
this.startColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
let endColorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("end_color")[0],
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.endColor,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.endColor = color
},//点击确认按钮事件回调
clear: () => {
this.endColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
let all_elm = contentElm.getElementsByTagName("*")
EventBinding.on(this, all_elm)
this._elms = EventBinding.element
this._elms.startColor = [startColorPicker]
this._elms.endColor = [endColorPicker]
} 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
// }
}
}
reset() {
if (!this.entity) {
return
}
this.name = this.originalOptions.name
this.startColor = this.originalOptions.startColor
this.endColor = this.originalOptions.endColor
this.minimumSpeed = this.originalOptions.minimumSpeed
this.maximumSpeed = this.originalOptions.maximumSpeed
this.minimumParticleLife = this.originalOptions.minimumParticleLife
this.maximumParticleLife = this.originalOptions.maximumParticleLife
this.startScale = this.originalOptions.startScale
this.endScale = this.originalOptions.endScale
this.emissionRate = this.originalOptions.emissionRate
this.particleSize = this.originalOptions.particleSize
this.lng = this.originalOptions.lng
this.lat = this.originalOptions.lat
this.alt = this.originalOptions.alt
syncPrimitives(this.entity)
}
async remove() {
super.remove()
this.sdk.viewer.scene.primitives.remove(this.entity);
this.entity = null
if (this._DialogObject && !this._DialogObject.isDestroy) {
this._DialogObject.close()
this._DialogObject = null
}
this.tip && this.tip.destroy()
this.event && this.event.destroy()
await this.sdk.removeIncetance(this.options.id)
await syncData(this.sdk, this.options.id)
}
/**@desc 打开平移功能
*
* @memberOf Source
* @param status {boolean}
*
* */
set positionEditing(status) {
if (!this.sdk || !this.sdk.viewer || !this.entity) {
return
}
this.operate.positionEditing = status
if (status === true) {
this.tip && this.tip.destroy()
this.tip = new MouseTip('点击鼠标左键确认,右键取消', this.sdk)
this.picking = false
this.previous = {
positions: { ...this.entity.position }
}
let movPos
this.event.mouse_move((movement, cartesian) => {
movPos = movement.endPosition
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.options.lng = positions.lng
this.options.lat = positions.lat
this.options.alt = positions.alt
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = this.options.lng
})
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = this.options.lat
})
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = this.options.alt
})
this.tip.setPosition(
cartesian,
movement.endPosition.x,
movement.endPosition.y
)
})
this.event.mouse_left((movement, cartesian) => {
if (!movPos || movPos.x !== movement.position.x || movPos.y !== movement.position.y-2) {
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.options.lng = positions.lng
this.options.lat = positions.lat
this.options.alt = positions.alt
}
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this.previous = {
positions: { ...this.entity.position }
}
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
this.event.gesture_pinck_start(() => { })
this.event.gesture_pinck_end(() => { })
this.positionEditing = false
})
this.event.mouse_right((movement, cartesian) => {
this.options.lng = this.entity.position.lng
this.options.lat = this.entity.position.lat
this.options.alt = this.entity.position.alt
this.positionEditing = false
})
this.event.gesture_pinck_start((movement, cartesian) => {
let startTime = new Date()
this.event.gesture_pinck_end(() => {
let endTime = new Date()
if (endTime - startTime >= 500) {
// 长按取消
this.options.lng = this.entity.position.lng
this.options.lat = this.entity.position.lat
this.options.alt = this.entity.position.alt
this.positionEditing = false
}
else {
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.options.lng = positions.lng
this.options.lat = positions.lat
this.options.alt = positions.alt
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this.previous = {
positions: { ...this.entity.position }
}
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
this.event.gesture_pinck_start(() => { })
this.event.gesture_pinck_end(() => { })
this.positionEditing = false
}
})
})
}
else {
this.picking = true
if (this.event) {
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
}
this.tip && this.tip.destroy()
if(!this.sdk || !this.sdk.viewer || !this.entity) {
return
}
this.options.lng = this.entity.position.lng
this.options.lat = this.entity.position.lat
this.options.alt = this.entity.position.alt
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = this.options.lng
})
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = this.options.lat
})
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = this.options.alt
})
}
}
get positionEditing() {
return this.operate.positionEditing
}
flicker() { }
}
export default Flame

View File

@ -0,0 +1,111 @@
function html() {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col">
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" min="-180" max="180" @model="lng">
</div>
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-90" max="90" @model="lat">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="-9999999" max="999999999" @model="alt">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<div class="row">
<div class="col">
<span class="label">起始颜色</span>
<div class="start_color"></div>
</div>
<div class="col" style="margin: 0;justify-content: flex-end;">
<span class="label">结束颜色</span>
<div class="end_color"></div>
</div>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<div class="row">
<span>最小初速度</span>
<input type="range" max="100" min="0" step="1" @model="minimumSpeed">
</div>
</div>
<div class="col">
<div class="row">
<span>最大初速度</span>
<input type="range" max="100" min="0" step="1" @model="maximumSpeed">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>最小存在时间</span>
<input type="range" max="100" min="0.01" step="0.1" @model="minimumParticleLife">
</div>
</div>
<div class="col">
<div class="row">
<span>最大存在时间</span>
<input type="range" max="100" min="0.01" step="0.1" @model="maximumParticleLife">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>起始比例</span>
<input type="range" max="10" min="0" step="0.1" @model="startScale">
</div>
</div>
<div class="col">
<div class="row">
<span>结束比例</span>
<input type="range" max="10" min="0" step="0.1" @model="endScale">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>发射速率(个/秒)</span>
<input type="range" max="100" min="0" step="1" @model="emissionRate">
</div>
</div>
<div class="col">
<div class="row">
<span>尺寸(像素)</span>
<input type="range" max="100" min="0" step="1" @model="particleSize">
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,92 @@
class eventBinding {
constructor() {
this.element = {}
}
static event = {}
getEvent(name) {
return eventBinding.event[name]
}
getEventAll() {
return eventBinding.event
}
setEvent(name, event) {
eventBinding.event[name] = event
}
on(that, elements) {
for (let i = 0; i < elements.length; i++) {
let Event = []
let isEvent = false
let removeName = []
if (!elements[i] ||!elements[i].attributes) {
continue
}
for (let m of elements[i].attributes) {
switch (m.name) {
case '@model': {
isEvent = true
if (elements[i].type == 'checkbox') {
Event.push((e) => { that[m.value] = e.target.checked })
elements[i].checked = that[m.value]
}
else {
Event.push((e) => {
let value = e.target.value
if(e.target.type == 'number' || e.target.type == 'range') {
value = Number(value)
}
that[m.value] = value
})
if(elements[i].nodeName=='IMG') {
elements[i].src = that[m.value]
}
else {
elements[i].value = that[m.value]
}
}
if(this.element[m.value]) {
this.element[m.value].push(elements[i])
}
else {
this.element[m.value] = [elements[i]]
}
removeName.push(m.name)
break;
}
case '@click': {
elements[i].addEventListener('click', (e) => {
if (typeof (that.Dialog[m.value]) === 'function') {
that.Dialog[m.value](e)
}
});
removeName.push(m.name)
// elements[i].attributes.removeNamedItem(m.name)
break;
}
}
// elements[i].attributes[m] = undefined
}
for(let n=0;n<removeName.length;n++) {
elements[i].attributes.removeNamedItem(removeName[n])
}
if (isEvent) {
let ventType = 'input'
if (elements[i].tagName != 'INPUT' || elements[i].type == 'checkbox') {
ventType = 'change'
}
elements[i].addEventListener(ventType, (e) => {
for (let t = 0; t < Event.length; t++) {
Event[t](e)
}
});
}
}
}
}
const EventBinding = new eventBinding();
export default EventBinding;

View File

@ -0,0 +1,765 @@
/**
* 喷泉特效
*/
import Dialog from '../../../Element/Dialog';
import { html } from "./_element";
import EventBinding from './eventBinding'
import Base from "../../index";
import MouseEvent from '../../../../Event/index'
import { syncData, getSdk as get2DSdk } from '../../../../Global/MultiViewportMode'
import MouseTip from '../../../../MouseTip'
import { setSplitDirection, syncSplitData, setActiveId } from '../../../../Global/SplitScreen'
import { setActiveViewer, closeRotateAround, closeViewFollow} from '../../../../Global/global'
class Fountain extends Base {
/**
* @constructor
* @description 喷泉特效
* @param sdk
* @param options {object} 粒子属性
* @param options.id {string} 标注id
* @param options.show=true {boolean} 显示/隐藏
* @param options.name {string} 名称
* @param options.url {string} 贴图地址
* @param options.startColor="#c1f7f24d" {string} 起始颜色
* @param options.endColor="#ffffff00" {string} 结束颜色
* @param options.startScale=1 {number} 初始比例
* @param options.endScale=20 {number} 结束比例
* @param options.minimumSpeed=9 {number} 最小初速度
* @param options.maximumSpeed=9.5 {number} 最大初速度
* @param options.minimumParticleLife=6 {number} 最小存在时间(秒)
* @param options.maximumParticleLife=7 {number} 最大存在时间(秒)
* @param options.emissionRate=20 {number} 发射速率(个/每秒)
* @param options.particleSize=0.5{number} 粒子尺大小
* @param options.lng 经度
* @param options.lat 纬度
* @param options.alt 高度
* @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} 高度
* */
constructor(sdk, options, _Dialog = {}) {
super(sdk, options);
this.options.url = options.url
this.options.startColor = options.startColor || "#c1f7f24d"
this.options.endColor = options.endColor || "#ffffff00"
this.options.startScale = options.startScale || 1
this.options.endScale = options.endScale || 20
this.options.minimumParticleLife = options.minimumParticleLife || 6
this.options.maximumParticleLife = options.maximumParticleLife || 7
this.options.minimumSpeed = options.minimumSpeed || 9
this.options.maximumSpeed = options.maximumSpeed || 9.5
this.options.emissionRate = options.emissionRate || 20
this.options.particleSize = options.particleSize || 0.5
// this.options.gravity = (options.gravity || options.gravity === 0) ? options.gravity : -3.5
this.options.show = options.show === false ? false : true
this._elms = {};
this.positionCallBack = null
this.rotationCallback = null
this.onClickCallback = null
this._DialogObject = null
this._element = null
this.particleSystem
this.sdk.addIncetance(this.options.id, this)
this.add()
this.operate = {}
this.previous = {
positions: {
lng: this.options.lng,
lat: this.options.lat,
alt: this.options.alt,
}
}
this.Dialog = _Dialog
this.event = new MouseEvent(this.sdk)
}
get type() {
return "ParticleEffects"
}
get show() {
return this.options.show
}
set show(v) {
if (typeof v === "boolean") {
let sdkD = get2DSdk().sdkD
if (!this.isShowView || !sdkD) {
this.options.show = v
}
if (!this.showView || this.showView == 3 || !sdkD) {
if (this.entity && this.sdk.viewer.camera.positionCartographic.height < 10000000) {
this.entity.show = this.options.show
}
if (this.options.label && this.options.label.show) {
this.label.show = this.options.show
}
}
else {
if (this.entity && this.sdk.viewer.camera.positionCartographic.height < 10000000) {
this.entity.show = false
}
if (this.options.label && this.options.label.show) {
this.label.show = false
}
}
if(this._DialogObject && this._DialogObject.showBtn) {
this._DialogObject.showBtn.checked = v
}
syncData(this.sdk, this.options.id)
syncSplitData(this.sdk, this.options.id)
this.isShowView = false
} else {
console.error("参数必须为boolean")
}
}
async add() {
let _this = this
this.originalOptions = this.deepCopyObj(this.options)
const scene = this.sdk.viewer.scene;
let gravityScratch = new Cesium.Cartesian3();
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
let matrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
Cesium.Matrix4.multiplyByScale(matrix, new Cesium.Cartesian3(1, 1, 1), matrix)
let cameraHeight = this.sdk.viewer.camera.positionCartographic.height
this.particleSystem = scene.primitives.add(
new Cesium.ParticleSystem({
show: (cameraHeight >= 10000000) ? false : this.options.show,
image: this.options.url || (this.getSourceRootPath() + '/img/particlesystem/fountain.png'),
// 从绿色到白色淡出
startColor: Cesium.Color.fromCssColorString(this.options.startColor), //粒子出生时的颜色
endColor: Cesium.Color.fromCssColorString(this.options.endColor), //当粒子死亡时的颜色
startScale: this.options.startScale, //粒子出生时的比例
endScale: this.options.endScale, //粒子在死亡时的比例
minimumParticleLife: this.options.minimumParticleLife, //设置粒子寿命的可能持续时间的最小界限(以秒为单位)
maximumParticleLife: this.options.maximumParticleLife, //设置粒子寿命的可能持续时间的最大界限(以秒为单位)
minimumSpeed: this.options.minimumSpeed,//设置以米/秒为单位的最小界限,超过该最小界限,随机选择粒子的实际速度。
maximumSpeed: this.options.maximumSpeed,//设置以米/秒为单位的最大界限,超过该最大界限,随机选择粒子的实际速度。
// imageSize: new Cesium.Cartesian2( //如果设置该属性,将会覆盖 minimumImageSize和maximumImageSize属性以像素为单位缩放image的大小
// this.options.imageSize || 10,
// this.options.imageSize || 10
// ),
lifetime: 0.5,
imageSize: new Cesium.Cartesian2(this.options.particleSize, this.options.particleSize * 2),
sizeInMeters: true,
emissionRate: this.options.emissionRate, //每秒发射的粒子数。
loop: true,
emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(0.2)),
modelMatrix: matrix,
emitterModelMatrix: computeEmitterodelMatrix(),// 发射器转换为世界坐标
// 增加重力场影像,
updateCallback: applyGravity,
})
);
let gravityVector = new Cesium.Cartesian3();
let gravity = -3.5;// !!!重力方向向上向下 -(9.8*9.8)
function applyGravity(p, dt) {
p._billboard.id = _this.options.id
let position = p.position;
Cesium.Cartesian3.normalize(position, gravityVector);
Cesium.Cartesian3.multiplyByScalar(gravityVector, gravity * dt, gravityVector);
p.velocity = Cesium.Cartesian3.add(p.velocity, gravityVector, p.velocity);
}
// 计算粒子发射器的位置姿态
function computeEmitterodelMatrix() {
let hpr = Cesium.HeadingPitchRoll.fromDegrees(0, 0, 0);//!!!发射粒子的方向
let trs = new Cesium.TranslationRotationScale();
trs.translation = Cesium.Cartesian3.fromElements(0, 0, 0);
trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr);
let Matrix4 = Cesium.Matrix4.fromTranslationRotationScale(trs);
return Matrix4
}
function computeModelMatrix(position) {
let center = Cesium.Cartesian3.fromDegrees(120.40100613624982, 36.09030781, -5)
let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center);
return modelMatrix;
}
// this.entity.modelMatrix
this.particleSystem.id = this.options.id
this.entity = this.particleSystem
// this.entity.modelMatrix = Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(100.0, 20.0)), new Cesium.Cartesian3(0.0, 0.0, 10000.0), new Cesium.Matrix4())
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
// this.editObj = new EditParticle(this.sdk, this.entity)
syncData(this.sdk, this.options.id)
if(this.options.show) {
setSplitDirection(0, this.options.id)
}
// 监听相机高度
this.sdk.viewer.camera.changed.addEventListener(() => {
if (this.entity && this.show) {
let cameraHeight = this.sdk.viewer.camera.positionCartographic.height;
if (cameraHeight >= 10000000) {
this.entity.show = false
}
else {
this.entity.show = true
}
}
});
}
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 = { lng: 0, lat: 0 }
if (this.options.position) {
position = { ...this.options.position }
}
else if (this.options.positions) {
position = { ...this.options.positions[0] }
}
else if (this.options.center) {
position = { ...this.options.center }
}
else {
if (this.options.hasOwnProperty('lng')) {
position.lng = this.options.lng
}
if (this.options.hasOwnProperty('lat')) {
position.lat = this.options.lat
}
if (this.options.hasOwnProperty('alt')) {
position.alt = this.options.alt
}
}
// 如果没有高度值,则获取紧贴高度计算
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 {
this.sdk.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(this.options.lng, this.options.lat, this.options.alt + 500),
orientation: options.orientation || {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
}
})
}
}
get startColor() {
return this.options.startColor
}
set startColor(v) {
this.options.startColor = v
this.particleSystem.startColor = Cesium.Color.fromCssColorString(v)
if (this._elms.startColor) {
this._elms.startColor.forEach((item, i) => {
let picker = new YJColorPicker({
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: v,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (c) => {
this.startColor = c
},//点击确认按钮事件回调
clear: () => {
this.startColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
this._elms.startColor[i] = picker
})
}
}
get endColor() {
return this.options.endColor
}
set endColor(v) {
this.options.endColor = v
this.particleSystem.endColor = Cesium.Color.fromCssColorString(v)
if (this._elms.endColor) {
this._elms.endColor.forEach((item, i) => {
let picker = new YJColorPicker({
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: v,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (c) => {
this.endColor = c
},//点击确认按钮事件回调
clear: () => {
this.endColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
this._elms.endColor[i] = picker
})
}
}
get minimumSpeed() {
return this.options.minimumSpeed
}
set minimumSpeed(v) {
this.options.minimumSpeed = v
this.particleSystem.minimumSpeed = v
this._elms.minimumSpeed && this._elms.minimumSpeed.forEach((item) => {
item.value = v
})
}
get maximumSpeed() {
return this.options.maximumSpeed
}
set maximumSpeed(v) {
this.options.maximumSpeed = v
this.particleSystem.maximumSpeed = v
this._elms.maximumSpeed && this._elms.maximumSpeed.forEach((item) => {
item.value = v
})
}
get minimumParticleLife() {
return this.options.minimumParticleLife
}
set minimumParticleLife(v) {
this.options.minimumParticleLife = Number(v)
this.particleSystem.minimumParticleLife = Number(v)
this._elms.minimumParticleLife && this._elms.minimumParticleLife.forEach((item) => {
item.value = Number(v)
})
}
get maximumParticleLife() {
return this.options.maximumParticleLife
}
set maximumParticleLife(v) {
this.options.maximumParticleLife = Number(v)
this.particleSystem.maximumParticleLife = Number(v)
this._elms.maximumParticleLife && this._elms.maximumParticleLife.forEach((item) => {
item.value = Number(v)
})
}
get startScale() {
return this.options.startScale
}
set startScale(v) {
this.options.startScale = v
this.particleSystem.startScale = v
this._elms.startScale && this._elms.startScale.forEach((item) => {
item.value = v
})
}
get endScale() {
return this.options.endScale
}
set endScale(v) {
this.options.endScale = v
this.particleSystem.endScale = v
this._elms.endScale && this._elms.endScale.forEach((item) => {
item.value = v
})
}
get emissionRate() {
return this.options.emissionRate
}
set emissionRate(v) {
this.options.emissionRate = v
this.particleSystem.emissionRate = v
this._elms.emissionRate && this._elms.emissionRate.forEach((item) => {
item.value = v
})
}
get particleSize() {
return this.options.particleSize
}
set particleSize(v) {
this.options.particleSize = v
this.particleSystem.minimumImageSize = new Cesium.Cartesian2(v, v)
this.particleSystem.maximumImageSize = new Cesium.Cartesian2(v, v)
this._elms.particleSize && this._elms.particleSize.forEach((item) => {
item.value = v
})
}
get lng() {
return this.options.lng
}
set lng(v) {
this.options.lng = v
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = v
})
}
get lat() {
return this.options.lat
}
set lat(v) {
this.options.lat = v
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = v
})
}
get alt() {
return this.options.alt
}
set alt(v) {
this.options.alt = v
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = v
})
}
/**
* @description 编辑框
* @param state=false {boolean} 状态: true打开, false关闭
*/
async edit(state = false) {
let _this = this
this.originalOptions = this.deepCopyObj(this.options)
// let elms = this.sdk.viewer._container.getElementsByClassName('YJ-custom-base-dialog')
// for (let i = elms.length - 1; i >= 0; i--) {
// this.sdk.viewer._container.removeChild(elms[i])
// }
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.originalOptions = this.deepCopyObj(this.options)
this._DialogObject.close()
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(this.originalOptions)
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.reset()
// this.entity.style = new Cesium.Cesium3DTileStyle({
// color: "color('rgba(255,255,255," + this.newData.transparency + ")')",
// show: true,
// });
this.positionEditing = false
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
},
showCallBack: (show) => {
this.show = show
this.Dialog.showCallBack && this.Dialog.showCallBack()
},
translationalCallBack: () => {
this.positionEditing = !this.positionEditing
}
}, true)
this._DialogObject._element.body.className = this._DialogObject._element.body.className + ' particle-effects'
let contentElm = document.createElement('div');
contentElm.innerHTML = html()
this._DialogObject.contentAppChild(contentElm)
// 颜色组件
let startColorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("start_color")[0],
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.startColor,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.startColor = color
},//点击确认按钮事件回调
clear: () => {
this.startColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
let endColorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("end_color")[0],
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.endColor,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.endColor = color
},//点击确认按钮事件回调
clear: () => {
this.endColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
let all_elm = contentElm.getElementsByTagName("*")
EventBinding.on(this, all_elm)
this._elms = EventBinding.element
this._elms.startColor = [startColorPicker]
this._elms.endColor = [endColorPicker]
} 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
// }
}
}
reset() {
if (!this.entity) {
return
}
this.name = this.originalOptions.name
this.startColor = this.originalOptions.startColor
this.endColor = this.originalOptions.endColor
this.minimumSpeed = this.originalOptions.minimumSpeed
this.maximumSpeed = this.originalOptions.maximumSpeed
this.minimumParticleLife = this.originalOptions.minimumParticleLife
this.maximumParticleLife = this.originalOptions.maximumParticleLife
this.startScale = this.originalOptions.startScale
this.endScale = this.originalOptions.endScale
this.emissionRate = this.originalOptions.emissionRate
this.particleSize = this.originalOptions.particleSize
this.lng = this.originalOptions.lng
this.lat = this.originalOptions.lat
this.alt = this.originalOptions.alt
}
async remove() {
super.remove()
this.sdk.viewer.scene.primitives.remove(this.entity);
this.entity = null
if (this._DialogObject && !this._DialogObject.isDestroy) {
this._DialogObject.close()
this._DialogObject = null
}
this.tip && this.tip.destroy()
this.event && this.event.destroy()
await this.sdk.removeIncetance(this.options.id)
await syncData(this.sdk, this.options.id)
}
/**@desc 打开平移功能
*
* @memberOf Source
* @param status {boolean}
*
* */
set positionEditing(status) {
if (!this.sdk || !this.sdk.viewer || !this.entity) {
return
}
this.operate.positionEditing = status
if (status === true) {
this.tip && this.tip.destroy()
this.tip = new MouseTip('点击鼠标左键确认,右键取消', this.sdk)
this.picking = false
this.previous = {
positions: { ...this.entity.position }
}
let movPos
this.event.mouse_move((movement, cartesian) => {
movPos = movement.endPosition
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.options.lng = positions.lng
this.options.lat = positions.lat
this.options.alt = positions.alt
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = this.options.lng
})
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = this.options.lat
})
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = this.options.alt
})
this.tip.setPosition(
cartesian,
movement.endPosition.x,
movement.endPosition.y
)
})
this.event.mouse_left((movement, cartesian) => {
if(!movPos || movPos.x !== movement.position.x || movPos.y !== movement.position.y-2) {
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.options.lng = positions.lng
this.options.lat = positions.lat
this.options.alt = positions.alt
}
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this.previous = {
positions: { ...this.entity.position }
}
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
this.event.gesture_pinck_start(() => { })
this.event.gesture_pinck_end(() => { })
this.positionEditing = false
})
this.event.mouse_right((movement, cartesian) => {
this.options.lng = this.entity.position.lng
this.options.lat = this.entity.position.lat
this.options.alt = this.entity.position.alt
this.positionEditing = false
})
this.event.gesture_pinck_start((movement, cartesian) => {
let startTime = new Date()
this.event.gesture_pinck_end(() => {
let endTime = new Date()
if (endTime - startTime >= 500) {
// 长按取消
this.options.lng = this.entity.position.lng
this.options.lat = this.entity.position.lat
this.options.alt = this.entity.position.alt
this.positionEditing = false
}
else {
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.options.lng = positions.lng
this.options.lat = positions.lat
this.options.alt = positions.alt
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this.previous = {
positions: { ...this.entity.position }
}
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
this.event.gesture_pinck_start(() => { })
this.event.gesture_pinck_end(() => { })
this.positionEditing = false
}
})
})
}
else {
this.picking = true
if (this.event) {
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
this.event.gesture_pinck_start(() => { })
this.event.gesture_pinck_end(() => { })
}
this.tip && this.tip.destroy()
if(!this.sdk || !this.sdk.viewer || !this.entity) {
return
}
this.options.lng = this.entity.position.lng
this.options.lat = this.entity.position.lat
this.options.alt = this.entity.position.alt
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = this.options.lng
})
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = this.options.lat
})
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = this.options.alt
})
}
}
get positionEditing() {
return this.operate.positionEditing
}
flicker() { }
}
export default Fountain

View File

@ -0,0 +1,111 @@
function html() {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col">
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" min="-180" max="180" @model="lng">
</div>
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-90" max="90" @model="lat">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="-9999999" max="999999999" @model="alt">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<div class="row">
<div class="col">
<span class="label">起始颜色</span>
<div class="start_color"></div>
</div>
<div class="col" style="margin: 0;justify-content: flex-end;">
<span class="label">结束颜色</span>
<div class="end_color"></div>
</div>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<div class="row">
<span>最小初速度</span>
<input type="range" max="100" min="0" step="1" @model="minimumSpeed">
</div>
</div>
<div class="col">
<div class="row">
<span>最大初速度</span>
<input type="range" max="100" min="0" step="1" @model="maximumSpeed">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>最小存在时间</span>
<input type="range" max="100" min="0.01" step="0.1" @model="minimumParticleLife">
</div>
</div>
<div class="col">
<div class="row">
<span>最大存在时间</span>
<input type="range" max="100" min="0.01" step="0.1" @model="maximumParticleLife">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>起始比例</span>
<input type="range" max="10" min="0" step="0.1" @model="startScale">
</div>
</div>
<div class="col">
<div class="row">
<span>结束比例</span>
<input type="range" max="10" min="0" step="0.1" @model="endScale">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>发射速率(个/秒)</span>
<input type="range" max="100" min="0" step="1" @model="emissionRate">
</div>
</div>
<div class="col">
<div class="row">
<span>尺寸(像素)</span>
<input type="range" max="100" min="0" step="1" @model="particleSize">
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,92 @@
class eventBinding {
constructor() {
this.element = {}
}
static event = {}
getEvent(name) {
return eventBinding.event[name]
}
getEventAll() {
return eventBinding.event
}
setEvent(name, event) {
eventBinding.event[name] = event
}
on(that, elements) {
for (let i = 0; i < elements.length; i++) {
let Event = []
let isEvent = false
let removeName = []
if (!elements[i] ||!elements[i].attributes) {
continue
}
for (let m of elements[i].attributes) {
switch (m.name) {
case '@model': {
isEvent = true
if (elements[i].type == 'checkbox') {
Event.push((e) => { that[m.value] = e.target.checked })
elements[i].checked = that[m.value]
}
else {
Event.push((e) => {
let value = e.target.value
if(e.target.type == 'number' || e.target.type == 'range') {
value = Number(value)
}
that[m.value] = value
})
if(elements[i].nodeName=='IMG') {
elements[i].src = that[m.value]
}
else {
elements[i].value = that[m.value]
}
}
if(this.element[m.value]) {
this.element[m.value].push(elements[i])
}
else {
this.element[m.value] = [elements[i]]
}
removeName.push(m.name)
break;
}
case '@click': {
elements[i].addEventListener('click', (e) => {
if (typeof (that.Dialog[m.value]) === 'function') {
that.Dialog[m.value](e)
}
});
removeName.push(m.name)
// elements[i].attributes.removeNamedItem(m.name)
break;
}
}
// elements[i].attributes[m] = undefined
}
for(let n=0;n<removeName.length;n++) {
elements[i].attributes.removeNamedItem(removeName[n])
}
if (isEvent) {
let ventType = 'input'
if (elements[i].tagName != 'INPUT' || elements[i].type == 'checkbox') {
ventType = 'change'
}
elements[i].addEventListener(ventType, (e) => {
for (let t = 0; t < Event.length; t++) {
Event[t](e)
}
});
}
}
}
}
const EventBinding = new eventBinding();
export default EventBinding;

View File

@ -0,0 +1,739 @@
/**
* 烟雾特效
*/
import Dialog from '../../../Element/Dialog';
import { html, css } from "./_element";
import EventBinding from './eventBinding'
import Base from "../../index";
import MouseEvent from '../../../../Event/index'
import { syncData, getSdk as get2DSdk } from '../../../../Global/MultiViewportMode'
import MouseTip from '../../../../MouseTip'
import { setSplitDirection, syncSplitData, setActiveId } from '../../../../Global/SplitScreen'
import { setActiveViewer, closeRotateAround, closeViewFollow} from '../../../../Global/global'
class Smoke extends Base {
/**
* @constructor
* @description 烟雾特效
* @param sdk
* @param options {object} 粒子属性
* @param options.id {string} 标注id
* @param options.show=true {boolean} 显示/隐藏
* @param options.name {string} 名称
* @param options.url {string} 贴图地址
* @param options.startColor="#00000000" {string} 起始颜色
* @param options.endColor="#0000001a" {string} 结束颜色
* @param options.startScale=0.1 {number} 初始比例
* @param options.endScale=10 {number} 结束比例
* @param options.minimumSpeed=10 {number} 最小初速度
* @param options.maximumSpeed=15 {number} 最大初速度
* @param options.minimumParticleLife=6 {number} 最小存在时间(秒)
* @param options.maximumParticleLife=7 {number} 最大存在时间(秒)
* @param options.emissionRate=28 {number} 发射速率(个/每秒)
* @param options.particleSize=2{number} 粒子尺大小
* @param options.lng 经度
* @param options.lat 纬度
* @param options.alt 高度
* @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} 高度
* */
constructor(sdk, options, _Dialog = {}) {
super(sdk, options);
this.options.url = options.url
this.options.startColor = options.startColor || "#00000000"
this.options.endColor = options.endColor || "#0000001a"
this.options.startScale = options.startScale || 0.1
this.options.endScale = options.endScale || 10
this.options.minimumParticleLife = options.minimumParticleLife || 6
this.options.maximumParticleLife = options.maximumParticleLife || 7
this.options.minimumSpeed = options.minimumSpeed || 10
this.options.maximumSpeed = options.maximumSpeed || 15
this.options.emissionRate = options.emissionRate || 28
this.options.particleSize = options.particleSize || 2
this.options.show = options.show === false ? false : true
this._elms = {};
this.positionCallBack = null
this.rotationCallback = null
this.onClickCallback = null
this._DialogObject = null
this._element = null
this.particleSystem
this.sdk.addIncetance(this.options.id, this)
this.add()
this.operate = {}
this.previous = {
positions: {
lng: this.options.lng,
lat: this.options.lat,
alt: this.options.alt,
}
}
this.Dialog = _Dialog
this.event = new MouseEvent(this.sdk)
}
get type() {
return "ParticleEffects"
}
get show() {
return this.options.show
}
set show(v) {
if (typeof v === "boolean") {
let sdkD = get2DSdk().sdkD
if (!this.isShowView || !sdkD) {
this.options.show = v
}
if (!this.showView || this.showView == 3 || !sdkD) {
if (this.entity && this.sdk.viewer.camera.positionCartographic.height < 10000000) {
this.entity.show = this.options.show
}
if (this.options.label && this.options.label.show) {
this.label.show = this.options.show
}
}
else {
if (this.entity && this.sdk.viewer.camera.positionCartographic.height < 10000000) {
this.entity.show = false
}
if (this.options.label && this.options.label.show) {
this.label.show = false
}
}
if(this._DialogObject && this._DialogObject.showBtn) {
this._DialogObject.showBtn.checked = v
}
syncData(this.sdk, this.options.id)
syncSplitData(this.sdk, this.options.id)
this.isShowView = false
} else {
console.error("参数必须为boolean")
}
}
async add() {
this.originalOptions = this.deepCopyObj(this.options)
const scene = this.sdk.viewer.scene;
var cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
var position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
let matrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
Cesium.Matrix4.multiplyByScale(matrix, new Cesium.Cartesian3(1, 1, 1), matrix)
let cameraHeight = this.sdk.viewer.camera.positionCartographic.height;
this.particleSystem = scene.primitives.add(
new Cesium.ParticleSystem({
show: (cameraHeight >= 10000000) ? false : this.options.show,
image: this.options.url || (this.getSourceRootPath() + '/img/particlesystem/smoke.png'),
startColor: Cesium.Color.fromCssColorString(this.options.startColor), //粒子出生时的颜色
endColor: Cesium.Color.fromCssColorString(this.options.endColor), //当粒子死亡时的颜色
startScale: this.options.startScale, //粒子出生时的比例
endScale: this.options.endScale, //粒子在死亡时的比例
minimumParticleLife: this.options.minimumParticleLife, //设置粒子寿命的可能持续时间的最小界限(以秒为单位)
maximumParticleLife: this.options.maximumParticleLife, //设置粒子寿命的可能持续时间的最大界限(以秒为单位)
minimumSpeed: this.options.minimumSpeed,//设置以米/秒为单位的最小界限,超过该最小界限,随机选择粒子的实际速度。
maximumSpeed: this.options.maximumSpeed,//设置以米/秒为单位的最大界限,超过该最大界限,随机选择粒子的实际速度。
// imageSize: new Cesium.Cartesian2( //如果设置该属性,将会覆盖 minimumImageSize和maximumImageSize属性以像素为单位缩放image的大小
// this.options.imageSize || 10,
// this.options.imageSize || 10
// ),
minimumImageSize: new Cesium.Cartesian2(
this.options.particleSize,
this.options.particleSize
),
maximumImageSize: new Cesium.Cartesian2(
this.options.particleSize,
this.options.particleSize
),
sizeInMeters: true,
emissionRate: this.options.emissionRate, //每秒发射的粒子数。
lifetime: 0.5, //多长时间的粒子系统将以秒为单位发射粒子
loop: true,
emitter: new Cesium.CircleEmitter(0.2),
performance: false,
modelMatrix: matrix,
updateCallback: (r)=>{
r._billboard.id = this.options.id
}
})
);
this.particleSystem.id = this.options.id
this.entity = this.particleSystem
// this.entity.modelMatrix = Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(100.0, 20.0)), new Cesium.Cartesian3(0.0, 0.0, 10000.0), new Cesium.Matrix4())
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
// this.editObj = new EditParticle(this.sdk, this.entity)
syncData(this.sdk, this.options.id)
if(this.options.show) {
setSplitDirection(0, this.options.id)
}
// 监听相机高度
this.sdk.viewer.camera.changed.addEventListener(() => {
if (this.entity && this.show) {
let cameraHeight = this.sdk.viewer.camera.positionCartographic.height;
if (cameraHeight >= 10000000) {
this.entity.show = false
}
else {
this.entity.show = true
}
}
});
}
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 = { lng: 0, lat: 0 }
if (this.options.position) {
position = { ...this.options.position }
}
else if (this.options.positions) {
position = { ...this.options.positions[0] }
}
else if (this.options.center) {
position = { ...this.options.center }
}
else {
if (this.options.hasOwnProperty('lng')) {
position.lng = this.options.lng
}
if (this.options.hasOwnProperty('lat')) {
position.lat = this.options.lat
}
if (this.options.hasOwnProperty('alt')) {
position.alt = this.options.alt
}
}
// 如果没有高度值,则获取紧贴高度计算
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 {
this.sdk.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(this.options.lng, this.options.lat, this.options.alt + 500),
orientation: options.orientation || {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
}
})
}
}
get startColor() {
return this.options.startColor
}
set startColor(v) {
this.options.startColor = v
this.particleSystem.startColor = Cesium.Color.fromCssColorString(v)
if (this._elms.startColor) {
this._elms.startColor.forEach((item, i) => {
let picker = new YJColorPicker({
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: v,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (c) => {
this.startColor = c
},//点击确认按钮事件回调
clear: () => {
this.startColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
this._elms.startColor[i] = picker
})
}
}
get endColor() {
return this.options.endColor
}
set endColor(v) {
this.options.endColor = v
this.particleSystem.endColor = Cesium.Color.fromCssColorString(v)
if (this._elms.endColor) {
this._elms.endColor.forEach((item, i) => {
let picker = new YJColorPicker({
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: v,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (c) => {
this.endColor = c
},//点击确认按钮事件回调
clear: () => {
this.endColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
this._elms.endColor[i] = picker
})
}
}
get minimumSpeed() {
return this.options.minimumSpeed
}
set minimumSpeed(v) {
this.options.minimumSpeed = v
this.particleSystem.minimumSpeed = v
this._elms.minimumSpeed && this._elms.minimumSpeed.forEach((item) => {
item.value = v
})
}
get maximumSpeed() {
return this.options.maximumSpeed
}
set maximumSpeed(v) {
this.options.maximumSpeed = v
this.particleSystem.maximumSpeed = v
this._elms.maximumSpeed && this._elms.maximumSpeed.forEach((item) => {
item.value = v
})
}
get minimumParticleLife() {
return this.options.minimumParticleLife
}
set minimumParticleLife(v) {
this.options.minimumParticleLife = v
this.particleSystem.minimumParticleLife = v
this._elms.minimumParticleLife && this._elms.minimumParticleLife.forEach((item) => {
item.value = v
})
}
get maximumParticleLife() {
return this.options.maximumParticleLife
}
set maximumParticleLife(v) {
this.options.maximumParticleLife = v
this.particleSystem.maximumParticleLife = v
this._elms.maximumParticleLife && this._elms.maximumParticleLife.forEach((item) => {
item.value = v
})
}
get startScale() {
return this.options.startScale
}
set startScale(v) {
this.options.startScale = v
this.particleSystem.startScale = v
this._elms.startScale && this._elms.startScale.forEach((item) => {
item.value = v
})
}
get endScale() {
return this.options.endScale
}
set endScale(v) {
this.options.endScale = v
this.particleSystem.endScale = v
this._elms.endScale && this._elms.endScale.forEach((item) => {
item.value = v
})
}
get emissionRate() {
return this.options.emissionRate
}
set emissionRate(v) {
this.options.emissionRate = v
this.particleSystem.emissionRate = v
this._elms.emissionRate && this._elms.emissionRate.forEach((item) => {
item.value = v
})
}
get particleSize() {
return this.options.particleSize
}
set particleSize(v) {
this.options.particleSize = v
this.particleSystem.minimumImageSize = new Cesium.Cartesian2(v, v)
this.particleSystem.maximumImageSize = new Cesium.Cartesian2(v, v)
this._elms.particleSize && this._elms.particleSize.forEach((item) => {
item.value = v
})
}
get lng() {
return this.options.lng
}
set lng(v) {
this.options.lng = v
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = v
})
}
get lat() {
return this.options.lat
}
set lat(v) {
this.options.lat = v
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = v
})
}
get alt() {
return this.options.alt
}
set alt(v) {
this.options.alt = v
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = v
})
}
/**
* @description 编辑框
* @param state=false {boolean} 状态: true打开, false关闭
*/
async edit(state = false) {
let _this = this
this.originalOptions = this.deepCopyObj(this.options)
// let elms = this.sdk.viewer._container.getElementsByClassName('YJ-custom-base-dialog')
// for (let i = elms.length - 1; i >= 0; i--) {
// this.sdk.viewer._container.removeChild(elms[i])
// }
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.originalOptions = this.deepCopyObj(this.options)
this._DialogObject.close()
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(this.originalOptions)
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.reset()
// this.entity.style = new Cesium.Cesium3DTileStyle({
// color: "color('rgba(255,255,255," + this.newData.transparency + ")')",
// show: true,
// });
this.positionEditing = false
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
},
showCallBack: (show) => {
this.show = show
this.Dialog.showCallBack && this.Dialog.showCallBack()
},
translationalCallBack: () => {
this.positionEditing = !this.positionEditing
}
}, true)
this._DialogObject._element.body.className = this._DialogObject._element.body.className + ' particle-effects'
let contentElm = document.createElement('div');
contentElm.innerHTML = html()
this._DialogObject.contentAppChild(contentElm)
// 颜色组件
let startColorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("start_color")[0],
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.startColor,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.startColor = color
},//点击确认按钮事件回调
clear: () => {
this.startColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
let endColorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("end_color")[0],
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.endColor,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.endColor = color
},//点击确认按钮事件回调
clear: () => {
this.endColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
let all_elm = contentElm.getElementsByTagName("*")
EventBinding.on(this, all_elm)
this._elms = EventBinding.element
this._elms.startColor = [startColorPicker]
this._elms.endColor = [endColorPicker]
} 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
// }
}
}
reset() {
if (!this.entity) {
return
}
this.name = this.originalOptions.name
this.startColor = this.originalOptions.startColor
this.endColor = this.originalOptions.endColor
this.minimumSpeed = this.originalOptions.minimumSpeed
this.maximumSpeed = this.originalOptions.maximumSpeed
this.minimumParticleLife = this.originalOptions.minimumParticleLife
this.maximumParticleLife = this.originalOptions.maximumParticleLife
this.startScale = this.originalOptions.startScale
this.endScale = this.originalOptions.endScale
this.emissionRate = this.originalOptions.emissionRate
this.particleSize = this.originalOptions.particleSize
this.lng = this.originalOptions.lng
this.lat = this.originalOptions.lat
this.alt = this.originalOptions.alt
}
async remove() {
super.remove()
this.sdk.viewer.scene.primitives.remove(this.entity);
this.entity = null
if (this._DialogObject && !this._DialogObject.isDestroy) {
this._DialogObject.close()
this._DialogObject = null
}
this.tip && this.tip.destroy()
this.event && this.event.destroy()
await this.sdk.removeIncetance(this.options.id)
await syncData(this.sdk, this.options.id)
}
/**@desc 打开平移功能
*
* @memberOf Source
* @param status {boolean}
*
* */
set positionEditing(status) {
if (!this.sdk || !this.sdk.viewer || !this.entity) {
return
}
this.operate.positionEditing = status
if (status === true) {
this.tip && this.tip.destroy()
this.tip = new MouseTip('点击鼠标左键确认,右键取消', this.sdk)
this.picking = false
this.previous = {
positions: { ...this.entity.position }
}
let movPos
this.event.mouse_move((movement, cartesian) => {
movPos = movement.endPosition
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.options.lng = positions.lng
this.options.lat = positions.lat
this.options.alt = positions.alt
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = this.options.lng
})
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = this.options.lat
})
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = this.options.alt
})
this.tip.setPosition(
cartesian,
movement.endPosition.x,
movement.endPosition.y
)
})
this.event.mouse_left((movement, cartesian) => {
if(!movPos || movPos.x !== movement.position.x || movPos.y !== movement.position.y-2) {
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.options.lng = positions.lng
this.options.lat = positions.lat
this.options.alt = positions.alt
}
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this.previous = {
positions: { ...this.entity.position }
}
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
this.event.gesture_pinck_start(() => { })
this.event.gesture_pinck_end(() => { })
this.positionEditing = false
})
this.event.mouse_right((movement, cartesian) => {
this.options.lng = this.entity.position.lng
this.options.lat = this.entity.position.lat
this.options.alt = this.entity.position.alt
this.positionEditing = false
})
this.event.gesture_pinck_start((movement, cartesian) => {
let startTime = new Date()
this.event.gesture_pinck_end(() => {
let endTime = new Date()
if (endTime - startTime >= 500) {
// 长按取消
this.options.lng = this.entity.position.lng
this.options.lat = this.entity.position.lat
this.options.alt = this.entity.position.alt
this.positionEditing = false
}
else {
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.options.lng = positions.lng
this.options.lat = positions.lat
this.options.alt = positions.alt
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this.previous = {
positions: { ...this.entity.position }
}
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
this.event.gesture_pinck_start(() => { })
this.event.gesture_pinck_end(() => { })
this.positionEditing = false
}
})
})
}
else {
this.picking = true
if (this.event) {
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
this.event.gesture_pinck_start(() => { })
this.event.gesture_pinck_end(() => { })
}
this.tip && this.tip.destroy()
if(!this.sdk || !this.sdk.viewer || !this.entity) {
return
}
this.options.lng = this.entity.position.lng
this.options.lat = this.entity.position.lat
this.options.alt = this.entity.position.alt
let cartographic = Cesium.Cartographic.fromDegrees(this.options.lng, this.options.lat, this.options.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = this.options.lng
})
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = this.options.lat
})
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = this.options.alt
})
}
}
get positionEditing() {
return this.operate.positionEditing
}
flicker() {}
}
export default Smoke

View File

@ -0,0 +1,122 @@
function html() {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input style="width: 175px;" class="input" type="text" @model="name">
</div>
<div class="col">
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" min="-180" max="180" @model="lng">
</div>
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-90" max="90" @model="lat">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="-9999999" max="999999999" @model="alt">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<div class="row">
<div class="col">
<span class="label">起始颜色</span>
<div class="start_color"></div>
</div>
<div class="col" style="margin: 0;justify-content: flex-end;">
<span class="label">结束颜色</span>
<div class="end_color"></div>
</div>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<div class="row">
<span>速度</span>
<input type="range" max="30" min="0" step="0.1" @model="speed">
</div>
</div>
<div class="col">
<div class="row">
<span>发射速率(个/秒)</span>
<input type="range" max="100" min="0" step="1" @model="emissionRate">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>最小存在时间</span>
<input type="range" max="100" min="0.01" step="0.1" @model="minimumParticleLife">
</div>
</div>
<div class="col">
<div class="row">
<span>最大存在时间</span>
<input type="range" max="100" min="0.01" step="0.1" @model="maximumParticleLife">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>起始比例</span>
<input type="range" max="10" min="0" step="0.1" @model="startScale">
</div>
</div>
<div class="col">
<div class="row">
<span>结束比例</span>
<input type="range" max="10" min="0" step="0.1" @model="endScale">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>朝向</span>
<input type="range" max="360" min="0.1" step="0.1" @model="heading">
</div>
</div>
<div class="col">
<div class="row">
<span>俯仰角度</span>
<input type="range" max="360" min="0.1" step="0.1" @model="pitch">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>尺寸(像素)</span>
<input type="range" max="100" min="0" step="1" @model="particleSize">
</div>
</div>
<div class="col">
</div>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,974 @@
/**
* 水柱特效
*/
import Dialog from '../../../Element/Dialog';
import { html, css } from "./_element";
import Base from "../../index";
import MouseEvent from '../../../../Event/index'
import { syncData, getSdk as get2DSdk } from '../../../../Global/MultiViewportMode'
import MouseTip from '../../../../MouseTip'
import { setSplitDirection, syncSplitData, setActiveId } from '../../../../Global/SplitScreen'
import { setActiveViewer, closeRotateAround, closeViewFollow } from '../../../../Global/global'
class Spout extends Base {
/**
* @constructor
* @description 水柱
* @param sdk
* @param options {object} 粒子属性
* @param options.id {string} 标注id
* @param options.show=true {boolean} 显示/隐藏
* @param options.name {string} 名称
* @param options.url {string} 贴图地址
* @param options.startColor="#c1f7f2" {string} 起始颜色
* @param options.endColor="#ffffff00" {string} 结束颜色
* @param options.startScale=0.2 {number} 初始比例
* @param options.endScale=2 {number} 结束比例
* @param options.speed {number} 速度
* @param options.minimumParticleLife=12 {number} 最小存在时间(秒)
* @param options.maximumParticleLife=12 {number} 最大存在时间(秒)
* @param options.emissionRate=100 {number} 发射速率(个/每秒)
* @param options.particleSize=1 {number} 粒子尺大小
* @param options.heading 航向角
* @param options.pitch 俯仰角
* @param options.start {object} 开始位置
* @param options.start.lng 经度
* @param options.start.lat 纬度
* @param options.start.alt 高度
* @param options.end {object} 结束位置
* @param options.end.lng 经度
* @param options.end.lat 纬度
* @param options.end.alt 高度
* @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} 高度
* */
constructor(sdk, options, _Dialog = {}) {
super(sdk, options);
this.options.url = options.url
this.options.startColor = options.startColor || "#c1f7f2"
this.options.endColor = options.endColor || "#ffffff00"
this.options.startScale = options.startScale || 0.2
this.options.endScale = options.endScale || 2
this.options.minimumParticleLife = options.minimumParticleLife || 12
this.options.maximumParticleLife = options.maximumParticleLife || 12
this.options.emissionRate = options.emissionRate || 100
this.options.particleSize = options.particleSize || 1
this.options.show = options.show === false ? false : true
this._elms = {};
this.positionCallBack = null
this.rotationCallback = null
this.onClickCallback = null
this._DialogObject = null
this._element = null
this.particleSystem
this.sdk.addIncetance(this.options.id, this)
this.add()
this.operate = {}
this.previous = {
positions: {
lng: this.options.start.lng,
lat: this.options.start.lat,
alt: this.options.start.alt,
}
}
this.Dialog = _Dialog
this.event = new MouseEvent(this.sdk)
}
get type() {
return "ParticleEffects"
}
get show() {
return this.options.show
}
set show(v) {
if (typeof v === "boolean") {
let sdkD = get2DSdk().sdkD
if (!this.isShowView || !sdkD) {
this.options.show = v
}
if (!this.showView || this.showView == 3 || !sdkD) {
if (this.entity && this.sdk.viewer.camera.positionCartographic.height < 10000000) {
this.entity.show = this.options.show
}
if (this.options.label && this.options.label.show) {
this.label.show = this.options.show
}
}
else {
if (this.entity && this.sdk.viewer.camera.positionCartographic.height < 10000000) {
this.entity.show = false
}
if (this.options.label && this.options.label.show) {
this.label.show = false
}
}
if(this._DialogObject && this._DialogObject.showBtn) {
this._DialogObject.showBtn.checked = v
}
syncData(this.sdk, this.options.id)
syncSplitData(this.sdk, this.options.id)
this.isShowView = false
} else {
console.error("参数必须为boolean")
}
}
async add() {
let _this = this
this.originalOptions = this.deepCopyObj(this.options)
const scene = this.sdk.viewer.scene;
let cartographic = Cesium.Cartographic.fromDegrees(this.options.start.lng, this.options.start.lat, this.options.start.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
let matrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
Cesium.Matrix4.multiplyByScale(matrix, new Cesium.Cartesian3(1, 1, 1), matrix)
let gravityVector = new Cesium.Cartesian3();
let gravity = -3.8;// 重力方向
let start = Cesium.Cartesian3.fromDegrees(this.options.start.lng, this.options.start.lat, this.options.start.alt)
let end = Cesium.Cartesian3.fromDegrees(this.options.end.lng, this.options.end.lat, this.options.end.alt)
if (!this.options.heading && this.options.heading !== 0) {
this.options.heading = getHeading(start, end)
}
let y0 = this.options.end.alt - this.options.start.alt
let x0 = Cesium.Cartesian3.distance(start, Cesium.Cartesian3.fromDegrees(this.options.end.lng, this.options.end.lat, this.options.start.alt))
let tanA
if (!y0) {
tanA = 0
}
else {
tanA = 2 * y0 / x0
}
let a = Math.atan(tanA) * (180 / Math.PI);
let t = Math.sqrt((Math.abs(tanA) * x0) / -gravity)
let speed = -gravity * t / Math.abs(Math.cos(a))
if (!this.options.pitch && this.options.pitch !== 0) {
this.options.pitch = 90 - a
}
if (!this.options.speed && this.options.speed !== 0) {
this.options.speed = speed
}
let cameraHeight = this.sdk.viewer.camera.positionCartographic.height;
// // 计算发射参数
// function calculateLaunchParameters(height, distance, gravity) {
// // 解决斜抛运动问题y = h + x·tan(θ) - (g·x²)/(2·v₀²·cos²(θ))
// // 当 y = 0, x = distance 时,求解 v₀ 和 θ
// // 简化计算,使用最优角度 θ = 45°
// const angle = Cesium.Math.toRadians(45);
// // 计算初始速度
// const velocity = Math.sqrt((gravity * distance * distance) /
// (2 * (height + distance * Math.tan(angle)) * Math.pow(Math.cos(angle), 2)));
// // 计算飞行时间
// const vy0 = velocity * Math.sin(angle);
// const flightTime = (vy0 + Math.sqrt(vy0 * vy0 + 2 * gravity * height)) / gravity;
// // 计算最大高度
// const maxHeight = height + (vy0 * vy0) / (2 * gravity);
// return { velocity, angle, flightTime, maxHeight };
// }
// let params = {
// launchHeight: this.options.start.alt, // 发射高度
// targetDistance: Cesium.Cartesian3.distance(start, end), // 目标距离
// gravity: 9.8, // 重力
// }
// // 计算初始速度和发射角度
// const { velocity, angle, flightTime, maxHeight } = calculateLaunchParameters(
// params.launchHeight,
// params.targetDistance,
// params.gravity
// );
// if (!this.options.speed && this.options.speed !== 0) {
// this.options.speed = velocity*10
// }
this.particleSystem = scene.primitives.add(
new Cesium.ParticleSystem({
show: (cameraHeight >= 10000000) ? false : this.options.show,
image: this.options.url || (this.getSourceRootPath() + '/img/particlesystem/smoke.png'),
// 从绿色到白色淡出
startColor: Cesium.Color.fromCssColorString(this.options.startColor), //粒子出生时的颜色
endColor: Cesium.Color.fromCssColorString(this.options.endColor), //当粒子死亡时的颜色
startScale: this.options.startScale, //粒子出生时的比例
endScale: this.options.endScale, //粒子在死亡时的比例
minimumParticleLife: this.options.minimumParticleLife, //设置粒子寿命的可能持续时间的最小界限(以秒为单位)
maximumParticleLife: this.options.maximumParticleLife, //设置粒子寿命的可能持续时间的最大界限(以秒为单位)
minimumSpeed: this.options.speed,//设置以米/秒为单位的最小界限,超过该最小界限,随机选择粒子的实际速度。
maximumSpeed: this.options.speed,//设置以米/秒为单位的最大界限,超过该最大界限,随机选择粒子的实际速度。
// imageSize: new Cesium.Cartesian2( //如果设置该属性,将会覆盖 minimumImageSize和maximumImageSize属性以像素为单位缩放image的大小
// this.options.imageSize || 10,
// this.options.imageSize || 10
// ),
lifetime: 0.5,
imageSize: new Cesium.Cartesian2(this.options.particleSize, this.options.particleSize * 2),
sizeInMeters: true,
emissionRate: this.options.emissionRate, //每秒发射的粒子数。
loop: true,
emitter: new Cesium.CircleEmitter(0.2),
modelMatrix: matrix,
emitterModelMatrix: computeEmitterModelMatrix(),// 发射器转换为世界坐标
// 增加重力场影像,
updateCallback: applyGravity,
})
);
function applyGravity(p, dt) {
p._billboard.id = _this.options.id
let position = p.position;
Cesium.Cartesian3.normalize(position, gravityVector);
// Cesium.Cartesian3.multiplyByScalar(gravityVector, -4.8 * dt, gravityVector);
Cesium.Cartesian3.multiplyByScalar(gravityVector, gravity * dt, gravityVector);
p.velocity = Cesium.Cartesian3.add(p.velocity, gravityVector, p.velocity);
}
// 计算粒子发射器的位置姿态
function computeEmitterModelMatrix() {
let hpr = Cesium.HeadingPitchRoll.fromDegrees(_this.options.heading + 90, _this.options.pitch, 0);//!!!发射粒子的方向
let trs = new Cesium.TranslationRotationScale();
trs.translation = Cesium.Cartesian3.fromElements(0, 0, 1);
trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr);
let Matrix4 = Cesium.Matrix4.fromTranslationRotationScale(trs);
return Matrix4
}
// 根据两个坐标点,获取Heading(朝向)
function getHeading(fromPosition, toPosition) {
let finalPosition = new Cesium.Cartesian3();
let matrix4 = Cesium.Transforms.eastNorthUpToFixedFrame(fromPosition);
Cesium.Matrix4.inverse(matrix4, matrix4);
Cesium.Matrix4.multiplyByPoint(matrix4, toPosition, finalPosition);
Cesium.Cartesian3.normalize(finalPosition, finalPosition);
return Cesium.Math.toDegrees(Math.atan2(finalPosition.x, finalPosition.y));
}
// this.entity.modelMatrix
this.particleSystem.id = this.options.id
this.entity = this.particleSystem
// this.entity.modelMatrix = Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(100.0, 20.0)), new Cesium.Cartesian3(0.0, 0.0, 10000.0), new Cesium.Matrix4())
this.entity.position = { lng: this.options.start.lng, lat: this.options.start.lat, alt: this.options.start.alt }
// this.editObj = new EditParticle(this.sdk, this.entity)
syncData(this.sdk, this.options.id)
if (this.options.show) {
setSplitDirection(0, this.options.id)
}
// 监听相机高度
this.sdk.viewer.camera.changed.addEventListener(() => {
if (this.entity && this.show) {
let cameraHeight = this.sdk.viewer.camera.positionCartographic.height;
if (cameraHeight >= 10000000) {
this.entity.show = false
}
else {
this.entity.show = true
}
}
});
// this.translation = new Cesium.Cartesian3();
// this.rotation = new Cesium.Quaternion();
// this.hpr = new Cesium.HeadingPitchRoll();
// this.trs = new Cesium.TranslationRotationScale();
// this.emitterModelMatrix = new Cesium.Matrix4();
// this.hpr = Cesium.HeadingPitchRoll.fromDegrees(60, 0.0, 0.0, this.hpr);
// this.trs.translation = Cesium.Cartesian3.fromElements(0, 0, 0, this.translation);
// this.trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(this.hpr, this.rotation);
// this.particleSystem.emitterModelMatrix = Cesium.Matrix4.fromTranslationRotationScale(this.trs, this.emitterModelMatrix);
}
async flyTo(options = {}) {
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 = { lng: 0, lat: 0 }
if (this.options.position) {
position = { ...this.options.position }
}
else if (this.options.positions) {
position = { ...this.options.positions[0] }
}
else if (this.options.line && this.options.line.positions) {
position = { ...this.options.line.positions[0] }
}
else if (this.options.center) {
position = { ...this.options.center }
}
else if (this.options.start) {
position = { ...this.options.start }
}
else {
if (this.options.hasOwnProperty('lng')) {
position.lng = this.options.lng
}
if (this.options.hasOwnProperty('lat')) {
position.lat = this.options.lat
}
if (this.options.hasOwnProperty('alt')) {
position.alt = this.options.alt
}
}
// 如果没有高度值,则获取紧贴高度计算
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 {
this.sdk.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(this.options.start.lng, this.options.start.lat, this.options.start.alt + 500),
orientation: options.orientation || {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
}
})
}
}
get startColor() {
return this.options.startColor
}
set startColor(v) {
this.options.startColor = v
this.particleSystem.startColor = Cesium.Color.fromCssColorString(v)
if (this._elms.startColor) {
this._elms.startColor.forEach((item, i) => {
let picker = new YJColorPicker({
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: v,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (c) => {
this.startColor = c
},//点击确认按钮事件回调
clear: () => {
this.startColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
this._elms.startColor[i] = picker
})
}
}
get endColor() {
return this.options.endColor
}
set endColor(v) {
this.options.endColor = v
this.particleSystem.endColor = Cesium.Color.fromCssColorString(v)
if (this._elms.endColor) {
this._elms.endColor.forEach((item, i) => {
let picker = new YJColorPicker({
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: v,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (c) => {
this.endColor = c
},//点击确认按钮事件回调
clear: () => {
this.endColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
this._elms.endColor[i] = picker
})
}
}
get speed() {
return this.options.speed
}
set speed(v) {
this.options.speed = Number(v)
this.particleSystem.minimumSpeed = Number(v)
this.particleSystem.maximumSpeed = Number(v)
this._elms.speed && this._elms.speed.forEach((item) => {
item.value = Number(v)
})
}
get minimumParticleLife() {
return this.options.minimumParticleLife
}
set minimumParticleLife(v) {
this.options.minimumParticleLife = Number(v)
this.particleSystem.minimumParticleLife = Number(v)
this._elms.minimumParticleLife && this._elms.minimumParticleLife.forEach((item) => {
item.value = Number(v)
})
}
get maximumParticleLife() {
return this.options.maximumParticleLife
}
set maximumParticleLife(v) {
this.options.maximumParticleLife = Number(v)
this.particleSystem.maximumParticleLife = Number(v)
this._elms.maximumParticleLife && this._elms.maximumParticleLife.forEach((item) => {
item.value = Number(v)
})
}
get startScale() {
return this.options.startScale
}
set startScale(v) {
this.options.startScale = Number(v)
this.particleSystem.startScale = Number(v)
this._elms.startScale && this._elms.startScale.forEach((item) => {
item.value = Number(v)
})
}
get endScale() {
return this.options.endScale
}
set endScale(v) {
this.options.endScale = Number(v)
this.particleSystem.endScale = Number(v)
this._elms.endScale && this._elms.endScale.forEach((item) => {
item.value = Number(v)
})
}
get emissionRate() {
return this.options.emissionRate
}
set emissionRate(v) {
this.options.emissionRate = Number(v)
this.particleSystem.emissionRate = Number(v)
this._elms.emissionRate && this._elms.emissionRate.forEach((item) => {
item.value = Number(v)
})
}
get particleSize() {
return this.options.particleSize
}
set particleSize(v) {
this.options.particleSize = Number(v)
this.particleSystem.minimumImageSize = new Cesium.Cartesian2(Number(v), Number(v) * 2)
this.particleSystem.maximumImageSize = new Cesium.Cartesian2(Number(v), Number(v) * 2)
this._elms.particleSize && this._elms.particleSize.forEach((item) => {
item.value = Number(v)
})
}
get lng() {
return this.options.start.lng
}
set lng(v) {
this.options.start.lng = v
let cartographic = Cesium.Cartographic.fromDegrees(this.options.start.lng, this.options.start.lat, this.options.start.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this.entity.position = { lng: this.options.start.lng, lat: this.options.start.lat, alt: this.options.start.alt }
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = v
})
}
get lat() {
return this.options.start.lat
}
set lat(v) {
this.options.start.lat = v
let cartographic = Cesium.Cartographic.fromDegrees(this.options.start.lng, this.options.start.lat, this.options.start.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this.entity.position = { lng: this.options.start.lng, lat: this.options.start.lat, alt: this.options.start.alt }
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = v
})
}
get alt() {
return this.options.start.alt
}
set alt(v) {
this.options.start.alt = v
let cartographic = Cesium.Cartographic.fromDegrees(this.options.start.lng, this.options.start.lat, this.options.start.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this.entity.position = { lng: this.options.start.lng, lat: this.options.start.lat, alt: this.options.start.alt }
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = v
})
}
get heading() {
return this.options.heading
}
set heading(v) {
this.options.heading = Number(v)
let hpr = Cesium.HeadingPitchRoll.fromDegrees(this.options.heading + 90, this.options.pitch, 0);//!!!发射粒子的方向
let trs = new Cesium.TranslationRotationScale();
trs.translation = Cesium.Cartesian3.fromElements(0, 0, 1);
trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr);
let Matrix4 = Cesium.Matrix4.fromTranslationRotationScale(trs);
this.particleSystem.emitterModelMatrix = Matrix4
this._elms.heading && this._elms.heading.forEach((item) => {
item.value = Number(v)
})
}
get pitch() {
return this.options.pitch
}
set pitch(v) {
this.options.pitch = Number(v)
let hpr = Cesium.HeadingPitchRoll.fromDegrees(this.options.heading + 90, this.options.pitch, 0);//!!!发射粒子的方向
let trs = new Cesium.TranslationRotationScale();
trs.translation = Cesium.Cartesian3.fromElements(0, 0, 1);
trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr);
let Matrix4 = Cesium.Matrix4.fromTranslationRotationScale(trs);
this.particleSystem.emitterModelMatrix = Matrix4
this._elms.pitch && this._elms.pitch.forEach((item) => {
item.value = Number(v)
})
}
/**
* @description 编辑框
* @param state=false {boolean} 状态: true打开, false关闭
*/
async edit(state = false) {
let _this = this
this.originalOptions = this.deepCopyObj(this.options)
// let elms = this.sdk.viewer._container.getElementsByClassName('YJ-custom-base-dialog')
// for (let i = elms.length - 1; i >= 0; i--) {
// this.sdk.viewer._container.removeChild(elms[i])
// }
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.originalOptions = this.deepCopyObj(this.options)
this._DialogObject.close()
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(this.originalOptions)
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.reset()
// this.entity.style = new Cesium.Cesium3DTileStyle({
// color: "color('rgba(255,255,255," + this.newData.transparency + ")')",
// show: true,
// });
this.positionEditing = false
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
},
showCallBack: (show) => {
this.show = show
this.Dialog.showCallBack && this.Dialog.showCallBack()
},
translationalCallBack: () => {
this.positionEditing = !this.positionEditing
}
}, true)
this._DialogObject._element.body.className = this._DialogObject._element.body.className + ' particle-effects'
let contentElm = document.createElement('div');
contentElm.innerHTML = html()
this._DialogObject.contentAppChild(contentElm)
// 颜色组件
let startColorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("start_color")[0],
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.startColor,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.startColor = color
},//点击确认按钮事件回调
clear: () => {
this.startColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
let endColorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("end_color")[0],
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.endColor,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.endColor = color
},//点击确认按钮事件回调
clear: () => {
this.endColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
let all_elm = contentElm.getElementsByTagName("*")
Spout.EventBinding(this, all_elm)
this._elms.startColor = [startColorPicker]
this._elms.endColor = [endColorPicker]
} 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
// }
}
}
reset() {
if (!this.entity) {
return
}
this.name = this.originalOptions.name
this.startColor = this.originalOptions.startColor
this.endColor = this.originalOptions.endColor
this.speed = this.originalOptions.speed
this.minimumParticleLife = this.originalOptions.minimumParticleLife
this.maximumParticleLife = this.originalOptions.maximumParticleLife
this.startScale = this.originalOptions.startScale
this.endScale = this.originalOptions.endScale
this.emissionRate = this.originalOptions.emissionRate
this.particleSize = this.originalOptions.particleSize
this.lng = this.originalOptions.start.lng
this.lat = this.originalOptions.start.lat
this.alt = this.originalOptions.start.alt
}
async remove() {
super.remove()
this.sdk.viewer.scene.primitives.remove(this.entity);
this.entity = null
if (this._DialogObject && !this._DialogObject.isDestroy) {
this._DialogObject.close()
this._DialogObject = null
}
this.tip && this.tip.destroy()
this.event && this.event.destroy()
await this.sdk.removeIncetance(this.options.id)
await syncData(this.sdk, this.options.id)
}
/**@desc 打开平移功能
*
* @memberOf Source
* @param status {boolean}
*
* */
set positionEditing(status) {
if (!this.sdk || !this.sdk.viewer || !this.entity) {
return
}
this.operate.positionEditing = status
if (status === true) {
this.tip && this.tip.destroy()
this.tip = new MouseTip('点击鼠标左键确认,右键取消', this.sdk)
this.picking = false
this.previous = {
positions: { ...this.entity.position }
}
let movPos
this.event.mouse_move((movement, cartesian) => {
movPos = movement.endPosition
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.options.start.lng = positions.lng
this.options.start.lat = positions.lat
this.options.start.alt = positions.alt
let cartographic = Cesium.Cartographic.fromDegrees(this.options.start.lng, this.options.start.lat, this.options.start.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = this.options.start.lng
})
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = this.options.start.lat
})
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = this.options.start.alt
})
this.tip.setPosition(
cartesian,
movement.endPosition.x,
movement.endPosition.y
)
})
this.event.mouse_left((movement, cartesian) => {
if (!movPos || movPos.x !== movement.position.x || movPos.y !== movement.position.y - 2) {
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.options.start.lng = positions.lng
this.options.start.lat = positions.lat
this.options.start.alt = positions.alt
}
this.entity.position = { lng: this.options.start.lng, lat: this.options.start.lat, alt: this.options.start.alt }
this.previous = {
positions: { ...this.entity.position }
}
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
this.event.gesture_pinck_start(() => { })
this.event.gesture_pinck_end(() => { })
this.positionEditing = false
})
this.event.mouse_right((movement, cartesian) => {
this.options.start.lng = this.entity.position.lng
this.options.start.lat = this.entity.position.lat
this.options.start.alt = this.entity.position.alt
this.positionEditing = false
})
this.event.gesture_pinck_start((movement, cartesian) => {
let startTime = new Date()
this.event.gesture_pinck_end(() => {
let endTime = new Date()
if (endTime - startTime >= 500) {
// 长按取消
this.options.lng = this.entity.position.lng
this.options.lat = this.entity.position.lat
this.options.alt = this.entity.position.alt
this.positionEditing = false
}
else {
let positions = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
this.options.lng = positions.lng
this.options.lat = positions.lat
this.options.alt = positions.alt
this.entity.position = { lng: this.options.lng, lat: this.options.lat, alt: this.options.alt }
this.previous = {
positions: { ...this.entity.position }
}
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
this.event.gesture_pinck_start(() => { })
this.event.gesture_pinck_end(() => { })
this.positionEditing = false
}
})
})
}
else {
this.picking = true
if (this.event) {
this.event.mouse_move(() => { })
this.event.mouse_left(() => { })
this.event.mouse_right(() => { })
this.event.gesture_pinck_start(() => { })
this.event.gesture_pinck_end(() => { })
}
this.tip && this.tip.destroy()
if (!this.sdk || !this.sdk.viewer || !this.entity) {
return
}
this.options.start.lng = this.entity.position.lng
this.options.start.lat = this.entity.position.lat
this.options.start.alt = this.entity.position.alt
let cartographic = Cesium.Cartographic.fromDegrees(this.options.start.lng, this.options.start.lat, this.options.start.alt);
let position = this.sdk.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
this.entity.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = this.options.start.lng
})
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = this.options.start.lat
})
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = this.options.start.alt
})
}
}
get positionEditing() {
return this.operate.positionEditing
}
static EventBinding(that, elements) {
for (let i = 0; i < elements.length; i++) {
let Event = []
let isEvent = false
let removeName = []
if (!elements[i] || !elements[i].attributes) {
continue
}
for (let m of elements[i].attributes) {
switch (m.name) {
case '@model': {
isEvent = true
if (elements[i].type == 'checkbox') {
Event.push((e) => { that[m.value] = e.target.checked })
elements[i].checked = that[m.value]
}
else {
Event.push((e) => {
let value = e.target.value
if (e.target.type == 'number') {
if (e.data != '.' && (e.data != '-' || 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)
}
that[m.value] = value
}
}
else {
that[m.value] = value
}
})
if (elements[i].nodeName == 'IMG') {
elements[i].src = that[m.value]
}
else {
elements[i].value = that[m.value]
}
}
if (that._elms[m.value]) {
that._elms[m.value].push(elements[i])
}
else {
that._elms[m.value] = [elements[i]]
}
removeName.push(m.name)
break;
}
case '@click': {
elements[i].addEventListener('click', (e) => {
if (typeof (that[m.value]) === 'function') {
that[m.value](e)
}
});
removeName.push(m.name)
// elements[i].attributes.removeNamedItem(m.name)
break;
}
case '@change': {
isEvent = true
Event.push((e) => {
let value = e.target.value
if (e.target.type == 'number' && value != '') {
value = Number(value)
e.target.value = value
}
if (typeof (that[m.value]) === 'function') {
that[m.value](e, value)
}
})
break;
}
}
// elements[i].attributes[m] = undefined
}
for (let n = 0; n < removeName.length; n++) {
elements[i].attributes.removeNamedItem(removeName[n])
}
if (isEvent) {
let ventType = 'input'
if (elements[i].tagName != 'INPUT' || elements[i].type == 'checkbox') {
ventType = 'change'
}
elements[i].addEventListener(ventType, (e) => {
for (let t = 0; t < Event.length; t++) {
Event[t](e)
}
});
}
}
}
flicker() { }
}
export default Spout

View File

@ -0,0 +1,115 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row" style="align-items: flex-start;">
<div class="col">
<span class="label" style="flex: 0 0 56px;">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col" style="flex: 0 0 60%;">
<div class="row">
<div class="col input-select-unit-box">
<span class="label" style="margin-right: 0px;">投影面积:</span>
<input class="input input-text" readonly="readonly" type="text" @model="area">
<div class="input-select-unit"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">动画时长</span>
<div class="input-number input-number-unit-3">
<input class="input blur" type="number" title="" min="500" max="9999999" @model="spreadTime">
<span class="unit">ms</span>
<span class="arrow"></span>
</div>
</div>
<div class="col" style="flex: 0 0 60%;">
<div class="row">
<div class="col">
<span class="label">动画</span>
<input class="btn-switch" type="checkbox" @model="spreadState">
</div>
<div class="col">
<span class="label">动画重复</span>
<input class="btn-switch" type="checkbox" @model="loop">
</div>
</div>
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<DIV-cy-tabs id="pincer-arrow-object-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="空间信息">
<div class="row">
<div class="col height-mode-box">
<span class="label" style="flex: 0 0 56px;">高度模式</span>
<div class="height-mode"></div>
</div>
<div class="col">
<span class="label">Z值统一增加</span>
<div class="input-number input-number-unit-1 height-box">
<input class="input height" type="number" title="" min="-9999999" max="999999999">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
<button class="confirm height-confirm" style="margin-left: 5px;">确认</button>
</div>
</div>
<div class="row">
<div class="table spatial-info-table">
<div class="table-head">
<div class="tr">
<div class="th"></div>
<div class="th">经度X</div>
<div class="th">纬度Y</div>
<div class="th">高度Z</div>
</div>
</div>
<div class="table-body">
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="面风格">
<div class="row">
<div class="col">
<span class="label">面颜色</span>
<div class="color"></div>
</div>
<div class="col">
<span class="label">边线颜色</span>
<div class="lineColor"></div>
</div>
<div class="col">
<span class="label">边线宽度</span>
<div class="input-number input-number-unit-2" style="width: 80px;">
<input class="input" type="number" title="" min="0" max="99" @model="lineWidth">
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
</DIV-cy-tabs>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,93 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row" style="align-items: flex-start;">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col" style="flex: 0 0 60%;">
<div class="row">
<div class="col input-select-unit-box">
<span class="label" style="margin-right: 0px;">投影面积:</span>
<input class="input input-text" readonly="readonly" type="text" @model="area">
<div class="input-select-unit"></div>
</div>
</div>
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<DIV-cy-tabs id="polygon-object-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="空间信息">
<div class="row">
<div class="col height-mode-box">
<span class="label" style="flex: 0 0 56px;">高度模式</span>
<div class="height-mode"></div>
</div>
<div class="col">
<span class="label">Z值统一增加</span>
<div class="input-number input-number-unit-1 height-box">
<input class="input height" type="number" title="" min="-9999999" max="999999999">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
<button class="confirm height-confirm" style="margin-left: 5px;">确认</button>
</div>
</div>
<div class="row">
<div class="table spatial-info-table">
<div class="table-head">
<div class="tr">
<div class="th"></div>
<div class="th">经度X</div>
<div class="th">纬度Y</div>
<div class="th">高度Z</div>
</div>
</div>
<div class="table-body">
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="面风格">
<div class="row">
<div class="col">
<span class="label">面颜色</span>
<div class="color"></div>
</div>
<div class="col">
<span class="label">描边颜色</span>
<div class="lineColor"></div>
</div>
<div class="col">
<span class="label">描边宽度</span>
<div class="input-number input-number-unit-2">
<input class="input" type="number" title="" min="0" max="99" @model="lineWidth">
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
</DIV-cy-tabs>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,60 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col" style="flex: 0 0 60%;">
<div class="row">
<div class="col input-select-unit-box">
<span class="label" style="margin-right: 0px;">投影面积:</span>
<input class="input input-text" readonly="readonly" type="text" @model="area">
<div class="input-select-unit"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">多面体颜色</span>
<div class="color"></div>
</div>
<div class="col" style="flex: 0 0 60%;">
<span class="label">多面体高度</span>
<div class="input-number input-number-unit-1" style="width: 80px;">
<input class="input" type="number" title="" min="0" max="9999999" data-null data-min="0.01" @model="height">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<!-- <div class="col">
<span class="label">拉伸高度</span>
<input class="input" type="number" title="" min="0" max="9999999" @model="extrudedHeight">
</div> -->
</div>
</div>
<div class="div-item">
<div class="row">
<DIV-cy-tabs id="polygon-object-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
</DIV-cy-tabs>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,142 @@
class eventBinding {
constructor() {
this.element = {}
}
static event = {}
getEvent(name) {
return eventBinding.event[name]
}
getEventAll() {
return eventBinding.event
}
setEvent(name, event) {
eventBinding.event[name] = event
}
on(that, elements) {
for (let i = 0; i < elements.length; i++) {
let Event = []
let isEvent = false
let removeName = []
let blurEvent = () => { }
if (!elements[i] || !elements[i].attributes) {
continue
}
for (let m of elements[i].attributes) {
switch (m.name) {
case '@model': {
isEvent = true
if (elements[i].type == 'checkbox') {
Event.push((e) => { that[m.value] = e.target.checked })
elements[i].checked = that[m.value]
}
else {
Event.push((e) => {
let value = e.target.value
if (e.target.type == 'number') {
let str = e.target.value + ''
if (e.data != '.' && (e.data != '-' || e.target.value) && !(str.charAt(str.length - 1) == '0' && e.target.value.toString().includes('.')) && e.target.value != '0') {
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)
}
if (e.target.dataset.min !== 'undefined' && e.target.dataset.min !== '') {
let min = Number(e.target.dataset.min)
if(value<min) {
value = min
}
}
that[m.value] = value
}
}
else {
that[m.value] = value
}
})
blurEvent = (e) => {
let value = e.target.value
if ((e.target.type == 'number') && (e.target.value || (e.target.dataset.null !== 'undefined' && e.target.dataset.null !== '' && !Boolean(e.target.dataset.null)))) {
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)
}
if ((e.target.dataset.min) && value < Number(e.target.dataset.min)) {
value = Number(e.target.dataset.min)
}
}
that[m.value] = value
}
if(elements[i].nodeName=='IMG') {
elements[i].src = that[m.value]
}
else {
elements[i].value = that[m.value]
}
}
if(this.element[m.value]) {
this.element[m.value].push(elements[i])
}
else {
this.element[m.value] = [elements[i]]
}
removeName.push(m.name)
break;
}
case '@click': {
elements[i].addEventListener('click', (e) => {
if (typeof (that[m.value]) === 'function') {
that[m.value](e)
}
});
removeName.push(m.name)
// elements[i].attributes.removeNamedItem(m.name)
break;
}
case '@change': {
isEvent = true
Event.push((e) => {
let value = e.target.value
if(e.target.type == 'number' && value!='') {
value = Number(value)
e.target.value = value
}
if (typeof (that[m.value]) === 'function') {
that[m.value](e, value)
}
})
break;
}
}
// elements[i].attributes[m] = undefined
}
for(let n=0;n<removeName.length;n++) {
elements[i].attributes.removeNamedItem(removeName[n])
}
if (isEvent) {
let ventType = 'input'
if (elements[i].tagName != 'INPUT' || elements[i].type == 'checkbox') {
ventType = 'change'
}
elements[i].addEventListener(ventType, (e) => {
for (let t = 0; t < Event.length; t++) {
Event[t](e)
}
});
elements[i].addEventListener('blur', blurEvent)
}
}
}
}
const EventBinding = new eventBinding();
export default EventBinding;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,62 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col">
<div class="row">
<div class="col">
<span class="label" style="margin-right: 0px;">投影面积:</span>
<input class="input input-text" readonly="readonly" type="text" @model="area">
<div class="input-select-unit"></div>
</div>
</div>
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<DIV-cy-tabs id="polygon-object-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="多面体风格">
<div class="row">
<div class="col">
<span class="label">多面体颜色</span>
<div class="color"></div>
</div>
<div class="col">
<span class="label">多面体高度</span>
<div class="input-number input-number-unit-1" style="width: 80px;">
<input class="input" type="number" title="" min="0" max="9999999" @model="height">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<!-- <span class="label">拉伸高度</span>
<input class="input" type="number" title="" min="0" max="9999999" @model="extrudedHeight"> -->
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
</DIV-cy-tabs>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,114 @@
class eventBinding {
constructor() {
this.element = {}
}
static event = {}
getEvent(name) {
return eventBinding.event[name]
}
getEventAll() {
return eventBinding.event
}
setEvent(name, event) {
eventBinding.event[name] = event
}
on(that, elements) {
for (let i = 0; i < elements.length; i++) {
let Event = []
let isEvent = false
let removeName = []
for (let m of elements[i].attributes) {
switch (m.name) {
case '@model': {
isEvent = true
if (elements[i].type == 'checkbox') {
Event.push((e) => { that[m.value] = e.target.checked })
elements[i].checked = that[m.value]
}
else {
Event.push((e) => {
let value = e.target.value
if (e.target.type == 'number') {
if (e.data != '.' && (e.data != '-' || 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)
}
that[m.value] = value
}
}
else {
that[m.value] = value
}
})
if(elements[i].nodeName=='IMG') {
elements[i].src = that[m.value]
}
else {
elements[i].value = that[m.value]
}
}
if(this.element[m.value]) {
this.element[m.value].push(elements[i])
}
else {
this.element[m.value] = [elements[i]]
}
removeName.push(m.name)
break;
}
case '@click': {
elements[i].addEventListener('click', (e) => {
if (typeof (that[m.value]) === 'function') {
that[m.value](e)
}
});
removeName.push(m.name)
// elements[i].attributes.removeNamedItem(m.name)
break;
}
case '@change': {
isEvent = true
Event.push((e) => {
let value = e.target.value
if(e.target.type == 'number' && value!='') {
value = Number(value)
e.target.value = value
}
if (typeof (that[m.value]) === 'function') {
that[m.value](e, value)
}
})
break;
}
}
// elements[i].attributes[m] = undefined
}
for(let n=0;n<removeName.length;n++) {
elements[i].attributes.removeNamedItem(removeName[n])
}
if (isEvent) {
let ventType = 'input'
if (elements[i].tagName != 'INPUT' || elements[i].type == 'checkbox') {
ventType = 'change'
}
elements[i].addEventListener(ventType, (e) => {
for (let t = 0; t < Event.length; t++) {
Event[t](e)
}
});
}
}
}
}
const EventBinding = new eventBinding();
export default EventBinding;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,168 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row" style="align-items: flex-start;">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col" style="flex: 0 0 56%;">
<div>
<div class="row">
<div class="col input-select-unit-box">
<div class="input-select-unit"></div>
<input class="input input-text" readonly="readonly" type="text" style="flex: 0 0 130px;" @model="length">
<div class="input-select-unit"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<DIV-cy-tabs id="polyline-object-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="空间信息">
<div class="row">
<div class="col height-mode-box">
<span class="label" style="flex: 0 0 56px;">高度模式</span>
<div class="height-mode"></div>
</div>
<div class="col">
<span class="label">Z值统一增加</span>
<div class="input-number input-number-unit-1 height-box">
<input class="input height" type="number" title="" min="-9999999" max="999999999">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
<button class="confirm height-confirm" style="margin-left: 5px;">应用</button>
</div>
</div>
<div class="row">
<div class="table spatial-info-table">
<div class="table-head">
<div class="tr">
<div class="th"></div>
<div class="th">经度X</div>
<div class="th">纬度Y</div>
<div class="th">高度Z</div>
</div>
</div>
<div class="table-body">
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="线条风格">
<div class="row">
<div class="col">
<span class="label">线条颜色</span>
<div class="color"></div>
</div>
<div class="col" style="flex: 0 0 33%;">
<span class="label">线条宽度</span>
<div class="input-number input-number-unit-1" style="width: 80px;">
<input class="input" type="number" title="" min="1" max="999" @model="lineWidth">
<span class="unit">px</span>
<span class="arrow"></span>
</div>
</div>
<div class="col input-select-line-type-box" style="flex: 0 0 37%;">
<span class="label">线条形式</span>
<div class="input-select-line-type"></div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">首尾相连</span>
<input class="btn-switch" type="checkbox" @model="noseToTail">
</div>
<div class="col" style="flex: 0 0 33%;">
<span class="label">线段圆滑</span>
<input class="btn-switch" type="checkbox" @model="smooth">
</div>
<div class="col" style="flex: 0 0 37%;">
</div>
</div>
<div class="row">
<div class="col">
<span class="label">线段缓冲</span>
<input class="btn-switch" type="checkbox" @model="extend">
</div>
<div class="col" style="flex: 0 0 33%;">
<span class="label">缓冲宽度</span>
<div class="input-number input-number-unit-1" style="width: 80px;">
<input class="input" type="number" title="" min="0" data-min="0.01" max="999999" @model="extendWidth">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col" style="flex: 0 0 37%;">
<span class="label">缓冲颜色</span>
<div class="extendColor"></div>
</div>
</div>
<div class="row" id="dashTextureDom">
<div class="col">
<span class="label">首尾反向</span>
<input class="btn-switch" type="checkbox" @model="rotate">
</div>
<div class="col" style="flex: 0 0 33%;">
<span class="label">流动速率</span>
<div class="input-number input-number-unit-1" style="width: 80px;">
<input class="input" type="number" title="" min="0" max="999999" step="1" @model="speed">
<span class="arrow"></span>
</div>
</div>
<div class="col" style="flex: 0 0 37%;">
<span class="label lineSpace">线条间距</span>
<div class="input-number input-number-unit-1 lineSpace" style="width: 80px;">
<input class="input" type="number" title="" min="0" max="4.5" step="0.1" @model="space">
<span class="unit">倍</span>
<span class="arrow"></span>
</div>
</div>
</div>
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
<!-- <DIV-cy-tab-pane label="灯光控制">-->
<!-- <div>-->
<!-- <div class="row">-->
<!-- <div class="col">-->
<!-- <span class="label">指令</span>-->
<!-- <input class="input" type="text" @model="instruct">-->
<!-- <button class="primary" @click="instructSubmit">提交</button>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </DIV-cy-tab-pane>-->
<!-- <DIV-cy-tab-pane label="设置操作点">-->
<!-- <div>-->
<!-- <div class="row">-->
<!-- <div class="col">-->
<!-- <span class="label">设置操作点</span>-->
<!-- <input class="input" type="text" @model="operatingPoint">-->
<!-- <button class="primary" @click="operatingPointSubmit">提交</button>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </DIV-cy-tab-pane>-->
</DIV-cy-tabs>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

View File

@ -0,0 +1,122 @@
class eventBinding {
constructor() {
this.element = {}
}
static event = {}
getEvent(name) {
return eventBinding.event[name]
}
getEventAll() {
return eventBinding.event
}
setEvent(name, event) {
eventBinding.event[name] = event
}
on(that, elements) {
for (let i = 0; i < elements.length; i++) {
let Event = []
let isEvent = false
let removeName = []
if (!elements[i] || !elements[i].attributes) {
continue
}
for (let m of elements[i].attributes) {
switch (m.name) {
case '@model': {
isEvent = true
if (elements[i].type == 'checkbox') {
Event.push((e) => { that[m.value] = e.target.checked })
elements[i].checked = that[m.value]
}
else {
Event.push((e) => {
let value = e.target.value
if (e.target.type == 'number') {
if (e.data != '.' && (e.data != '-' || e.target.value)) {
value = Number(value)
if ((e.target.max) && value > Number(e.target.max)) {
value = Number(e.target.max)
e.target.value = value
}
if ((e.target.min) && value < Number(e.target.min)) {
value = Number(e.target.min)
e.target.value = value
}
if ((e.target.dataset.min) && value < Number(e.target.dataset.min)) {
value = Number(e.target.dataset.min)
}
that[m.value] = value
}
}
else {
that[m.value] = value
}
})
if (elements[i].nodeName == 'IMG') {
elements[i].src = that[m.value]
}
else {
elements[i].value = that[m.value]
}
}
if (this.element[m.value]) {
this.element[m.value].push(elements[i])
}
else {
this.element[m.value] = [elements[i]]
}
removeName.push(m.name)
break;
}
case '@click': {
elements[i].addEventListener('click', (e) => {
if (typeof (that[m.value]) === 'function') {
that[m.value](e)
}
});
removeName.push(m.name)
// elements[i].attributes.removeNamedItem(m.name)
break;
}
case '@change': {
isEvent = true
Event.push((e) => {
let value = e.target.value
if (e.target.type == 'number' && value != '') {
value = Number(value)
e.target.value = value
}
if (typeof (that[m.value]) === 'function') {
that[m.value](e, value)
}
})
break;
}
}
// elements[i].attributes[m] = undefined
}
for (let n = 0; n < removeName.length; n++) {
elements[i].attributes.removeNamedItem(removeName[n])
}
if (isEvent) {
let ventType = 'input'
if (elements[i].tagName != 'INPUT' || elements[i].type == 'checkbox') {
ventType = 'change'
}
elements[i].addEventListener(ventType, (e) => {
for (let t = 0; t < Event.length; t++) {
Event[t](e)
}
});
}
}
}
}
const EventBinding = new eventBinding();
export default EventBinding;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,67 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col">
<span class="label">扫描颜色</span>
<div class="color"></div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" min="-180" max="180" @model="lng">
</div>
<div class="col">
<span class="label">扫描半径</span>
<div class="input-number input-number-unit-2 input-radius">
<input class="input" type="number" title="" data-min="0.1" max="999999">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
<div class="input-radius-unit-box" style="flex: 0 0 60px;">
<div class="input-radius-unit"></div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-90" max="90" @model="lat">
</div>
<div class="col">
<span class="label">扫描速度</span>
<input class="input" type="number" title="" min="0" max="100" @model="speed">
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<DIV-cy-tabs id="radar-scan-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
</DIV-cy-tabs>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,91 @@
import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../Element/elm_html'
function html(that) {
return `
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" @model="name">
</div>
<div class="col">
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" min="-180" max="180" @model="lng">
</div>
<div class="col">
<span class="label">扩散半径</span>
<div class="input-number input-number-unit-2 input-radius">
<input class="input" type="number" title="" data-min="0.1" max="999999">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
<div class="input-radius-unit-box" style="flex: 0 0 60px;">
<div class="input-radius-unit"></div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-90" max="90" @model="lat">
</div>
<div class="col">
<span class="label">持续时间</span>
<div class="input-number input-number-unit-2">
<input class="input" type="number" title="" min="100" max="99999" @model="duration">
<span class="unit">ms</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="-9999999" max="999999999" @model="alt">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<div class="row">
<div class="col">
<span class="label">范围颜色</span>
<div class="colorOut"></div>
</div>
<div class="col">
<span class="label">扫描颜色</span>
<div class="colorIn"></div>
</div>
</div>
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<DIV-cy-tabs id="radar-scan-edit-tabs">
<DIV-cy-tab-pane label="属性信息">
${attributeElm(that)}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标注风格">
${labelStyleElm1()}
</DIV-cy-tab-pane>
<DIV-cy-tab-pane label="标签风格">
${labelStyleElm2()}
</DIV-cy-tab-pane>
</DIV-cy-tabs>
</div>
</div>
<span class="custom-divider"></span>
`
}
export { html }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,124 @@
import Tools from "../../../Tools";
function init_material() {
let _that = this
let tools = new Tools()
if (typeof Cesium !== 'undefined') (function (Cesium) {
/**
* 自定义材质线Property 适用于entity和primitive材质
* @param {object} options
* @param source {string} glsl的shader代码
* @param options.image {string} 图片地址
*/
function RoadMaterialProperty(options = {}, source) {
var Color = Cesium.Color,
defaultValue = Cesium.defaultValue,
defineProperties = Object.defineProperties,
Event = Cesium.Event,
createPropertyDescriptor = Cesium.createPropertyDescriptor,
Property = Cesium.Property,
Material = Cesium.Material,
MaterialType = options.MaterialType || 'wallType' + parseInt(Math.random() * 1000);
// 创建自定义动态材质对象
function PolylineCustomMaterialProperty(options = {}) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
// 定义内置属性
this._definitionChanged = new Event();
this._color = undefined;
this._colorSubscription = undefined;
this._repeat = undefined;
this._repeatSubscription = undefined;
this._rotate = undefined;
this._rotateSubscription = undefined;
this.image = options.image;
this.color = new Cesium.Color.fromCssColorString(options.color || "rgba(4,253,231,0.87)");
this.repeat = options.repeat;
this.rotate = options.rotate;
this.duration = (options.duration || options.duration===0) ? options.duration : 1000
this._time = new Date().getTime();
}
// 定义材质对象默认属性
defineProperties(PolylineCustomMaterialProperty.prototype, {
isvarant: {
get: function () {
return false;
}
},
definitionChanged: {
get: function () {
return this._definitionChanged;
}
},
repeat: Cesium.createPropertyDescriptor('repeat'),
rotate: Cesium.createPropertyDescriptor('rotate'),
color: createPropertyDescriptor('color')
});
// 材质对象需要有type函数 value函数 equals函数
PolylineCustomMaterialProperty.prototype.getType = function (time) {
return MaterialType;
};
PolylineCustomMaterialProperty.prototype.getValue = function (time, result) {
if (!Cesium.defined(result)) {
result = {};
}
result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color);
result.time = this.duration ? ((new Date().getTime() - this._time) % this.duration) / this.duration : 0;
result.image = this.image;
result.repeat = Cesium.Property.getValueOrDefault(this.repeat);
result.rotate = Cesium.Property.getValueOrDefault(this.rotate);
return result;
};
PolylineCustomMaterialProperty.prototype.equals = function (other) {
return this === other || //
(other instanceof PolylineCustomMaterialProperty &&
Property.equals(this._color, other._color)) &&
Property.equals(this.repeat, other._repeat) &&
Property.equals(this.rotate, other._rotate)
};
// 将定义的材质对象添加到cesium的材质队列中
Material._materialCache.addMaterial(MaterialType, {
fabric: {
type: MaterialType,
uniforms: {
color: new Cesium.Color(1.0, 1.0, 1.0, 1),
image: options.image || tools.getSourceRootPath() + "/img/material/arrow.png",
time: options.time || 0,
repeat: new Cesium.Cartesian2(100.0, 100.0),
rotate: 0,
},
// 动态材质shader
source: `
czm_material czm_getMaterial(czm_materialInput materialInput)
{
czm_material material = czm_getDefaultMaterial(materialInput);
mat2 rotationMatrix = mat2(cos(radians(rotate)), sin(radians(rotate)), -sin(radians(rotate)), cos(radians(rotate)));
vec2 st = repeat * materialInput.st*rotationMatrix;
vec4 colorImage = texture2D(image, vec2(fract(st.s - time), st.t));
material.alpha = colorImage.a;
material.diffuse = colorImage.rgb*1.0;
return material;
}`,
components: {
specular: 10.0,
diffuse: "vec3(0.5)"
},
},
// 透明
translucent: function (material) {
return true;
}
})
return new PolylineCustomMaterialProperty(options);
}
Cesium.RoadMaterialProperty = RoadMaterialProperty;
})(Cesium);
}
export { init_material }

386
src/Obj/Base/Road/index.js Normal file
View File

@ -0,0 +1,386 @@
import Base from "../index";
import PolylineImageTrailMaterialProperty from "../../Materail/PolylineImageTrailMaterialProperty";
class Corridor extends Base {
// /**
// * @constructor
// * @description 道路
// * @param sdk
// * @param options {object} 属性
// * @param options.name{string} 名称
// * @param options.image{string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} 指定 Image、URL、Canvas 或 Video 的属性
// * @param options.width=10{number} 宽度
// * @param options.height=0{number} 高度
// * */
constructor(sdk, options = {}) {
super(sdk, options);
this.options.name = options.name || ''
this.options.image = options.image
this.options.width = options.width || 10
this.options.height = options.height || 0
}
create(positions) {
this.computeRoad(positions)
let fromDegreesArray = []
for (let i = 0; i < positions.length; i++) {
fromDegreesArray.push(positions[i].lng, positions[i].lat)
}
let length = this.computeDistance2(positions)
let geometry = new Cesium.CorridorGeometry({
positions: Cesium.Cartesian3.fromDegreesArray(fromDegreesArray),
width: this.options.width,
height: this.options.height,
cornerType: Cesium.CornerType.MITERED,
vertexFormat: Cesium.MaterialAppearance.MaterialSupport.ALL.vertexFormat
})
// console.log(Cesium.CorridorGeometry.createGeometry(geometry))
// this.entity = this.sdk.viewer.scene.primitives.add(new Cesium.Primitive({//GroundPrimitive贴地
// geometryInstances: new Cesium.GeometryInstance({
// geometry: geometry,
// attributes: {
// color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 1.0, 1.0, 0.5))
// }
// }),
// appearance: new Cesium.MaterialAppearance({
// material: Cesium.Material.fromType('Image', {
// image: this.options.image,
// repeat: new Cesium.Cartesian2(length / this.options.width * 2, 1.0)
// }),
// faceForward: true,
// renderState: {
// blending: Cesium.BlendingState.ALPHA_BLEND
// }
// })
// }));
// console.log(this.entity, Outlinegeometry)
// this.entity = this.sdk.viewer.entities.add({
// name: "Red corridor on surface with rounded corners",
// corridor: {
// positions: Cesium.Cartesian3.fromDegreesArray(fromDegreesArray),
// width: this.options.width,
// height: 10,
// cornerType: Cesium.CornerType.MITERED,
// material: new Cesium.ImageMaterialProperty({
// image: this.options.image,
// repeat: new Cesium.Cartesian2(100, 1.0),
// color: Cesium.Color.TOMATO
// })
// }
// });
}
// 编辑框
async edit(state) { }
remove() {
this.sdk.viewer.scene.primitives.remove(this.entity)
this.entity = null
}
computeRoad(positions) {
let fromDegreesArray = []
for (let i = 0; i < positions.length; i++) {
fromDegreesArray.push(positions[i].lng, positions[i].lat)
}
let Outlinegeometry = new Cesium.CorridorGeometry({
positions: Cesium.Cartesian3.fromDegreesArray(fromDegreesArray),
width: this.options.width,
cornerType: Cesium.CornerType.MITERED,
vertexFormat: Cesium.MaterialAppearance.MaterialSupport.ALL.vertexFormat
})
let geometry = Cesium.CorridorGeometry.createGeometry(Outlinegeometry)
console.log(geometry)
let initposition = []
for (let i = 0; i < geometry.attributes.position.values.length; i += 3) {
console.log(geometry.attributes.position.values[i], geometry.attributes.position.values[i + 1], geometry.attributes.position.values[i + 2])
initposition.push(new Cesium.Cartesian3(geometry.attributes.position.values[i], geometry.attributes.position.values[i + 1], geometry.attributes.position.values[i + 2]))
}
console.log(initposition, Cesium.Cartesian3.fromDegrees(91.08567036051947, 24.990201656481236))
let flag = true
let bearing
this.entityArray = []
// 创建一个矩形实体,顶点坐标为世界坐标
const rectangle = this.sdk.viewer.entities.add({
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(-100.0, 20.0, -90.0, 30.0),
material: new Cesium.ImageMaterialProperty({
image: this.options.image,
repeat: new Cesium.Cartesian2(10, 1.0),
}),
},
});
for (let i = 0; i < geometry.indices.length; i += 3) {
// console.log(bearing)
let angleInDegrees
let theta
if (flag) {
let a = this.cartesian3Towgs84(initposition[geometry.indices[i]], this.sdk.viewer)
let b = this.cartesian3Towgs84(initposition[geometry.indices[i + 2]], this.sdk.viewer)
let point1 = turf.point([a.lng, a.lat]);
let point2 = turf.point([b.lng, b.lat]);
bearing = turf.bearing(point1, point2);
// 计算两点之间的角度
let angle = Cesium.Cartesian3.angleBetween(initposition[geometry.indices[i]], initposition[geometry.indices[i + 2]]);
// 转换角度为角度而不是弧度
angleInDegrees = Cesium.Math.toDegrees(angle)
//以a点为原点建立局部坐标系东方向为x轴,北方向为y轴,垂直于地面为z轴得到一个局部坐标到世界坐标转换的变换矩阵
let localToWorld_Matrix = Cesium.Transforms.eastNorthUpToFixedFrame(initposition[geometry.indices[i]]);
//求世界坐标到局部坐标的变换矩阵
let worldToLocal_Matrix = Cesium.Matrix4.inverse(localToWorld_Matrix, new Cesium.Matrix4());
//a点在局部坐标的位置其实就是局部坐标原点
let localPosition_A = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, initposition[geometry.indices[i]], new Cesium.Cartesian3());
//B点在以A点为原点的局部的坐标位置
let localPosition_B = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, initposition[geometry.indices[i + 2]], new Cesium.Cartesian3());
//弧度
let angle2 = Cesium.Math.fastApproximateAtan2((localPosition_B.y - localPosition_A.y), (localPosition_B.x - localPosition_A.x))
//角度
theta = angle2 * (180 / Cesium.Math.PI);
}
else {
let a = this.cartesian3Towgs84(initposition[geometry.indices[i + 1]], this.sdk.viewer)
let b = this.cartesian3Towgs84(initposition[geometry.indices[i + 2]], this.sdk.viewer)
let point1 = turf.point([a.lng, a.lat]);
let point2 = turf.point([b.lng, b.lat]);
bearing = turf.bearing(point1, point2);
// 计算两点之间的角度
let angle = Cesium.Cartesian3.angleBetween(initposition[geometry.indices[i + 1]], initposition[geometry.indices[i + 2]]);
// 转换角度为角度而不是弧度
angleInDegrees = Cesium.Math.toDegrees(angle)
//以a点为原点建立局部坐标系东方向为x轴,北方向为y轴,垂直于地面为z轴得到一个局部坐标到世界坐标转换的变换矩阵
let localToWorld_Matrix = Cesium.Transforms.eastNorthUpToFixedFrame(initposition[geometry.indices[i + 1]]);
//求世界坐标到局部坐标的变换矩阵
let worldToLocal_Matrix = Cesium.Matrix4.inverse(localToWorld_Matrix, new Cesium.Matrix4());
//a点在局部坐标的位置其实就是局部坐标原点
let localPosition_A = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, initposition[geometry.indices[i + 1]], new Cesium.Cartesian3());
//B点在以A点为原点的局部的坐标位置
let localPosition_B = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, initposition[geometry.indices[i + 2]], new Cesium.Cartesian3());
//弧度
let angle2 = Cesium.Math.fastApproximateAtan2((localPosition_B.y - localPosition_A.y), (localPosition_B.x - localPosition_A.x))
//角度
theta = angle2 * (180 / Cesium.Math.PI);
}
let point1 = Cesium.Cartesian3.fromDegrees(91, 24.990201656481236);
let point2 = Cesium.Cartesian3.fromDegrees(91, 24.626517401118033);
// 计算两点之间的角度
let angle = Cesium.Cartesian3.angleBetween(point1, point2);
// 转换角度为角度而不是弧度
let xx = Cesium.Math.toDegrees(angle)
flag = !flag
bearing = bearing - 90 + 0.145
console.log(bearing, angleInDegrees, angle, xx, theta)
//以a点为原点建立局部坐标系东方向为x轴,北方向为y轴,垂直于地面为z轴得到一个局部坐标到世界坐标转换的变换矩阵
let localToWorld_Matrix = Cesium.Transforms.eastNorthUpToFixedFrame(point1);
//求世界坐标到局部坐标的变换矩阵
let worldToLocal_Matrix = Cesium.Matrix4.inverse(localToWorld_Matrix, new Cesium.Matrix4());
//a点在局部坐标的位置其实就是局部坐标原点
let localPosition_A = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, point1, new Cesium.Cartesian3());
//B点在以A点为原点的局部的坐标位置
let localPosition_B = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, point2, new Cesium.Cartesian3());
//弧度
let angle2 = Cesium.Math.fastApproximateAtan2((localPosition_B.z - localPosition_A.z), (localPosition_B.x - localPosition_A.x))
//角度
let theta2 = angle2 * (180 / Cesium.Math.PI);
// alert(theta2)
// let entity = this.sdk.viewer.entities.add({
// show: this.options.show,
// polygon: {
// hierarchy: new Cesium.PolygonHierarchy([initposition[geometry.indices[i]], initposition[geometry.indices[i + 1]], initposition[geometry.indices[i + 2]]]),
// perPositionHeight: false,
// // material: new PolylineImageTrailMaterialProperty({
// // image: this.options.image,
// // repeat: new Cesium.Cartesian2(10, 1.0),
// // color: Cesium.Color.TOMATO,
// // rotate: 0
// // }),
// material: new Cesium.ImageMaterialProperty({
// image: this.options.image,
// repeat: new Cesium.Cartesian2(1000, 1.0),
// }),
// stRotation: Cesium.Math.toRadians(theta - 90 - 0.0128),
// outline: true,
// outlineColor: Cesium.Color.BLACK,
// }
// })
let aa = 0
const shader = `
uniform sampler2D image;
uniform vec4 color;
uniform vec2 repeat;
czm_material czm_getMaterial(czm_materialInput materialInput){
czm_material material=czm_getDefaultMaterial(materialInput);
mat2 rotationMatrix = mat2(cos(radians(-rotate)), sin(radians(-rotate)), -sin(radians(-rotate)), cos(radians(-rotate)));
vec2 st=repeat*materialInput.st*rotationMatrix;
float time=fract(czm_frameNumber);
vec4 colorImage=texture2D(image,vec2(fract(st.s-time),st.t));
material.alpha=colorImage.a;
material.diffuse=colorImage.rgb;
return material;
}`
console.log(Cesium.Math.toRadians(theta - 90))
let entity = this.sdk.viewer.scene.primitives.add(new Cesium.GroundPrimitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy([initposition[geometry.indices[i]], initposition[geometry.indices[i + 1]], initposition[geometry.indices[i + 2]]]),
}),
}),
appearance: new Cesium.EllipsoidSurfaceAppearance({
aboveGroud: true,
material: new Cesium.Material({
fabric: {
uniforms: {
color: new Cesium.Color(1.0, 0.0, 0.0, 0.1),
image: this.options.image,
repeat: new Cesium.Cartesian2(1000, 1.0),
rotate: 0
},
source: shader
},
}),
}),
}));
// console.log(entity)
// let geometryInstances2 = new Cesium.GeometryInstance({
// geometry: new Cesium.PolygonGeometry({
// polygonHierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray([100, 1, 101, 1, 101, -1, 100, -1])),
// }),
// })
// let entity2 = this.sdk.viewer.scene.primitives.add(new Cesium.GroundPrimitive({
// geometryInstances: geometryInstances2,
// appearance: new Cesium.EllipsoidSurfaceAppearance({
// aboveGroud: true,
// material: new Cesium.Material({
// fabric: {
// uniforms: {
// color: new Cesium.Color(1.0, 0.0, 0.0, 0.1),
// image: this.options.image,
// repeat: new Cesium.Cartesian2(1000, 1.0),
// rotate: 0
// },
// source: shader
// },
// }),
// }),
// }));
// console.log(geometryInstances2)
// // 获取多边形的边界矩形
// let boundingSphere = geometryInstances2.geometry.boundingSphere;
// // 创建一个矩阵,它表示多边形的本地坐标到世界坐标的转换
// let matrix = Cesium.Transforms.eastNorthUpToFixedFrame(boundingSphere.center);
// console.log(entity2, matrix)
// setInterval(() => {
// }, 100);
this.entityArray.push(entity)
console.log(entity)
}
// let entity = this.sdk.viewer.entities.add({
// show: this.options.show,
// polygon: {
// hierarchy: new Cesium.PolygonHierarchy([
// new Cesium.Cartesian3(1201222.3498141132, 5794200.4246190665, 2372132.932514765),
// new Cesium.Cartesian3(1200929.6921250424, 5794615.962987943, 2371271.7244476764),
// new Cesium.Cartesian3(1199139.8791256004, 5794316.892300814, 2372896.7988495603)]),
// perPositionHeight: true,
// material: new PolylineImageTrailMaterialProperty({
// image: this.options.image,
// repeat: new Cesium.Cartesian2(10, 1.0),
// color: Cesium.Color.TOMATO,
// rotate: 0
// }),
// outline: true,
// outlineColor: Cesium.Color.BLACK,
// }
// })
// console.log(entity)
// 创建新材质
let newMaterial = new Cesium.Material({
fabric: {
type: 'Color',
uniforms: {
color: new Cesium.Color(1.0, 0.0, 0.0, 1.0) // 红色
}
}
});
console.log(newMaterial)
// this.entity = this.sdk.viewer.entities.add({
// show: this.options.show,
// polygon: {
// hierarchy: new Cesium.PolygonHierarchy(initposition),
// perPositionHeight: false,
// material: new Cesium.ImageMaterialProperty({
// image: this.options.image,
// repeat: new Cesium.Cartesian2(100, 1.0),
// color: Cesium.Color.AQUA
// })
// }
// })
for (let i = 0; i < initposition.length; i++) {
let entity = this.sdk.viewer.entities.add({
name: 'node-secondary-edit-point',
index: i,
position: initposition[i],
billboard: {
image: this.getSourceRootPath() + '/img/point.png',
width: 15,
height: 15,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
color: Cesium.Color.WHITE.withAlpha(0.99)
},
label: {
text: '' + i,
pixelOffset: { x: 0, y: -20 },
},
})
}
this.sdk.viewer.entities.add({
name: 'node-secondary-edit-point',
position: Cesium.Cartesian3.fromDegrees(91.08567036051947, 24.990201656481236),
billboard: {
image: this.getSourceRootPath() + '/img/point.png',
width: 15,
height: 15,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
color: Cesium.Color.WHITE.withAlpha(0.99)
},
})
this.sdk.viewer.entities.add({
name: 'node-secondary-edit-point',
position: Cesium.Cartesian3.fromDegrees(91.08588488854294, 24.626517401118033),
billboard: {
image: this.getSourceRootPath() + '/img/point.png',
width: 15,
height: 15,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
color: Cesium.Color.WHITE.withAlpha(0.99)
},
})
}
test(v) {
for (let i = 0; i < this.entityArray.length; i++) {
this.entityArray[i].polygon.stRotation = Cesium.Math.toRadians(v)
}
}
}
export default Corridor

Some files were not shown because too many files have changed in this diff Show More