From 484fe70e16dd9f5adb89514b0bb2ac57054bd579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=8F=E5=A4=A7=E8=83=86?= <1101282782@qq.com> Date: Thu, 3 Jul 2025 16:28:48 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E9=A3=9E=E7=BA=BF=EF=BC=8C=E5=85=89?= =?UTF-8?q?=E7=85=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Global/efflect/Sunshine/_element.js | 56 +++ src/Global/efflect/Sunshine/eventBinding.js | 92 ++++ src/Global/efflect/Sunshine/index.js | 224 +++++++++ src/Global/efflect/Sunshine/timeLIne.js | 133 +++++ src/In/index.js | 11 +- src/Obj/Base/FlowLine/_element.js | 76 +++ src/Obj/Base/FlowLine/eventBinding.js | 92 ++++ src/Obj/Base/FlowLine/index.js | 476 ++++++++++++++++++ src/Obj/Base/PolylineObject/index.js | 113 ++--- .../FlowDashedLineFlowMaterialProperty.js | 124 +++++ src/Obj/Materail/FlowLineMaterialProperty.js | 113 +++++ .../Materail/LineTextureMaterialProperty.js | 110 ++++ .../Materail/PolylineFlowMaterialProperty.js | 113 +++++ .../PolylineFlowMultMaterialProperty.js | 134 +++++ src/Obj/Materail/index.js | 12 +- src/Tools/index.js | 61 ++- static/custom/css/index.css | 85 +++- static/img/arrow/1.png | Bin 0 -> 17773 bytes static/img/arrow/2.png | Bin 0 -> 3317 bytes static/img/arrow/3.png | Bin 0 -> 10202 bytes static/img/arrow/4.png | Bin 0 -> 20367 bytes static/img/arrow/5.png | Bin 0 -> 56821 bytes static/img/arrow/6.png | Bin 0 -> 10767 bytes 23 files changed, 1959 insertions(+), 66 deletions(-) create mode 100644 src/Global/efflect/Sunshine/_element.js create mode 100644 src/Global/efflect/Sunshine/eventBinding.js create mode 100644 src/Global/efflect/Sunshine/index.js create mode 100644 src/Global/efflect/Sunshine/timeLIne.js create mode 100644 src/Obj/Base/FlowLine/_element.js create mode 100644 src/Obj/Base/FlowLine/eventBinding.js create mode 100644 src/Obj/Base/FlowLine/index.js create mode 100644 src/Obj/Materail/FlowDashedLineFlowMaterialProperty.js create mode 100644 src/Obj/Materail/FlowLineMaterialProperty.js create mode 100644 src/Obj/Materail/LineTextureMaterialProperty.js create mode 100644 src/Obj/Materail/PolylineFlowMaterialProperty.js create mode 100644 src/Obj/Materail/PolylineFlowMultMaterialProperty.js create mode 100644 static/img/arrow/1.png create mode 100644 static/img/arrow/2.png create mode 100644 static/img/arrow/3.png create mode 100644 static/img/arrow/4.png create mode 100644 static/img/arrow/5.png create mode 100644 static/img/arrow/6.png diff --git a/src/Global/efflect/Sunshine/_element.js b/src/Global/efflect/Sunshine/_element.js new file mode 100644 index 0000000..6d0a7d3 --- /dev/null +++ b/src/Global/efflect/Sunshine/_element.js @@ -0,0 +1,56 @@ +function html() { + return ` + +
+
+
+ 播放倍数 +
+ + +
+
+
+ 阴影柔和度 +
+ + +
+
+
+
+
+
+
+ 阴影优化 + +
+
+ 日期选择 + +
+
+
+ +
+
+
+
+
+
+
+
00:00:00
+
+
+
+
+ +
+
+
+
+ + ` +} + +export { html } diff --git a/src/Global/efflect/Sunshine/eventBinding.js b/src/Global/efflect/Sunshine/eventBinding.js new file mode 100644 index 0000000..6e1b840 --- /dev/null +++ b/src/Global/efflect/Sunshine/eventBinding.js @@ -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; diff --git a/src/Global/efflect/Sunshine/index.js b/src/Global/efflect/Sunshine/index.js new file mode 100644 index 0000000..115d39a --- /dev/null +++ b/src/Global/efflect/Sunshine/index.js @@ -0,0 +1,224 @@ +/** + * @description 水面 + */ +import Dialog from '../../../Obj/Element/Dialog'; +import { html } from "./_element"; +import EventBinding from '../../../Obj/Element/Dialog/eventBinding'; +import { syncData } from '../../MultiViewportMode' +import Tools from '../../../Tools' +import TimeLine from './TimeLine' +import { setSplitDirection, syncSplitData, setActiveId } from '../../SplitScreen' + +export default class Sunshine { + /** + * @constructor + * @param sdk + * @description 光照 + * @param options {object} 光照属性 + * @param options.time=当前时间 {string} 当前时间 + * @param options.speed=1000 {number} 速度倍速 + * @param options.darkness=0.3 {number} 阴影不透明度--越大越不透明 + * @param options.softShadow=false {boolean} 阴影优化--true/false} + * @param Dialog {object} 弹框对象 + * @param Dialog.confirmCallBack {function} 弹框确认时的回调 + * */ + constructor(sdk, options = {}, _Dialog = {}) { + this.viewer = sdk.viewer + this.options = { ...options } + this.sdk = { ...sdk } + this.options.time = options.time || new Date() + this.options.speed = options.speed || 1000 + this.options.darkness = options.darkness || 0.4 + this.options.softShadow = options.softShadow || true + this.options.show = options.show === true ? true : false + this.Dialog = _Dialog + this.timeLine + this._EventBinding = new EventBinding() + this._elms = {}; + Sunshine.start(this) + } + + + static start(that) { + that.viewer.scene.globe.enableLighting = true + that.viewer.shadows = true + that.viewer.scene.globe.enableLighting = true; + + that.viewer.terrainShadows = Cesium.ShadowMode.RECEIVE_ONLY + that.viewer.shadowMap.darkness = 1.0 - that.options.darkness //阴影透明度--越大越透明 + + const now = new Date(); + now.setHours(0, 0, 0, 0); // 设置为当天0点 + that.viewer.clock.currentTime = Cesium.JulianDate.fromDate(now); + that.viewer.clock.multiplier = that.options.speed; + that.viewer.shadowMap.softShadows = that.options.softShadow; + + that.edit(true) + } + get darkness() { + return this.options.darkness + } + set darkness(v) { + this.options.darkness = v + this.viewer.shadowMap.darkness = 1.0 - this.options.darkness + } + + get speed() { + return this.options.speed + } + set speed(v) { + this.options.speed = v + this.viewer.clock.multiplier = this.options.speed; + this.timeLine.setSpeed(v) + } + get softShadow() { + return this.options.softShadow + } + set softShadow(v) { + this.options.softShadow = v + this.viewer.shadowMap.softShadows = this.options.softShadow; + } + + /** + * @description 编辑框 + * @param state=false {boolean} 状态: true打开, false关闭 + */ + async edit(state = false) { + let tools = new Tools() + this.originalOptions = tools.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.originalOptions = tools.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 + ' sun-shine-surface' + let contentElm = document.createElement('div'); + contentElm.innerHTML = html() + this._DialogObject.contentAppChild(contentElm) + + //时间轴 + let _that = this + this.timeLine = new TimeLine(this.sdk, this.options.speed) + // this.timeLine.setSpeed(1000) + this.timeLine.moveComplay(item => { + let timeData = _that.time + " " + item + _that.viewer.clock.currentTime = Cesium.JulianDate.fromDate(new Date(timeData)); + _that.viewer.scene.requestRender(); + + + }) + let jeDateObject + let printDateElm = contentElm.getElementsByClassName('sunshine-date')[0] + let text + + jeDateObject = jeDate(printDateElm, { + format: "YYYY-MM-DD", + isinitVal: true, + isClear: false, + donefun: function (obj) { + this.time = obj.val + + const now = new Date(); + let timeData = now.setHours(0, 0, 0, 0); // 设置为当天0点 + _that.viewer.clock.currentTime = Cesium.JulianDate.fromDate(new Date(timeData)); + + _that.timeLine.updateTime(timeData) + } + }); + if (this.time) { + jeDateObject.setValue(this.time) + } + else { + jeDateObject.nowBtn && jeDateObject.nowBtn() + this.time = jeDateObject.getValue() + } + + let all_elm = contentElm.getElementsByTagName("*") + this._EventBinding.on(this, all_elm) + this._elms = this._EventBinding.element + this._elms.color = [jeDateObject] + } 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.time = this.originalOptions.time + this.speed = this.originalOptions.speed + this.darkness = this.originalOptions.darkness + } + + /** + * 飞到对应实体 + */ + async flyTo(options = {}) { + } + /** + * 删除 + */ + async remove() { + + this.viewer.scene.globe.enableLighting = false + this.viewer.shadows = false + this.viewer.clock.multiplier = 1.0 + this.viewer.clock.currentTime = Cesium.JulianDate.fromDate(new Date()); + this.entity = null + this.timeLine.clear() + + 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() { } +} + diff --git a/src/Global/efflect/Sunshine/timeLIne.js b/src/Global/efflect/Sunshine/timeLIne.js new file mode 100644 index 0000000..a012f69 --- /dev/null +++ b/src/Global/efflect/Sunshine/timeLIne.js @@ -0,0 +1,133 @@ +export default class TimeLine { + constructor(sdk, speed) { + this.sdk = { ...sdk }; + this.progress = document.getElementById('progress'); + this.handle = document.getElementById('handle'); + this.timeline = document.getElementById('timeline'); + this.currentTime = document.getElementById('currentTime'); + this.timelineCon = document.getElementsByClassName('timeline-container')[0]; + this.speed = speed; + this.animationId; + this.startTime = Date.now(); + this.manualPosition = null; + this.isDragging = false; + this.pauseed = false; + this.time = ''; + this.update = this.update.bind(this); + + TimeLine.init(this) + } + static init(that) { + for (let i = 0; i <= 24; i++) { + if (i % 6 === 0) { + const label = document.createElement('div'); + label.className = 'time-mark'; + label.textContent = `${i}:00`; + label.style.left = `${(i / 24) * 100}%`; + document.getElementsByClassName('time-marks')[0].appendChild(label) + } + } + + + that.startTime = Date.now() - ((that.manualPosition || 0) * 86400 * 1000 / that.speed); + + that.timeline.addEventListener('mousedown', (e) => { + that.isDragging = true; + e.preventDefault(); + }); + + that.timeline.addEventListener('mousemove', (e) => { + if (!that.isDragging) return; + + const rect = that.timeline.getBoundingClientRect(); + let pos = (e.clientX - rect.left) / rect.width; + pos = Math.max(0, Math.min(1, pos)); + + that.manualPosition = pos; + that.progress.style.width = `${pos * 100}%`; + + const seconds = pos * 86400; + that.currentTime.textContent = that.formatTime(seconds); + }); + that.update(); + + document.getElementById('timePause').addEventListener('click', function () { + that.pauseed = !that.pauseed; + if (that.pauseed) { + document.getElementById('timePause').textContent = '播放'; + that.animationId && cancelAnimationFrame(that.animationId); + that.pausedTime = Date.now(); // 记录暂停时刻 + that.sdk.viewer.clock.shouldAnimate = false + } else { + document.getElementById('timePause').textContent = '暂停'; + that.manualPosition = null + + const pausedDuration = Date.now() - that.pausedTime; + that.startTime += pausedDuration; // 补偿暂停期间的时间差 + that.sdk.viewer.clock.shouldAnimate = true + that.update(); // 重启动画循环 + } + }); + } + moveComplay(func) { + let that = this + that.timeline.addEventListener('mouseup', () => { + that.isDragging = false; + if (that.manualPosition !== null) { + // that.sdk.viewer.clock.shouldAnimate = true + that.startTime = Date.now() - (that.manualPosition * 86400 * 1000 / that.speed); + that.manualPosition = null; + + if (!that.pauseed) { + that.update() + func(that.time) + } else { + that.pausedTime = Date.now(); // 记录暂停时刻 + func(that.currentTime.textContent) + } + + } + }); + } + formatTime(seconds) { + const hrs = Math.floor(seconds / 3600).toString().padStart(2, '0'); + const mins = Math.floor((seconds % 3600) / 60).toString().padStart(2, '0'); + const secs = Math.floor(seconds % 60).toString().padStart(2, '0'); + return `${hrs}:${mins}:${secs}`; + } + + update() { + if (this.manualPosition !== null) return; + + const elapsed = (Date.now() - this.startTime) * this.speed; + const totalSeconds = elapsed / 1000; + const daySeconds = totalSeconds % 86400; + const percentage = daySeconds / 86400; + + this.progress.style.width = `${percentage * 100}%`; + this.time = this.formatTime(daySeconds) + this.currentTime.textContent = this.time; + this.animationId = requestAnimationFrame(this.update); + } + setSpeed(v) { + const currentProgress = this.manualPosition ?? + (Date.now() - this.startTime) * this.speed / (86400 * 1000); + + this.speed = v; + this.startTime = Date.now() - (currentProgress * 86400 * 1000 / this.speed); + this.manualPosition = null; + this.update(); + + } + updateTime() { + this.startTime = Date.now() - (this.manualPosition * 86400 * 1000 / this.speed); + this.manualPosition = null; + this.update(); + } + clear() { + this.animationId && cancelAnimationFrame(this.animationId); + this.progress.style.width = '0%'; + this.currentTime.textContent = '00:00:00'; + } + +} diff --git a/src/In/index.js b/src/In/index.js index 61fc475..ca9db7f 100644 --- a/src/In/index.js +++ b/src/In/index.js @@ -70,7 +70,7 @@ import { import { MouseCoordinate } from '../Global/MouseCoordinate' import { MouseRightMenu } from '../Global/mouseRightMenu' import { dialog as ContourDialog } from '../Global/Contour' -import { on as SplitScreenOn, off as SplitScreenOff, setActiveId as SplitScreenSetActiveId ,getSdk } from '../Global/SplitScreen' +import { on as SplitScreenOn, off as SplitScreenOff, setActiveId as SplitScreenSetActiveId, getSdk } from '../Global/SplitScreen' import LocateCurrent from '../Obj/Base/LocateCurrent' import { Clear as AnalysisClear } from '../Obj/Analysis/clear' @@ -183,6 +183,8 @@ import Dialog from '../Obj/Element/Dialog' import newAirLine from '../Obj/AirLine/pointRoute.js' import Frustum from '../Obj/AirLine/frustum' import DrawTakeOff from '../Obj/AirLine/DrawTakeOff' +import FlowLine from '../Obj/Base/FlowLine' +import Sunshine from '../Global/efflect/Sunshine' const YJEarthismeasuring = Symbol('测量状态') const screenRecord = Symbol('录屏对象') @@ -253,7 +255,8 @@ if (!window.YJ) { newAirLine, FRUSTUN: Frustum, // GenerateRoute - Dialog + Dialog, + FlowLine }, YJEarth, Tools, @@ -292,7 +295,7 @@ if (!window.YJ) { cease: FlyRoamCease }, flyTo, - efflect: { rain, snow, fog, nightVision, skyStarry, illumination }, + efflect: { rain, snow, fog, nightVision, skyStarry, illumination, Sunshine }, CameraController, CesiumContainer, setBillboardDefaultUrl, @@ -301,7 +304,7 @@ if (!window.YJ) { on: multiViewportModeOn, off: multiViewportModeOff, get2DView, - getSdk:getSdk2 + getSdk: getSdk2 }, MouseCoordinate, MouseRightMenu, diff --git a/src/Obj/Base/FlowLine/_element.js b/src/Obj/Base/FlowLine/_element.js new file mode 100644 index 0000000..4cdc020 --- /dev/null +++ b/src/Obj/Base/FlowLine/_element.js @@ -0,0 +1,76 @@ +function html() { + return ` + +
+
+
+ 名称 + +
+
+ 颜色 +
+
+
+
+ +
+
+
+ 飞线数量 +
+ + +
+
+
+ 飞线宽度 +
+ + +
+
+
+
+
+
+ +
+ 飞线高度 +
+ + +
+
+
+ 飞线高度差 +
+ + +
+
+
+
+
+
+
+ 单次运动时长(s) +
+ + +
+
+
+ 轨迹透明度 +
+ + +
+
+
+
+ + ` +} + +export { html } diff --git a/src/Obj/Base/FlowLine/eventBinding.js b/src/Obj/Base/FlowLine/eventBinding.js new file mode 100644 index 0000000..ccbf026 --- /dev/null +++ b/src/Obj/Base/FlowLine/eventBinding.js @@ -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; \ No newline at end of file diff --git a/src/Obj/Base/FlowLine/index.js b/src/Obj/Base/FlowLine/index.js new file mode 100644 index 0000000..f972e23 --- /dev/null +++ b/src/Obj/Base/FlowLine/index.js @@ -0,0 +1,476 @@ +/** + * @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.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) + } + + // 创建水面 + 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) + }) + } + 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 = []; + 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) { + points.push([ + lon, + lat + ]); + } + } + 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 end = Cesium.Cartesian3.fromDegrees(point[0], point[1], that.options.height + Math.random() * that.options.heightDifference) + //创建线 + that.viewer.entities.add({ + parent: celiangEntity, + polyline: { + positions: [start, end], + width: 2, + // 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 ewPlugins('colorpicker', { + 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 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 ewPlugins('colorpicker', { + 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.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 diff --git a/src/Obj/Base/PolylineObject/index.js b/src/Obj/Base/PolylineObject/index.js index 5317663..d40ab76 100644 --- a/src/Obj/Base/PolylineObject/index.js +++ b/src/Obj/Base/PolylineObject/index.js @@ -13,7 +13,6 @@ import MouseTip from '../../../MouseTip' import Controller from '../../../Controller/index' import { syncData } from '../../../Global/MultiViewportMode' import { legp } from '../../Element/datalist' -import { getFontList, getFontFamilyName } from '../../Element/fontSelect' import { setSplitDirection, syncSplitData, setActiveId } from '../../../Global/SplitScreen' import { setActiveViewer, closeRotateAround, closeViewFollow } from '../../../Global/global' @@ -78,7 +77,6 @@ class PolylineObject extends Base { options.label.fontSize || options.label.fontSize === 0 ? options.label.fontSize : 20, - fontFamily: options.label.fontFamily ? options.label.fontFamily : 0, color: options.label.color || '#ffffff', lineWidth: options.label.lineWidth || options.label.lineWidth === 0 @@ -275,6 +273,31 @@ class PolylineObject extends Base { name: '泛光', value: '泛光', key: 2 + }, + { + name: '尾迹光线', + value: '尾迹光线', + key: 3 + }, + { + name: '多尾迹光线', + value: '多尾迹光线', + key: 4 + }, + { + name: '流动虚线1', + value: '流动虚线1', + key: 5 + }, + { + name: '流动虚线2', + value: '流动虚线2', + key: 6 + }, + { + name: '流动箭头1', + value: '流动箭头1', + key: 7 } ] this.options.type = Number(v) @@ -507,21 +530,6 @@ class PolylineObject extends Base { }) } - get labelFontFamily() { - return this.options.label.fontFamily - } - - set labelFontFamily(v) { - this.options.label.fontFamily = v || 0 - this.label && (this.label.fontFamily = this.options.label.fontFamily) - - let name = getFontFamilyName(this.labelFontFamily) || '' - this._elms.labelFontFamily && - this._elms.labelFontFamily.forEach(item => { - item.value = name - }) - } - get labelColor() { return this.options.label.color } @@ -1141,7 +1149,6 @@ class PolylineObject extends Base { ], text: that.options.name, fontSize: that.options.label.fontSize, - fontFamily: that.options.label.fontFamily, color: that.options.label.color, pixelOffset: that.options.label.pixelOffset, backgroundColor: that.options.label.backgroundColor, @@ -1508,6 +1515,31 @@ class PolylineObject extends Base { name: '泛光', value: '泛光', key: 2 + }, + { + name: '尾迹光线', + value: '尾迹光线', + key: 3 + }, + { + name: '多尾迹光线', + value: '多尾迹光线', + key: 4 + }, + { + name: '流动虚线1', + value: '流动虚线1', + key: 5 + }, + { + name: '流动虚线2', + value: '流动虚线2', + key: 6 + }, + { + name: '流动箭头1', + value: '流动箭头1', + key: 7 } ] let lineTypeDataLegpObject = legp( @@ -1760,37 +1792,6 @@ class PolylineObject extends Base { this._elms.altInput.push(altInput) tBodyElm.appendChild(tr) } - - let fontData = getFontList() - let fontObject = legp( - this._DialogObject._element.content.getElementsByClassName( - 'font-select-box' - )[0], - '.font-select' - ) - if (fontObject) { - fontObject.legp_search(fontData) - let fontDataLegpElm = this._DialogObject._element.content - .getElementsByClassName('font-select')[0] - .getElementsByTagName('input')[0] - fontDataLegpElm.value = fontData[this.labelFontFamily].value - for (let i = 0; i < fontData.length; i++) { - if (fontData[i].value == fontDataLegpElm.value) { - fontObject.legp_searchActive(fontData[i].value) - break - } - } - fontDataLegpElm.addEventListener('input', () => { - for (let i = 0; i < fontData.length; i++) { - if (fontData[i].value === fontDataLegpElm.value) { - this.labelFontFamily = fontData[i].key - break - } - } - }) - this._elms.labelFontFamily = [fontDataLegpElm] - } - }, 0) } else { if (this._DialogObject && this._DialogObject.close) { @@ -1972,10 +1973,6 @@ class PolylineObject extends Base { this.labelShow = this.originalOptions.label.show this.labelColor = this.originalOptions.label.color this.labelFontSize = this.originalOptions.label.fontSize - this.labelFontFamily = this.originalOptions.label.fontFamily - this.labelScaleByDistance = this.originalOptions.label.scaleByDistance - this.labelNear = this.originalOptions.label.near - this.labelFar = this.originalOptions.label.far this.labelLineWidth = this.originalOptions.label.lineWidth this.labelPixelOffset = this.originalOptions.label.pixelOffset this.labelLineColor = this.originalOptions.label.lineColor @@ -2039,7 +2036,7 @@ class PolylineObject extends Base { .value ) { this.options.attribute.link.content.push({ - name: '链接', + name: '链接' + (this.options.attribute.link.content.length + 1), url: this._DialogObject._element.content.getElementsByClassName( 'link_add' )[0].value @@ -2057,7 +2054,7 @@ class PolylineObject extends Base { // input.addEventListener('change', (event) => { // if (input.value) { // this.options.attribute.link.content.push({ - // name: '链接', + // name: '链接' + (this.options.attribute.link.content.length + 1), // url: input.value // }) // this.attributeLink = this.options.attribute.link.content @@ -2067,7 +2064,7 @@ class PolylineObject extends Base { } addAttributeLink(link) { this.options.attribute.link.content.push({ - name: '链接', + name: '链接' + (this.options.attribute.link.content.length + 1), url: link }) this.attributeLink = this.options.attribute.link.content @@ -2080,7 +2077,7 @@ class PolylineObject extends Base { )[0].value ) { this.options.attribute.vr.content.push({ - name: '全景图' , + name: '全景图' + (this.options.attribute.vr.content.length + 1), url: this._DialogObject._element.content.getElementsByClassName( 'vr_add' )[0].value @@ -2096,7 +2093,7 @@ class PolylineObject extends Base { addAttributeRr(vr) { this.options.attribute.vr.content.push({ - name: '全景图' , + name: '全景图' + (this.options.attribute.vr.content.length + 1), url: vr }) this.attributeVr = this.options.attribute.vr.content diff --git a/src/Obj/Materail/FlowDashedLineFlowMaterialProperty.js b/src/Obj/Materail/FlowDashedLineFlowMaterialProperty.js new file mode 100644 index 0000000..10d5d6c --- /dev/null +++ b/src/Obj/Materail/FlowDashedLineFlowMaterialProperty.js @@ -0,0 +1,124 @@ +/* + * @Description: 流动线 + */ +function FlowDashedLine() { + class FlowDashedLineFlowMaterialProperty { + constructor(options) { + this._definitionChanged = new Cesium.Event(); + this._color = undefined; + this._speed = undefined; + this._uType = undefined; + this.color = new Cesium.Color.fromCssColorString(options.color || "rgba(255,255,255,1)"); + this.speed = options.speed || 0.25;//速度 + this.uType = options.uType === undefined ? 1 : options.uType;//类型:0:普通流动线 1:虚化虚线 + this.lineBackAlpha = options.lineBackAlpha || 0.05; + } + + get isConstant() { + return false; + } + + get definitionChanged() { + return this._definitionChanged; + } + + getType(time) { + return Cesium.Material.FlowDashedLineMaterialType; + } + + getValue(time, result) { + if (!Cesium.defined(result)) { + result = {}; + } + + result.color = Cesium.Property.getValueOrDefault( + this._color, + time, + Cesium.Color.RED, + result.color + ); + result.speed = Cesium.Property.getValueOrDefault( + this._speed, + time, + 10, + result.speed + ); + result.uType = Cesium.Property.getValueOrDefault( + this._uType, + time, + 1, + result.uType + ); + result.lineBackAlpha = this.lineBackAlpha; + result.frameNumber = Cesium.getTimestamp(); + return result; + } + + equals(other) { + return ( + this === other || + (other instanceof FlowDashedLineFlowMaterialProperty && + Cesium.Property.equals(this._color, other._color) && + Cesium.Property.equals(this._speed, other.speed) && + Cesium.Property.equals(this._uType, other.uType) && + Cesium.Property.equals(this.lineBackAlpha, other.lineBackAlpha)) + ); + } + } + + Object.defineProperties(FlowDashedLineFlowMaterialProperty.prototype, { + color: Cesium.createPropertyDescriptor("color"), + speed: Cesium.createPropertyDescriptor("speed"), + uType: Cesium.createPropertyDescriptor("uType"), + transparency: Cesium.createPropertyDescriptor("lineBackAlpha"), + }); + + Cesium.FlowDashedLineFlowMaterialProperty = FlowDashedLineFlowMaterialProperty; + Cesium.Material.FlowDashedLineFlowMaterialProperty = "FlowDashedLineFlowMaterialProperty"; + Cesium.Material.FlowDashedLineMaterialType = "FlowDashedLineMaterialType"; + Cesium.Material.FlowDashedLineMaterialSource = ` + uniform vec4 color; + uniform float speed; + // uniform int uType; + uniform float lineBackAlpha; + + czm_material czm_getMaterial(czm_materialInput materialInput) + { + czm_material material = czm_getDefaultMaterial(materialInput); + vec2 st = materialInput.st; + + // 计算流动虚线 + float dashSize = 0.03; + float gapSize = 0.01; + float progress = fract(czm_frameNumber * 0.01); // 时间控制流动 + float pattern = fract(st.x / (dashSize + gapSize) + progress); + float dash1 = step(0.1, pattern) - step(0.9, pattern); + float dash2 = smoothstep(0.1, 0.3, pattern) - smoothstep(0.7, 0.9, pattern); + float dash = (float(uType) != 1.0)?dash1:dash2; + material.alpha = dash; + material.diffuse = color.rgb; + return material; + } + `; + + Cesium.Material._materialCache.addMaterial( + Cesium.Material.FlowDashedLineMaterialType, + { + fabric: { + type: Cesium.Material.FlowDashedLineMaterialType, + uniforms: { + color: new Cesium.Color(1.0, 1.0, 1.0, 1.0), + speed: 0.1, + uType: 1, + lineBackAlpha: 0.05, + }, + source: Cesium.Material.FlowDashedLineMaterialSource, + }, + translucent: function (material) { + return true; + }, + } + ); +} + +export { FlowDashedLine } diff --git a/src/Obj/Materail/FlowLineMaterialProperty.js b/src/Obj/Materail/FlowLineMaterialProperty.js new file mode 100644 index 0000000..7b4e009 --- /dev/null +++ b/src/Obj/Materail/FlowLineMaterialProperty.js @@ -0,0 +1,113 @@ +/* + * @Description: 流动线 + */ +function FlowLine() { + class FlowLineMaterialProperty { + constructor(options) { + this._definitionChanged = new Cesium.Event(); + this._color = undefined; + this._duration = undefined; + this.color = new Cesium.Color.fromCssColorString(options.color || "rgba(255,255,255,1)"); + this.duration = options.duration || 10.0; + this.lineBackAlpha = options.lineBackAlpha || 0.05; + } + + get isConstant() { + return false; + } + + get definitionChanged() { + return this._definitionChanged; + } + + getType(time) { + return Cesium.Material.FlowLineMaterialType; + } + + getValue(time, result) { + if (!Cesium.defined(result)) { + result = {}; + } + + result.color = Cesium.Property.getValueOrDefault( + this._color, + time, + Cesium.Color.RED, + result.color + ); + result.duration = Cesium.Property.getValueOrDefault( + this._duration, + time, + 10, + result.duration + ); + result.lineBackAlpha = this.lineBackAlpha; + result.frameNumber = Cesium.getTimestamp(); + return result; + } + + equals(other) { + return ( + this === other || + (other instanceof FlowLineMaterialProperty && + Cesium.Property.equals(this._color, other._color) && + Cesium.Property.equals(this._duration, other.duration) && + Cesium.Property.equals(this.lineBackAlpha, other.lineBackAlpha)) + ); + } + } + + Object.defineProperties(FlowLineMaterialProperty.prototype, { + color: Cesium.createPropertyDescriptor("color"), + duration: Cesium.createPropertyDescriptor("duration"), + transparency: Cesium.createPropertyDescriptor("lineBackAlpha"), + }); + + Cesium.FlowLineMaterialProperty = FlowLineMaterialProperty; + Cesium.Material.FlowLineMaterialProperty = "FlowLineMaterialProperty"; + Cesium.Material.FlowLineMaterialType = "FlowLineMaterialType"; + Cesium.Material.FlowLineMaterialSource = ` + uniform vec4 color; + uniform float duration; + uniform float lineBackAlpha; + + czm_material czm_getMaterial(czm_materialInput materialInput) + { + //生成默认的基础材质 + czm_material material = czm_getDefaultMaterial(materialInput); + //获取st(uv) + vec2 st = materialInput.st; + //获取当前帧数,10秒内变化0-1 + float time = fract(czm_frameNumber / (60.0*duration)); + //长度1/10 + time = time * (1.0 + 0.1); + //平滑过渡函数 + float alpha = smoothstep(time-0.1,time,st.s) * step(-time,-st.s); + //光带轨迹(不会完全透明) + alpha += lineBackAlpha; + material.alpha = alpha; + material.diffuse = color.rgb; + return material; + } + `; + + Cesium.Material._materialCache.addMaterial( + Cesium.Material.FlowLineMaterialType, + { + fabric: { + type: Cesium.Material.FlowLineMaterialType, + uniforms: { + color: new Cesium.Color(1.0, 1.0, 1.0, 1.0), + duration: 10.0, + lineBackAlpha: 0.05, + }, + source: Cesium.Material.FlowLineMaterialSource, + }, + translucent: function (material) { + return true; + }, + } + ); +} + +export { FlowLine } diff --git a/src/Obj/Materail/LineTextureMaterialProperty.js b/src/Obj/Materail/LineTextureMaterialProperty.js new file mode 100644 index 0000000..105f391 --- /dev/null +++ b/src/Obj/Materail/LineTextureMaterialProperty.js @@ -0,0 +1,110 @@ +/* + * @Description: 流动线 + */ +function LineTexture() { + class LineTextureMaterialProperty { + constructor(options) { + this._definitionChanged = new Cesium.Event(); + this._image = undefined; + this._color = undefined; + this._imageW = undefined; + this.image = options.image || ""; + this.color = new Cesium.Color.fromCssColorString(options.color || "rgba(255,255,255,1)"); + this.imageW = options.imageW || 1; + } + + get isConstant() { + return false; + } + + get definitionChanged() { + return this._definitionChanged; + } + + getType(time) { + return Cesium.Material.LineTextureMaterialType; + } + + getValue(time, result) { + if (!Cesium.defined(result)) { + result = {}; + } + result.image = Cesium.Property.getValueOrDefault( + this._image, + time, + "", + result.image + ); + result.color = Cesium.Property.getValueOrDefault( + this._color, + time, + Cesium.Color.RED, + result.color + ); + result.imageW = Cesium.Property.getValueOrDefault( + this._imageW, + time, + 1, + result.imageW + ); + return result; + } + + equals(other) { + return ( + this === other || + (other instanceof LineTextureMaterialProperty && + Cesium.Property.equals(this._image, other._image) && + Cesium.Property.equals(this._color, other._color) && + Cesium.Property.equals(this._imageW, other._imageW)) + ); + } + } + + Object.defineProperties(LineTextureMaterialProperty.prototype, { + image: Cesium.createPropertyDescriptor("image"), + color: Cesium.createPropertyDescriptor("color"), + imageW: Cesium.createPropertyDescriptor("imageW"), + }); + + Cesium.LineTextureMaterialProperty = LineTextureMaterialProperty; + Cesium.Material.LineTextureMaterialProperty = "LineTextureMaterialProperty"; + Cesium.Material.LineTextureMaterialType = "LineTextureMaterialType"; + Cesium.Material.LineTextureMaterialSource = ` + #extension GL_OES_standard_derivatives : enable + czm_material czm_getMaterial(czm_materialInput materialInput) + { + czm_material m = czm_getDefaultMaterial(materialInput); + + + vec2 st = materialInput.st * vec2(494/172, 1.0); // 横向重复两次 + vec2 uv = vec2(fract(st.s + uTime*0.1), st.t); + // uv.y = mix(uv.y, 1.0-uv.y, step(0.5, fract(uTime))); // 周期性反转Y轴 + vec4 tex = texture(image, uv); + m.diffuse =(tex.rgb+color.rgb)/2.0; + m.alpha = tex.a * (1.0 - fract(st.t)) * color.a; // 顶部渐隐 + + return m; + } + `; + Cesium.Material._materialCache.addMaterial( + Cesium.Material.LineTextureMaterialType, + { + fabric: { + type: Cesium.Material.LineTextureMaterialType, + uniforms: { + color: new Cesium.Color(1.0, 1.0, 1.0, 1.0), + image: '', + imageW: 1, + uTime: 1 + }, + source: Cesium.Material.LineTextureMaterialSource, + }, + translucent: function (material) { + return true; + }, + } + ); +} + +export { LineTexture } diff --git a/src/Obj/Materail/PolylineFlowMaterialProperty.js b/src/Obj/Materail/PolylineFlowMaterialProperty.js new file mode 100644 index 0000000..79cb6df --- /dev/null +++ b/src/Obj/Materail/PolylineFlowMaterialProperty.js @@ -0,0 +1,113 @@ +/* + * @Description: 流动线 + */ +function PolylineFlow() { + class PolylineFlowMaterialProperty { + constructor(options) { + this._definitionChanged = new Cesium.Event(); + this._color = undefined; + this._speed = undefined; + this.color = new Cesium.Color.fromCssColorString(options.color || "rgba(255,255,255,1)"); + this.speed = options.speed || 0.25;//速度 + this.lineBackAlpha = options.lineBackAlpha || 0.05; + } + + get isConstant() { + return false; + } + + get definitionChanged() { + return this._definitionChanged; + } + + getType(time) { + return Cesium.Material.PolylineFlowMaterialType; + } + + getValue(time, result) { + if (!Cesium.defined(result)) { + result = {}; + } + + result.color = Cesium.Property.getValueOrDefault( + this._color, + time, + Cesium.Color.RED, + result.color + ); + result.speed = Cesium.Property.getValueOrDefault( + this._speed, + time, + 10, + result.speed + ); + result.lineBackAlpha = this.lineBackAlpha; + result.frameNumber = Cesium.getTimestamp(); + return result; + } + + equals(other) { + return ( + this === other || + (other instanceof PolylineFlowMaterialProperty && + Cesium.Property.equals(this._color, other._color) && + Cesium.Property.equals(this._speed, other.speed) && + Cesium.Property.equals(this.lineBackAlpha, other.lineBackAlpha)) + ); + } + } + + Object.defineProperties(PolylineFlowMaterialProperty.prototype, { + color: Cesium.createPropertyDescriptor("color"), + speed: Cesium.createPropertyDescriptor("speed"), + transparency: Cesium.createPropertyDescriptor("lineBackAlpha"), + }); + + Cesium.PolylineFlowMaterialProperty = PolylineFlowMaterialProperty; + Cesium.Material.PolylineFlowMaterialProperty = "PolylineFlowMaterialProperty"; + Cesium.Material.PolylineFlowMaterialType = "PolylineFlowMaterialType"; + Cesium.Material.PolylineFlowMaterialSource = ` + uniform vec4 color; + uniform float speed; + uniform float lineBackAlpha; + + czm_material czm_getMaterial(czm_materialInput materialInput) + { + //生成默认的基础材质 + czm_material material = czm_getDefaultMaterial(materialInput); + //获取st(uv) + vec2 st = materialInput.st; + //获取当前帧数,10秒内变化0-1 + float time = fract(czm_frameNumber * speed / 60.0); + //长度1/10 + time = time * (1.0 + 0.1); + //平滑过渡函数 + float alpha = smoothstep(time-0.1,time,st.s) * step(-time,-st.s); + //光带轨迹(不会完全透明) + alpha += lineBackAlpha; + material.alpha = alpha; + material.diffuse = color.rgb; + return material; + } + `; + + Cesium.Material._materialCache.addMaterial( + Cesium.Material.PolylineFlowMaterialType, + { + fabric: { + type: Cesium.Material.PolylineFlowMaterialType, + uniforms: { + color: new Cesium.Color(1.0, 1.0, 1.0, 1.0), + speed: 0.1, + lineBackAlpha: 0.05, + }, + source: Cesium.Material.PolylineFlowMaterialSource, + }, + translucent: function (material) { + return true; + }, + } + ); +} + +export { PolylineFlow } diff --git a/src/Obj/Materail/PolylineFlowMultMaterialProperty.js b/src/Obj/Materail/PolylineFlowMultMaterialProperty.js new file mode 100644 index 0000000..c9b64f2 --- /dev/null +++ b/src/Obj/Materail/PolylineFlowMultMaterialProperty.js @@ -0,0 +1,134 @@ +/* + * @Description: 流动线 + */ +function PolylineFlowMult() { + class PolylineFlowMultMaterialProperty { + constructor(options) { + this._definitionChanged = new Cesium.Event(); + this._color = undefined; + this._speed = undefined; + this.color = new Cesium.Color.fromCssColorString(options.color || "rgba(255,255,255,1)"); + this.speed = options.speed || 0.1;//速度 + this.lineBackAlpha = options.lineBackAlpha || 0.05; + } + + get isConstant() { + return false; + } + + get definitionChanged() { + return this._definitionChanged; + } + + getType(time) { + return Cesium.Material.PolylineFlowMultMaterialType; + } + + getValue(time, result) { + if (!Cesium.defined(result)) { + result = {}; + } + + result.color = Cesium.Property.getValueOrDefault( + this._color, + time, + Cesium.Color.RED, + result.color + ); + result.speed = Cesium.Property.getValueOrDefault( + this._speed, + time, + 10, + result.speed + ); + result.lineBackAlpha = this.lineBackAlpha; + result.frameNumber = Cesium.getTimestamp(); + return result; + } + + equals(other) { + return ( + this === other || + (other instanceof PolylineFlowMultMaterialProperty && + Cesium.Property.equals(this._color, other._color) && + Cesium.Property.equals(this._speed, other.speed) && + Cesium.Property.equals(this.lineBackAlpha, other.lineBackAlpha)) + ); + } + } + + Object.defineProperties(PolylineFlowMultMaterialProperty.prototype, { + color: Cesium.createPropertyDescriptor("color"), + speed: Cesium.createPropertyDescriptor("speed"), + transparency: Cesium.createPropertyDescriptor("lineBackAlpha"), + }); + + Cesium.PolylineFlowMultMaterialProperty = PolylineFlowMultMaterialProperty; + Cesium.Material.PolylineFlowMultMaterialProperty = "PolylineFlowMultMaterialProperty"; + Cesium.Material.PolylineFlowMultMaterialType = "PolylineFlowMultMaterialType"; + Cesium.Material.PolylineFlowMaterialSource = ` + uniform vec4 color; + uniform float speed; + uniform float lineBackAlpha; + + czm_material czm_getMaterial(czm_materialInput materialInput) + { + czm_material material = czm_getDefaultMaterial(materialInput); + vec2 st = materialInput.st; + + // 基础时间轴(控制主光带) + float baseTime = fract(czm_frameNumber * speed / 60.0) * 1.1; + + // 高频时间轴(控制高光点) + float highlightTime = fract(czm_frameNumber * speed * 3.0 / 60.0); + float highlightSpacing = 0.3; // 高光点间隔 + + // 主光带透明度计算 + float mainAlpha = smoothstep(baseTime-0.1, baseTime, st.s) * step(-baseTime, -st.s); + + // 多高光点计算(3个周期性光斑) + float highlight1 = smoothstep(highlightTime-0.05, highlightTime, st.s) * + step(-highlightTime, -st.s) * + (1.0 - smoothstep(0.0, highlightSpacing, abs(st.s - highlightTime))); + + float highlight2 = smoothstep(highlightTime+highlightSpacing-0.05, + highlightTime+highlightSpacing, st.s) * + step(-(highlightTime+highlightSpacing), -st.s) * + (1.0 - smoothstep(0.0, highlightSpacing, abs(st.s - (highlightTime+highlightSpacing)))); + + float highlight3 = smoothstep(highlightTime+2.0*highlightSpacing-0.05, + highlightTime+2.0*highlightSpacing, st.s) * + step(-(highlightTime+2.0*highlightSpacing), -st.s) * + (1.0 - smoothstep(0.0, highlightSpacing, abs(st.s - (highlightTime+2.0*highlightSpacing)))); + + // 合并效果 + // material.alpha = mainAlpha * 0.7 + + // (highlight1 + highlight2 + highlight3) * 0.5 + + // lineBackAlpha; + material.alpha = (highlight1 + highlight2 + highlight3) * 0.5 + + lineBackAlpha; + material.diffuse = color.rgb; // 高光区变亮 + return material; + } + `; + + Cesium.Material._materialCache.addMaterial( + Cesium.Material.PolylineFlowMultMaterialType, + { + fabric: { + type: Cesium.Material.PolylineFlowMultMaterialType, + uniforms: { + color: new Cesium.Color(1.0, 1.0, 1.0, 1.0), + speed: 0.1, + lineBackAlpha: 0.05, + }, + source: Cesium.Material.PolylineFlowMaterialSource, + }, + translucent: function (material) { + return true; + }, + } + ); +} + +export { PolylineFlowMult } diff --git a/src/Obj/Materail/index.js b/src/Obj/Materail/index.js index 5397891..e7fff6b 100644 --- a/src/Obj/Materail/index.js +++ b/src/Obj/Materail/index.js @@ -2,6 +2,11 @@ import { StreamWall1, StreamWall2 } from './WallMaterialProperty' import { RadarScan } from './RadarScanMaterialProperty' import { CustomColorMaterialSource } from './CustomColorMaterialSource' import { CustomImageMaterialSource } from './CustomImageMaterialSource' +import { FlowLine } from './FlowLineMaterialProperty' +import { PolylineFlow } from './PolylineFlowMaterialProperty' +import { PolylineFlowMult } from './PolylineFlowMultMaterialProperty' +import { FlowDashedLine } from './FlowDashedLineFlowMaterialProperty' +import { LineTexture } from './LineTextureMaterialProperty' function init_material() { StreamWall1() @@ -9,6 +14,11 @@ function init_material() { RadarScan() CustomColorMaterialSource() CustomImageMaterialSource() + FlowLine() + PolylineFlow() + PolylineFlowMult() + FlowDashedLine() + LineTexture() } -export { init_material } \ No newline at end of file +export { init_material } diff --git a/src/Tools/index.js b/src/Tools/index.js index 11528d8..53c0fe5 100644 --- a/src/Tools/index.js +++ b/src/Tools/index.js @@ -529,6 +529,63 @@ class Tools { color: Cesium.Color.fromCssColorString(color), }) break + case 3: //尾迹光线 + material = new Cesium.PolylineFlowMaterialProperty({ + color: color + }) + break + case 4: //多尾迹光线 + material = new Cesium.PolylineFlowMultMaterialProperty({ + color: color + }) + break + case 5: //普通流动虚线 + material = new Cesium.FlowDashedLineFlowMaterialProperty({ + color: color, + uType: 0 + }) + break + case 6: //流动虚线2 + material = new Cesium.FlowDashedLineFlowMaterialProperty({ + color: color, + uType: 1 + }) + break + case 7: //流动箭头1 + material = new Cesium.LineTextureMaterialProperty({ + color: color, + image: this.getSourceRootPath() + '/img/arrow/2.png', + // imageW: 172 + }) + // let that = this + // var curCanvas = 'a'; + // let i = 0; + // function drawCanvasImage(time, result) { + // let canvas = document.createElement('canvas'); + // canvas.id = "canvas-" + curCanvas; + // // document.getElementById('app').appendChild(canvas) + // // var canvas = document.getElementById("canvas-" + curCanvas); + // let cwidth = 494; + // let cheight = 172; + // var ctx = canvas.getContext("2d"); + // var img = new Image(); + // img.src = that.getSourceRootPath() + '/img/arrow/1.png'; + // ctx.clearRect(0, 0, cwidth, cheight); + // img.onload = function () { + // if (i <= cwidth) { + // ctx.drawImage(img, i, 0); + // } else + // i = 0; + // i += 3; + // } + // curCanvas = curCanvas === 'a' ? 'b' : 'a'; + // return canvas; + // } + // material = new Cesium.ImageMaterialProperty({ + // image: new Cesium.CallbackProperty(drawCanvasImage, false), + // transparent: true + // }) + break default: material = Cesium.Color.fromCssColorString(color) break @@ -982,8 +1039,8 @@ class Tools { /** * @desc cmyk转rbg - * @param {*} color - * @returns + * @param {*} color + * @returns */ cmykToRgb(color) { let { c, m, y, k } = color diff --git a/static/custom/css/index.css b/static/custom/css/index.css index cb003ee..bf4ec1e 100644 --- a/static/custom/css/index.css +++ b/static/custom/css/index.css @@ -1780,6 +1780,89 @@ .YJ-custom-base-dialog.water-surface>.content>div .row .label { flex: 0 0 60px; } +/* 流光飞线 */ +.YJ-custom-base-dialog.flow-line-surface>.content { + width: 586px; +} + +.YJ-custom-base-dialog.flow-line-surface>.content>div .row .label { + flex: 0 0 60px; +} + +/* 光照 */ +.YJ-custom-base-dialog.sun-shine-surface>.content { + width: 586px; +} + +.YJ-custom-base-dialog.sun-shine-surface>.content>div .row .label { + flex: 0 0 60px; +} + +.YJ-custom-base-dialog.sun-shine-surface>.content>div .timeline-container { + width: 100%; + padding: 20px 0; + position: relative; +} + +.YJ-custom-base-dialog.sun-shine-surface>.content>div .timeline { + height: 8px; + background: #f0f0f0; + border-radius: 15px; + position: relative; + cursor: pointer; +} + +.YJ-custom-base-dialog.sun-shine-surface>.content>div .progress { + height: 100%; + width: 0; + background: rgba(var(--color-sdk-base-rgb), 1); + border-radius: 15px; + position: relative; +} + +.YJ-custom-base-dialog.sun-shine-surface>.content>div .handle { + width: 16px; + height: 16px; + background: white; + /* border: 3px solid #4285f4; */ + background: rgba(var(--color-sdk-base-rgb), 1); + border-radius: 50%; + position: absolute; + right: -8px; + top: 50%; + transform: translateY(-50%); + cursor: grab; +} + +.YJ-custom-base-dialog.sun-shine-surface>.content>div .time-marks { + display: flex; + justify-content: space-between; + margin-top: 5px; +} + +.YJ-custom-base-dialog.sun-shine-surface>.content>div .time-mark { + font-size: 12px; + color: #fff; +} + +.YJ-custom-base-dialog.sun-shine-surface>.content>div .controls { + margin: 15px 0; +} + + +.YJ-custom-base-dialog.sun-shine-surface>.content>div .current-time { + font-size: 12px; + position: absolute; + width: 50px; + text-align: center; + right: -25px; + top: -200%; + transform: translateY(-50%); +} + +.YJ-custom-base-dialog.sun-shine-surface>.content>div #timePause { + margin-top: 10px; +} /* 电子围墙 */ .YJ-custom-base-dialog.wall-stereoscopic>.content { @@ -2983,4 +3066,4 @@ .YJ-custom-base-dialog.contour>.content .label { flex: 0 0 56px; -} \ No newline at end of file +} diff --git a/static/img/arrow/1.png b/static/img/arrow/1.png new file mode 100644 index 0000000000000000000000000000000000000000..a959a24f69097db19494de6bc1214f70ee666563 GIT binary patch literal 17773 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 literal 0 HcmV?d00001 diff --git a/static/img/arrow/2.png b/static/img/arrow/2.png new file mode 100644 index 0000000000000000000000000000000000000000..1c1985ac8f06d9dac18908e2bfec0e6f1dcca6a7 GIT binary patch literal 3317 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 literal 0 HcmV?d00001 diff --git a/static/img/arrow/3.png b/static/img/arrow/3.png new file mode 100644 index 0000000000000000000000000000000000000000..895389c3678f62565b9804b64d1f22b764c28803 GIT binary patch literal 10202 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

tQ+MW=pUX!lKdJT8g_N|Ro4&6wd$8zzq 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 Uwss~yT>t<807*qoM6N<$f)}nrVE_OC literal 0 HcmV?d00001 diff --git a/static/img/arrow/4.png b/static/img/arrow/4.png new file mode 100644 index 0000000000000000000000000000000000000000..dcd6705734f1856e34fd616ec309a7fdf3db9963 GIT binary patch literal 20367 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 AS^xk5 literal 0 HcmV?d00001 From fa3325580c987769b538a386360b37ce6702b6f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=8F=E5=A4=A7=E8=83=86?= <1101282782@qq.com> Date: Mon, 7 Jul 2025 16:21:01 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E7=BA=BF=E6=A0=B7=E5=BC=8F=EF=BC=88?= =?UTF-8?q?=E6=97=A0=E5=90=8C=E6=AD=A5=E9=97=B4=E8=B7=9D=E8=B0=83=E8=8A=82?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Obj/Base/PolylineObject/_element.js | 24 ++- src/Obj/Base/PolylineObject/index.js | 130 +++++++++++++++- .../FlowDashedLineFlowMaterialProperty.js | 32 +++- .../Materail/LineTextureMaterialProperty.js | 52 ++++--- .../Materail/PolylineFlowMaterialProperty.js | 23 ++- .../PolylineFlowMultMaterialProperty.js | 41 ++++- src/Tools/index.js | 142 +++++++++++++----- static/custom/css/index.css | 6 +- 8 files changed, 373 insertions(+), 77 deletions(-) diff --git a/src/Obj/Base/PolylineObject/_element.js b/src/Obj/Base/PolylineObject/_element.js index dd5d305..383e9bd 100644 --- a/src/Obj/Base/PolylineObject/_element.js +++ b/src/Obj/Base/PolylineObject/_element.js @@ -1,7 +1,7 @@ import { attributeElm, labelStyleElm1, labelStyleElm2 } from '../../Element/elm_html' function html(that) { - return ` + return `
@@ -97,6 +97,28 @@ function html(that) {
+
+
+ 动画顺向 + +
+
+ 动画倍数 +
+ + +
+
+
+ + 间距 +
+ + +
+
+
+
线段缓冲 diff --git a/src/Obj/Base/PolylineObject/index.js b/src/Obj/Base/PolylineObject/index.js index d40ab76..f72b6ec 100644 --- a/src/Obj/Base/PolylineObject/index.js +++ b/src/Obj/Base/PolylineObject/index.js @@ -57,6 +57,10 @@ class PolylineObject extends Base { this.options['nose-to-tail'] = options['nose-to-tail'] || false this.options.smooth = options.smooth || false this.options.extend = options.extend || false + this.options.rotate = options.rotate || true + this.options.space = options.space || 0.1 + this.options.speed = options.speed || 1 + this.options.dashSize = options.dashSize || 0.03 this.options['length-unit'] = options['length-unit'] || '米' this.options['fit-length-unit'] = options['fit-length-unit'] || '米' this.options['extend-width'] = @@ -144,7 +148,7 @@ class PolylineObject extends Base { } set color(v) { this.options.color = v - this.entity.polyline.material = this.getMaterial(v, this.options.type) + this.entity.polyline.material = this.getMaterial(v, this.options.type, this.entity, this.options) if (this._elms.color) { this._elms.color.forEach((item, i) => { let colorPicker = new ewPlugins('colorpicker', { @@ -166,6 +170,48 @@ class PolylineObject extends Base { } } + get speed() { + return this.options.speed + } + + set speed(v) { + this.options.speed = v + this.entity.polyline.material = this.getMaterial(this.options.color, this.options.type, this.entity, this.options) + } + get dashSize() { + return this.options.dashSize + } + + set dashSize(v) { + this.options.dashSize = v + this.entity.polyline.material = this.getMaterial(this.options.color, this.options.type, this.entity, this.options) + } + + get rotate() { + return this.options.rotate + } + + set rotate(v) { + this.options.rotate = v + PolylineObject.closeNodeEdit(this) + this._elms.rotate && + this._elms.rotate.forEach(item => { + item.checked = v + }) + + this.options.rotate = v + this.entity.polyline.material = this.getMaterial(this.options.color, this.options.type, this.entity, this.options) + } + + get space() { + return this.options.space + } + + set space(v) { + this.options.space = v + this.entity.polyline.material = this.getMaterial(this.options.color, this.options.type, this.entity, this.options) + } + get length() { return this.options.length } @@ -298,6 +344,31 @@ class PolylineObject extends Base { name: '流动箭头1', value: '流动箭头1', key: 7 + }, + { + name: '流动箭头2', + value: '流动箭头2', + key: 8 + }, + { + name: '流动箭头3', + value: '流动箭头3', + key: 9 + }, + { + name: '流动箭头4', + value: '流动箭头4', + key: 10 + }, + { + name: '流动箭头5', + value: '流动箭头5', + key: 11 + }, + { + name: '流动箭头6', + value: '流动箭头6', + key: 12 } ] this.options.type = Number(v) @@ -306,6 +377,16 @@ class PolylineObject extends Base { this._elms.lineType && this._elms.lineType.forEach(item => { item.value = lineTypeData[i].value + if (2 < item.value && item.value < 13) {//贴图参数 + document.getElementById('dashTextureDom').style.display = 'flex' + } else { + document.getElementById('dashTextureDom').style.display = 'none' + } + if (2 < item.value && item.value < 5) {//尾迹参数 + document.getElementById('lineSpace').style.display = 'none' + } else { + document.getElementById('lineSpace').style.display = 'flex' + } }) break } @@ -314,7 +395,9 @@ class PolylineObject extends Base { this.entity.polyline && (this.entity.polyline.material = this.getMaterial( this.options.color, - this.options.type + this.options.type, + this.entity, + this.options )) } get noseToTail() { @@ -1177,7 +1260,7 @@ class PolylineObject extends Base { positions: Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArray), width: that.options.width, clampToGround: ground, - material: that.getMaterial(that.options.color, that.options.type), + material: that.getMaterial(that.options.color, that.options.type, that.entity, that.options), zIndex: that.sdk._entityZIndex } }) @@ -1540,6 +1623,31 @@ class PolylineObject extends Base { name: '流动箭头1', value: '流动箭头1', key: 7 + }, + { + name: '流动箭头2', + value: '流动箭头2', + key: 8 + }, + { + name: '流动箭头3', + value: '流动箭头3', + key: 9 + }, + { + name: '流动箭头4', + value: '流动箭头4', + key: 10 + }, + { + name: '流动箭头5', + value: '流动箭头5', + key: 11 + }, + { + name: '流动箭头6', + value: '流动箭头6', + key: 12 } ] let lineTypeDataLegpObject = legp( @@ -1565,6 +1673,18 @@ class PolylineObject extends Base { for (let i = 0; i < lineTypeData.length; i++) { if (lineTypeData[i].value === lineTypeDataLegpElm.value) { this.lineType = lineTypeData[i].key + + //控制参数显隐 + if (2 < this.lineType && this.lineType < 13) {//贴图参数 + document.getElementById('dashTextureDom').style.display = 'flex' + } else { + document.getElementById('dashTextureDom').style.display = 'none' + } + if (2 < this.lineType && this.lineType < 5) {//尾迹参数 + document.getElementById('lineSpace').style.display = 'none' + } else { + document.getElementById('lineSpace').style.display = 'flex' + } break } } @@ -1984,6 +2104,10 @@ class PolylineObject extends Base { this.attributeVr = this.options.attribute.vr.content this.attributeCamera = this.options.attribute.camera.content this.attributeGoods = this.options.attribute.goods.content + this.rotate = this.originalOptions.rotate + this.speed = this.originalOptions.speed + this.dashSize = this.originalOptions.dashSize + this.space = this.originalOptions.space this.cameraSelect && this.cameraSelect() this.goodsSelect && this.goodsSelect() diff --git a/src/Obj/Materail/FlowDashedLineFlowMaterialProperty.js b/src/Obj/Materail/FlowDashedLineFlowMaterialProperty.js index 10d5d6c..b5a4fbe 100644 --- a/src/Obj/Materail/FlowDashedLineFlowMaterialProperty.js +++ b/src/Obj/Materail/FlowDashedLineFlowMaterialProperty.js @@ -8,8 +8,12 @@ function FlowDashedLine() { this._color = undefined; this._speed = undefined; this._uType = undefined; + this._space = undefined; + this._dashSize = undefined; this.color = new Cesium.Color.fromCssColorString(options.color || "rgba(255,255,255,1)"); - this.speed = options.speed || 0.25;//速度 + this.speed = options.speed != undefined ? options.speed : 1.0;//速度 + this.space = options.space || 0.01;//速度 + this.dashSize = options.dashSize || 0.03;//速度 this.uType = options.uType === undefined ? 1 : options.uType;//类型:0:普通流动线 1:虚化虚线 this.lineBackAlpha = options.lineBackAlpha || 0.05; } @@ -43,6 +47,18 @@ function FlowDashedLine() { 10, result.speed ); + result.space = Cesium.Property.getValueOrDefault( + this._space, + time, + 10, + result.space + ); + result.dashSize = Cesium.Property.getValueOrDefault( + this._dashSize, + time, + 10, + result.dashSize + ); result.uType = Cesium.Property.getValueOrDefault( this._uType, time, @@ -69,6 +85,8 @@ function FlowDashedLine() { Object.defineProperties(FlowDashedLineFlowMaterialProperty.prototype, { color: Cesium.createPropertyDescriptor("color"), speed: Cesium.createPropertyDescriptor("speed"), + space: Cesium.createPropertyDescriptor("space"), + dashSize: Cesium.createPropertyDescriptor("dashSize"), uType: Cesium.createPropertyDescriptor("uType"), transparency: Cesium.createPropertyDescriptor("lineBackAlpha"), }); @@ -89,11 +107,13 @@ function FlowDashedLine() { // 计算流动虚线 float dashSize = 0.03; - float gapSize = 0.01; - float progress = fract(czm_frameNumber * 0.01); // 时间控制流动 + // float gapSize = 0.01; + // float dashSize = dashSize; + float gapSize = space; + float progress = fract(speed * czm_frameNumber * 0.01); // 时间控制流动 float pattern = fract(st.x / (dashSize + gapSize) + progress); float dash1 = step(0.1, pattern) - step(0.9, pattern); - float dash2 = smoothstep(0.1, 0.3, pattern) - smoothstep(0.7, 0.9, pattern); + float dash2 = smoothstep(0.0, 0.4, pattern) - smoothstep(0.6, 1.0, pattern); float dash = (float(uType) != 1.0)?dash1:dash2; material.alpha = dash; material.diffuse = color.rgb; @@ -108,7 +128,9 @@ function FlowDashedLine() { type: Cesium.Material.FlowDashedLineMaterialType, uniforms: { color: new Cesium.Color(1.0, 1.0, 1.0, 1.0), - speed: 0.1, + speed: 1, + space: 0.01, + dashSize: 0.03, uType: 1, lineBackAlpha: 0.05, }, diff --git a/src/Obj/Materail/LineTextureMaterialProperty.js b/src/Obj/Materail/LineTextureMaterialProperty.js index 105f391..2fedee1 100644 --- a/src/Obj/Materail/LineTextureMaterialProperty.js +++ b/src/Obj/Materail/LineTextureMaterialProperty.js @@ -7,10 +7,12 @@ function LineTexture() { this._definitionChanged = new Cesium.Event(); this._image = undefined; this._color = undefined; - this._imageW = undefined; + this._speed = undefined; + this._repeat = undefined; this.image = options.image || ""; this.color = new Cesium.Color.fromCssColorString(options.color || "rgba(255,255,255,1)"); - this.imageW = options.imageW || 1; + this.speed = options.speed != undefined ? options.speed : 1.0; + this.repeat = options.repeat || 1.0; } get isConstant() { @@ -41,11 +43,17 @@ function LineTexture() { Cesium.Color.RED, result.color ); - result.imageW = Cesium.Property.getValueOrDefault( - this._imageW, + result.speed = Cesium.Property.getValueOrDefault( + this._speed, time, - 1, - result.imageW + 1.0, + result.speed + ); + result.repeat = Cesium.Property.getValueOrDefault( + this._repeat, + time, + 1.0, + result.repeat ); return result; } @@ -56,7 +64,8 @@ function LineTexture() { (other instanceof LineTextureMaterialProperty && Cesium.Property.equals(this._image, other._image) && Cesium.Property.equals(this._color, other._color) && - Cesium.Property.equals(this._imageW, other._imageW)) + Cesium.Property.equals(this._imageW, other._imageW) && + Cesium.Property.equals(this._speed, other._speed)) ); } } @@ -64,27 +73,27 @@ function LineTexture() { Object.defineProperties(LineTextureMaterialProperty.prototype, { image: Cesium.createPropertyDescriptor("image"), color: Cesium.createPropertyDescriptor("color"), - imageW: Cesium.createPropertyDescriptor("imageW"), + speed: Cesium.createPropertyDescriptor("speed"), + repeat: Cesium.createPropertyDescriptor("repeat"), }); Cesium.LineTextureMaterialProperty = LineTextureMaterialProperty; Cesium.Material.LineTextureMaterialProperty = "LineTextureMaterialProperty"; Cesium.Material.LineTextureMaterialType = "LineTextureMaterialType"; Cesium.Material.LineTextureMaterialSource = ` - #extension GL_OES_standard_derivatives : enable + uniform vec4 color; + uniform sampler2D image; + uniform float speed; + uniform float repeat; czm_material czm_getMaterial(czm_materialInput materialInput) { - czm_material m = czm_getDefaultMaterial(materialInput); - - - vec2 st = materialInput.st * vec2(494/172, 1.0); // 横向重复两次 - vec2 uv = vec2(fract(st.s + uTime*0.1), st.t); - // uv.y = mix(uv.y, 1.0-uv.y, step(0.5, fract(uTime))); // 周期性反转Y轴 - vec4 tex = texture(image, uv); - m.diffuse =(tex.rgb+color.rgb)/2.0; - m.alpha = tex.a * (1.0 - fract(st.t)) * color.a; // 顶部渐隐 - - return m; + czm_material material = czm_getDefaultMaterial(materialInput); + vec2 st = materialInput.st; + st.s *= repeat; // 关键:通过repeat控制纹理密度 + vec4 colorImage = texture2D(image, vec2(fract(st.s + speed*czm_frameNumber* 0.01), st.t)); + material.alpha = colorImage.a * color.a; + material.diffuse = color.rgb; + return material; } `; Cesium.Material._materialCache.addMaterial( @@ -95,7 +104,8 @@ function LineTexture() { uniforms: { color: new Cesium.Color(1.0, 1.0, 1.0, 1.0), image: '', - imageW: 1, + repeat: 1.0, + speed: 1.0, uTime: 1 }, source: Cesium.Material.LineTextureMaterialSource, diff --git a/src/Obj/Materail/PolylineFlowMaterialProperty.js b/src/Obj/Materail/PolylineFlowMaterialProperty.js index 79cb6df..95021fc 100644 --- a/src/Obj/Materail/PolylineFlowMaterialProperty.js +++ b/src/Obj/Materail/PolylineFlowMaterialProperty.js @@ -7,9 +7,11 @@ function PolylineFlow() { this._definitionChanged = new Cesium.Event(); this._color = undefined; this._speed = undefined; + this._rotate = undefined; this.color = new Cesium.Color.fromCssColorString(options.color || "rgba(255,255,255,1)"); - this.speed = options.speed || 0.25;//速度 + this.speed = options.speed != undefined ? options.speed : 1.0;//速度 this.lineBackAlpha = options.lineBackAlpha || 0.05; + this.rotate = options.rotate; } get isConstant() { @@ -41,6 +43,12 @@ function PolylineFlow() { 10, result.speed ); + result.rotate = Cesium.Property.getValueOrDefault( + this._rotate, + time, + true, + result.rotate + ); result.lineBackAlpha = this.lineBackAlpha; result.frameNumber = Cesium.getTimestamp(); return result; @@ -60,6 +68,7 @@ function PolylineFlow() { Object.defineProperties(PolylineFlowMaterialProperty.prototype, { color: Cesium.createPropertyDescriptor("color"), speed: Cesium.createPropertyDescriptor("speed"), + rotate: Cesium.createPropertyDescriptor("rotate"), transparency: Cesium.createPropertyDescriptor("lineBackAlpha"), }); @@ -78,11 +87,16 @@ function PolylineFlow() { //获取st(uv) vec2 st = materialInput.st; //获取当前帧数,10秒内变化0-1 - float time = fract(czm_frameNumber * speed / 60.0); + // float time = fract(czm_frameNumber * speed / 60.0); + float time = fract(abs(speed) * czm_frameNumber * 0.01); //长度1/10 - time = time * (1.0 + 0.1); + // time = time * (1.0 + 0.1); + float staticAlpha = rotate?smoothstep(0.0,1.0, 1.0-st.s) * step(-1.0,-(1.0-st.s)):smoothstep(0.0,1.0, st.s) * step(-1.0,-st.s); + //平滑过渡函数 - float alpha = smoothstep(time-0.1,time,st.s) * step(-time,-st.s); + float alpha1 = smoothstep(time-0.1,time,1.0-st.s) * step(-time,- (1.0-st.s)); + float alpha2 = smoothstep(time-0.1,time,st.s) * step(-time,- st.s); + float alpha =(speed== 0.0)? staticAlpha:(speed < 0.0)?alpha2:alpha1; //光带轨迹(不会完全透明) alpha += lineBackAlpha; material.alpha = alpha; @@ -99,6 +113,7 @@ function PolylineFlow() { uniforms: { color: new Cesium.Color(1.0, 1.0, 1.0, 1.0), speed: 0.1, + rotate: true, lineBackAlpha: 0.05, }, source: Cesium.Material.PolylineFlowMaterialSource, diff --git a/src/Obj/Materail/PolylineFlowMultMaterialProperty.js b/src/Obj/Materail/PolylineFlowMultMaterialProperty.js index c9b64f2..473136c 100644 --- a/src/Obj/Materail/PolylineFlowMultMaterialProperty.js +++ b/src/Obj/Materail/PolylineFlowMultMaterialProperty.js @@ -7,9 +7,11 @@ function PolylineFlowMult() { this._definitionChanged = new Cesium.Event(); this._color = undefined; this._speed = undefined; + this._rotate = undefined; this.color = new Cesium.Color.fromCssColorString(options.color || "rgba(255,255,255,1)"); - this.speed = options.speed || 0.1;//速度 + this.speed = options.speed != undefined ? options.speed : 1.0;//速度 this.lineBackAlpha = options.lineBackAlpha || 0.05; + this.rotate = options.rotate; } get isConstant() { @@ -41,6 +43,12 @@ function PolylineFlowMult() { 10, result.speed ); + result.rotate = Cesium.Property.getValueOrDefault( + this._rotate, + time, + true, + result.rotate + ); result.lineBackAlpha = this.lineBackAlpha; result.frameNumber = Cesium.getTimestamp(); return result; @@ -52,6 +60,7 @@ function PolylineFlowMult() { (other instanceof PolylineFlowMultMaterialProperty && Cesium.Property.equals(this._color, other._color) && Cesium.Property.equals(this._speed, other.speed) && + Cesium.Property.equals(this._rotate, other.rotate) && Cesium.Property.equals(this.lineBackAlpha, other.lineBackAlpha)) ); } @@ -60,6 +69,7 @@ function PolylineFlowMult() { Object.defineProperties(PolylineFlowMultMaterialProperty.prototype, { color: Cesium.createPropertyDescriptor("color"), speed: Cesium.createPropertyDescriptor("speed"), + rotate: Cesium.createPropertyDescriptor("rotate"), transparency: Cesium.createPropertyDescriptor("lineBackAlpha"), }); @@ -80,27 +90,47 @@ function PolylineFlowMult() { float baseTime = fract(czm_frameNumber * speed / 60.0) * 1.1; // 高频时间轴(控制高光点) - float highlightTime = fract(czm_frameNumber * speed * 3.0 / 60.0); + // float highlightTime = fract(czm_frameNumber * speed * 3.0 / 60.0); + float highlightTime = fract(abs(speed) * czm_frameNumber * 0.01); float highlightSpacing = 0.3; // 高光点间隔 // 主光带透明度计算 float mainAlpha = smoothstep(baseTime-0.1, baseTime, st.s) * step(-baseTime, -st.s); // 多高光点计算(3个周期性光斑) - float highlight1 = smoothstep(highlightTime-0.05, highlightTime, st.s) * + float highlight11 = smoothstep(highlightTime-0.05, highlightTime, st.s) * step(-highlightTime, -st.s) * (1.0 - smoothstep(0.0, highlightSpacing, abs(st.s - highlightTime))); - float highlight2 = smoothstep(highlightTime+highlightSpacing-0.05, + float highlight21 = smoothstep(highlightTime+highlightSpacing-0.05, highlightTime+highlightSpacing, st.s) * step(-(highlightTime+highlightSpacing), -st.s) * (1.0 - smoothstep(0.0, highlightSpacing, abs(st.s - (highlightTime+highlightSpacing)))); - float highlight3 = smoothstep(highlightTime+2.0*highlightSpacing-0.05, + float highlight31 = smoothstep(highlightTime+2.0*highlightSpacing-0.05, highlightTime+2.0*highlightSpacing, st.s) * step(-(highlightTime+2.0*highlightSpacing), -st.s) * (1.0 - smoothstep(0.0, highlightSpacing, abs(st.s - (highlightTime+2.0*highlightSpacing)))); + + float highlight12 = smoothstep(highlightTime-0.05, highlightTime, 1.0 - st.s) * + step(-highlightTime, -(1.0-st.s)) * + (1.0 - smoothstep(0.0, highlightSpacing, abs(1.0 - st.s - highlightTime))); + + float highlight22 = smoothstep(highlightTime+highlightSpacing-0.05, + highlightTime+highlightSpacing, 1.0 - st.s) * + step(-(highlightTime+highlightSpacing),-(1.0 - st.s)) * + (1.0 - smoothstep(0.0, highlightSpacing, abs(1.0-st.s - (highlightTime+highlightSpacing)))); + + float highlight32 = smoothstep(highlightTime+2.0*highlightSpacing-0.05, + highlightTime+2.0*highlightSpacing, 1.0 - st.s) * + step(-(highlightTime+2.0*highlightSpacing), -(1.0-st.s)) * + (1.0 - smoothstep(0.0, highlightSpacing, abs(1.0 - st.s - (highlightTime+2.0*highlightSpacing)))); + + + float highlight1 = !rotate?highlight11:highlight12; + float highlight2 = !rotate?highlight21:highlight22; + float highlight3 = !rotate?highlight31:highlight32; // 合并效果 // material.alpha = mainAlpha * 0.7 + // (highlight1 + highlight2 + highlight3) * 0.5 + @@ -120,6 +150,7 @@ function PolylineFlowMult() { uniforms: { color: new Cesium.Color(1.0, 1.0, 1.0, 1.0), speed: 0.1, + rotate: true, lineBackAlpha: 0.05, }, source: Cesium.Material.PolylineFlowMaterialSource, diff --git a/src/Tools/index.js b/src/Tools/index.js index 53c0fe5..6a8e9a4 100644 --- a/src/Tools/index.js +++ b/src/Tools/index.js @@ -10,6 +10,7 @@ import { Proj } from './proj' import { open as projConvertOpen, close as projConvertClose } from './projConvert' import { open as projectionConvertOpen, close as projectionConvertClose } from './projectionConvert' import { setActiveViewer, closeRotateAround, closeViewFollow } from '../Global/global' +import FlowPictureMaterialProperty from '../Obj/Materail/FlowPictureMaterialProperty' class Tools { /** @@ -513,8 +514,11 @@ class Tools { return res } - getMaterial(color = '#2ab0c2', type = 0) { + getMaterial(color = '#2ab0c2', type = 0, entity = null, newParam = {}) { let material = '' + + + switch (Number(type)) { case 1: //虚线 @@ -531,60 +535,51 @@ class Tools { break case 3: //尾迹光线 material = new Cesium.PolylineFlowMaterialProperty({ - color: color + color: color, + speed: newParam.rotate ? newParam.speed : 0 - newParam.speed, + rotate: newParam.rotate }) break case 4: //多尾迹光线 material = new Cesium.PolylineFlowMultMaterialProperty({ - color: color + color: color, + speed: newParam.rotate ? newParam.speed : 0 - newParam.speed, + rotate: newParam.rotate }) break case 5: //普通流动虚线 material = new Cesium.FlowDashedLineFlowMaterialProperty({ color: color, - uType: 0 + uType: 0, + speed: newParam.rotate ? newParam.speed : 0 - newParam.speed, + // dashSize: newParam.dashSize, + space: newParam.space }) break case 6: //流动虚线2 material = new Cesium.FlowDashedLineFlowMaterialProperty({ color: color, - uType: 1 + uType: 1, + speed: newParam.rotate ? newParam.speed : 0 - newParam.speed, + // dashSize: newParam.dashSize, + space: newParam.space }) break case 7: //流动箭头1 - material = new Cesium.LineTextureMaterialProperty({ + case 8: //流动箭头2 + case 9: //流动箭头3 + case 10: //流动箭头4 + case 11: //流动箭头5 + case 12: //流动箭头6 + let param = { color: color, - image: this.getSourceRootPath() + '/img/arrow/2.png', - // imageW: 172 - }) - // let that = this - // var curCanvas = 'a'; - // let i = 0; - // function drawCanvasImage(time, result) { - // let canvas = document.createElement('canvas'); - // canvas.id = "canvas-" + curCanvas; - // // document.getElementById('app').appendChild(canvas) - // // var canvas = document.getElementById("canvas-" + curCanvas); - // let cwidth = 494; - // let cheight = 172; - // var ctx = canvas.getContext("2d"); - // var img = new Image(); - // img.src = that.getSourceRootPath() + '/img/arrow/1.png'; - // ctx.clearRect(0, 0, cwidth, cheight); - // img.onload = function () { - // if (i <= cwidth) { - // ctx.drawImage(img, i, 0); - // } else - // i = 0; - // i += 3; - // } - // curCanvas = curCanvas === 'a' ? 'b' : 'a'; - // return canvas; - // } - // material = new Cesium.ImageMaterialProperty({ - // image: new Cesium.CallbackProperty(drawCanvasImage, false), - // transparent: true - // }) + image: this.getSourceRootPath() + `/img/arrow/${type - 6}.png`, + space: newParam.space, + speed: newParam.speed + } + param.speed = newParam.rotate ? param.speed : 0 - param.speed + this.getFlowTexture(this, param, entity) + break default: material = Cesium.Color.fromCssColorString(color) @@ -592,6 +587,79 @@ class Tools { } return material } + getFlowTexture(that, options, entity) { + + const canvasEle = document.createElement('canvas'); + const ctx = canvasEle.getContext('2d') + const myImg = new Image() + // myImg.src = that.getSourceRootPath() + '/img/arrow/1.png' + myImg.src = options.image + myImg.onload = function () { + if (options.speed > 0 || options.speed == 0) { + canvasEle.width = myImg.width * (options.space + 1) + canvasEle.height = myImg.height + ctx.drawImage(myImg, myImg.width * (options.space / 2), 0) + } else { + ctx.clearRect(0, 0, canvasEle.width, canvasEle.height); + ctx.save(); // 保存当前状态 + canvasEle.width = myImg.width * (options.space + 1) + canvasEle.height = myImg.height + ctx.translate(canvasEle.width / 2, canvasEle.height / 2); // 移动原点至中心 + ctx.rotate(Math.PI); // (弧度制) + ctx.drawImage(myImg, -myImg.width * (options.space / 2), -myImg.height / 2) + ctx.restore(); // 恢复状态 + } + + // let repeat = getRepeat() + // }, false) + entity.polyline.material = new Cesium.LineTextureMaterialProperty( + { + color: options.color, + // image: options.image, + image: canvasEle, + speed: options.speed, + // repeat: repeat + repeat: new Cesium.CallbackProperty(function () { + // function getRepeat() { + var positionProperty = entity.polyline.positions; + var positions = positionProperty.getValue(that.sdk.viewer.clock.currentTime); + + if (!Cesium.defined(positions)) { + // return new Cesium.Cartesian2(1.0, 1.0); + return 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 / entity.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 / ((myImg.width / myImg.height * 5) + 1); + repeatX *= groundResolution / cameraHeight / (options.space * (canvasEle.width / canvasEle.height * 5) + 1); + // if (repeatX < 3) { + // repeatX = 3 + // } + // return new Cesium.Cartesian2(repeatX, 1.0); + return repeatX; + }) + } + ) + } + } /*创建直箭头图片*/ create_arrow1_picture(color) { diff --git a/static/custom/css/index.css b/static/custom/css/index.css index bf4ec1e..eadf7ca 100644 --- a/static/custom/css/index.css +++ b/static/custom/css/index.css @@ -2594,7 +2594,9 @@ .YJ-custom-base-dialog.polyline>.content { width: 580px; } - +.YJ-custom-base-dialog.polyline>.content>div #dashTextureDom { + display: none; +} .YJ-custom-base-dialog.polyline>.content>div .row .col { margin: 0 10px; } @@ -2643,6 +2645,8 @@ max-height: 185px; } + + /* 贴地图片 */ .YJ-custom-base-dialog.ground-image>.content { width: 500px; From dd003aa00dc9b95d12604394d3363ecb9ac0b5aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=8F=E5=A4=A7=E8=83=86?= <1101282782@qq.com> Date: Mon, 7 Jul 2025 17:17:40 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E8=B4=B4=E5=9B=BE=E5=8F=8D=E5=90=91bug?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Tools/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Tools/index.js b/src/Tools/index.js index 6a8e9a4..d8cc632 100644 --- a/src/Tools/index.js +++ b/src/Tools/index.js @@ -606,7 +606,8 @@ class Tools { canvasEle.height = myImg.height ctx.translate(canvasEle.width / 2, canvasEle.height / 2); // 移动原点至中心 ctx.rotate(Math.PI); // (弧度制) - ctx.drawImage(myImg, -myImg.width * (options.space / 2), -myImg.height / 2) + ctx.translate(-canvasEle.width / 2, -canvasEle.height / 2); // 移回原点 + ctx.drawImage(myImg, -myImg.width * (options.space / 2), 0) ctx.restore(); // 恢复状态 } From 45f2d6f4ebbabd259189254420eca98c80ac50c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=8F=E5=A4=A7=E8=83=86?= <1101282782@qq.com> Date: Wed, 9 Jul 2025 11:26:33 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=B4=E8=B7=9D?= =?UTF-8?q?=E5=A4=A7=E5=80=BC=20=E7=BC=93=E5=86=B2=E5=8C=BAbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Obj/Base/PolylineObject/_element.js | 11 +++++----- src/Obj/Base/PolylineObject/eventBinding.js | 20 +++++++++-------- src/Obj/Base/PolylineObject/index.js | 13 +++++++---- .../FlowDashedLineFlowMaterialProperty.js | 22 ++++++++++--------- .../Materail/LineTextureMaterialProperty.js | 5 ++++- .../Materail/PolylineFlowMaterialProperty.js | 7 ++++-- .../PolylineFlowMultMaterialProperty.js | 6 +++-- src/Tools/index.js | 6 +++-- 8 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/Obj/Base/PolylineObject/_element.js b/src/Obj/Base/PolylineObject/_element.js index 383e9bd..1f01892 100644 --- a/src/Obj/Base/PolylineObject/_element.js +++ b/src/Obj/Base/PolylineObject/_element.js @@ -103,20 +103,19 @@ function html(that) {
- 动画倍数 + 动画时长
+ s
- - 间距 -
- + 间距 +
+
-
diff --git a/src/Obj/Base/PolylineObject/eventBinding.js b/src/Obj/Base/PolylineObject/eventBinding.js index bcbf281..7a665f8 100644 --- a/src/Obj/Base/PolylineObject/eventBinding.js +++ b/src/Obj/Base/PolylineObject/eventBinding.js @@ -22,7 +22,7 @@ class eventBinding { let isEvent = false let removeName = [] if (!elements[i] || !elements[i].attributes) { - continue + continue } for (let m of elements[i].attributes) { switch (m.name) { @@ -38,13 +38,15 @@ class eventBinding { 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)) { + if ((e.target.max) && value > Number(e.target.max)) { value = Number(e.target.max) + e.target.value = value } - if((e.target.min) && value { let value = e.target.value - if(e.target.type == 'number' && value!='') { + if (e.target.type == 'number' && value != '') { value = Number(value) e.target.value = value } @@ -97,7 +99,7 @@ class eventBinding { } // elements[i].attributes[m] = undefined } - for(let n=0;n { item.value = v @@ -1681,9 +1684,11 @@ class PolylineObject extends Base { document.getElementById('dashTextureDom').style.display = 'none' } if (2 < this.lineType && this.lineType < 5) {//尾迹参数 - document.getElementById('lineSpace').style.display = 'none' + document.getElementsByClassName('lineSpace')[0].style.display = 'none' + document.getElementsByClassName('lineSpace')[1].style.display = 'none' } else { - document.getElementById('lineSpace').style.display = 'flex' + document.getElementsByClassName('lineSpace')[0].style.display = 'flex' + document.getElementsByClassName('lineSpace')[1].style.display = 'flex' } break } diff --git a/src/Obj/Materail/FlowDashedLineFlowMaterialProperty.js b/src/Obj/Materail/FlowDashedLineFlowMaterialProperty.js index b5a4fbe..546cda6 100644 --- a/src/Obj/Materail/FlowDashedLineFlowMaterialProperty.js +++ b/src/Obj/Materail/FlowDashedLineFlowMaterialProperty.js @@ -12,7 +12,7 @@ function FlowDashedLine() { this._dashSize = undefined; this.color = new Cesium.Color.fromCssColorString(options.color || "rgba(255,255,255,1)"); this.speed = options.speed != undefined ? options.speed : 1.0;//速度 - this.space = options.space || 0.01;//速度 + this.space = options.space || 0.0;//速度 this.dashSize = options.dashSize || 0.03;//速度 this.uType = options.uType === undefined ? 1 : options.uType;//类型:0:普通流动线 1:虚化虚线 this.lineBackAlpha = options.lineBackAlpha || 0.05; @@ -105,15 +105,16 @@ function FlowDashedLine() { czm_material material = czm_getDefaultMaterial(materialInput); vec2 st = materialInput.st; - // 计算流动虚线 - float dashSize = 0.03; - // float gapSize = 0.01; - // float dashSize = dashSize; + float dashSize = 0.1; float gapSize = space; - float progress = fract(speed * czm_frameNumber * 0.01); // 时间控制流动 - float pattern = fract(st.x / (dashSize + gapSize) + progress); - float dash1 = step(0.1, pattern) - step(0.9, pattern); - float dash2 = smoothstep(0.0, 0.4, pattern) - smoothstep(0.6, 1.0, pattern); + // speed现在表示完成一次完整动画循环的秒数 + float progress = speed==0.0 ? 0.0 : fract(frameNumber / 1000.0 / speed); + float pattern = fract(st.x / dashSize * (1.0 + gapSize) + progress / dashSize * (1.0 + gapSize)); + float dash1 = step(0.0, pattern) - step(1.0/(1.0 + gapSize), pattern); + float dash2 = smoothstep(0.0, 0.2, pattern) - + smoothstep(1.0/(1.0 + gapSize), + 1.0/(1.0 + gapSize) + 0.2, + pattern); float dash = (float(uType) != 1.0)?dash1:dash2; material.alpha = dash; material.diffuse = color.rgb; @@ -129,8 +130,9 @@ function FlowDashedLine() { uniforms: { color: new Cesium.Color(1.0, 1.0, 1.0, 1.0), speed: 1, - space: 0.01, + space: 0.0, dashSize: 0.03, + frameNumber: Cesium.getTimestamp(), uType: 1, lineBackAlpha: 0.05, }, diff --git a/src/Obj/Materail/LineTextureMaterialProperty.js b/src/Obj/Materail/LineTextureMaterialProperty.js index 2fedee1..5bed3ec 100644 --- a/src/Obj/Materail/LineTextureMaterialProperty.js +++ b/src/Obj/Materail/LineTextureMaterialProperty.js @@ -55,6 +55,7 @@ function LineTexture() { 1.0, result.repeat ); + result.frameNumber = Cesium.getTimestamp(); return result; } @@ -90,7 +91,8 @@ function LineTexture() { czm_material material = czm_getDefaultMaterial(materialInput); vec2 st = materialInput.st; st.s *= repeat; // 关键:通过repeat控制纹理密度 - vec4 colorImage = texture2D(image, vec2(fract(st.s + speed*czm_frameNumber* 0.01), st.t)); + // vec4 colorImage = texture2D(image, vec2(fract(st.s + speed*czm_frameNumber* 0.01), st.t)); + vec4 colorImage = speed==0.0?texture2D(image, vec2(fract(st.s), st.t)):texture2D(image, vec2(fract(st.s + frameNumber / 1000.0 / speed * repeat ), st.t)); material.alpha = colorImage.a * color.a; material.diffuse = color.rgb; return material; @@ -106,6 +108,7 @@ function LineTexture() { image: '', repeat: 1.0, speed: 1.0, + frameNumber: Cesium.getTimestamp(), uTime: 1 }, source: Cesium.Material.LineTextureMaterialSource, diff --git a/src/Obj/Materail/PolylineFlowMaterialProperty.js b/src/Obj/Materail/PolylineFlowMaterialProperty.js index 95021fc..5621365 100644 --- a/src/Obj/Materail/PolylineFlowMaterialProperty.js +++ b/src/Obj/Materail/PolylineFlowMaterialProperty.js @@ -50,7 +50,8 @@ function PolylineFlow() { result.rotate ); result.lineBackAlpha = this.lineBackAlpha; - result.frameNumber = Cesium.getTimestamp(); + result.frameTime = Cesium.getTimestamp(); + // result.frameNumber = Cesium.getTimestamp(); return result; } @@ -88,7 +89,8 @@ function PolylineFlow() { vec2 st = materialInput.st; //获取当前帧数,10秒内变化0-1 // float time = fract(czm_frameNumber * speed / 60.0); - float time = fract(abs(speed) * czm_frameNumber * 0.01); + // float time = fract(abs(speed) * czm_frameNumber * 0.01); + float time = fract(frameTime / 1000.0 / abs(speed)); //长度1/10 // time = time * (1.0 + 0.1); float staticAlpha = rotate?smoothstep(0.0,1.0, 1.0-st.s) * step(-1.0,-(1.0-st.s)):smoothstep(0.0,1.0, st.s) * step(-1.0,-st.s); @@ -114,6 +116,7 @@ function PolylineFlow() { color: new Cesium.Color(1.0, 1.0, 1.0, 1.0), speed: 0.1, rotate: true, + frameTime: Cesium.getTimestamp(), lineBackAlpha: 0.05, }, source: Cesium.Material.PolylineFlowMaterialSource, diff --git a/src/Obj/Materail/PolylineFlowMultMaterialProperty.js b/src/Obj/Materail/PolylineFlowMultMaterialProperty.js index 473136c..8e37538 100644 --- a/src/Obj/Materail/PolylineFlowMultMaterialProperty.js +++ b/src/Obj/Materail/PolylineFlowMultMaterialProperty.js @@ -50,7 +50,7 @@ function PolylineFlowMult() { result.rotate ); result.lineBackAlpha = this.lineBackAlpha; - result.frameNumber = Cesium.getTimestamp(); + result.frameTime = Cesium.getTimestamp(); return result; } @@ -91,7 +91,8 @@ function PolylineFlowMult() { // 高频时间轴(控制高光点) // float highlightTime = fract(czm_frameNumber * speed * 3.0 / 60.0); - float highlightTime = fract(abs(speed) * czm_frameNumber * 0.01); + // float highlightTime = fract(abs(speed) * czm_frameNumber * 0.01); + float highlightTime = fract(frameTime / 1000.0 / abs(speed)); float highlightSpacing = 0.3; // 高光点间隔 // 主光带透明度计算 @@ -151,6 +152,7 @@ function PolylineFlowMult() { color: new Cesium.Color(1.0, 1.0, 1.0, 1.0), speed: 0.1, rotate: true, + frameTime: Cesium.getTimestamp(), lineBackAlpha: 0.05, }, source: Cesium.Material.PolylineFlowMaterialSource, diff --git a/src/Tools/index.js b/src/Tools/index.js index d8cc632..3cf0284 100644 --- a/src/Tools/index.js +++ b/src/Tools/index.js @@ -555,6 +555,7 @@ class Tools { // dashSize: newParam.dashSize, space: newParam.space }) + console.log(newParam.space) break case 6: //流动虚线2 material = new Cesium.FlowDashedLineFlowMaterialProperty({ @@ -595,19 +596,20 @@ class Tools { // myImg.src = that.getSourceRootPath() + '/img/arrow/1.png' myImg.src = options.image myImg.onload = function () { + options.space = Math.max(0.1, options.space); if (options.speed > 0 || options.speed == 0) { canvasEle.width = myImg.width * (options.space + 1) canvasEle.height = myImg.height ctx.drawImage(myImg, myImg.width * (options.space / 2), 0) } else { ctx.clearRect(0, 0, canvasEle.width, canvasEle.height); - ctx.save(); // 保存当前状态 canvasEle.width = myImg.width * (options.space + 1) canvasEle.height = myImg.height + ctx.save(); // 保存当前状态 ctx.translate(canvasEle.width / 2, canvasEle.height / 2); // 移动原点至中心 ctx.rotate(Math.PI); // (弧度制) ctx.translate(-canvasEle.width / 2, -canvasEle.height / 2); // 移回原点 - ctx.drawImage(myImg, -myImg.width * (options.space / 2), 0) + ctx.drawImage(myImg, myImg.width * (options.space / 2), 0) ctx.restore(); // 恢复状态 }