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 0000000..a959a24 Binary files /dev/null and b/static/img/arrow/1.png differ diff --git a/static/img/arrow/2.png b/static/img/arrow/2.png new file mode 100644 index 0000000..1c1985a Binary files /dev/null and b/static/img/arrow/2.png differ diff --git a/static/img/arrow/3.png b/static/img/arrow/3.png new file mode 100644 index 0000000..895389c Binary files /dev/null and b/static/img/arrow/3.png differ diff --git a/static/img/arrow/4.png b/static/img/arrow/4.png new file mode 100644 index 0000000..dcd6705 Binary files /dev/null and b/static/img/arrow/4.png differ diff --git a/static/img/arrow/5.png b/static/img/arrow/5.png new file mode 100644 index 0000000..f444e83 Binary files /dev/null and b/static/img/arrow/5.png differ diff --git a/static/img/arrow/6.png b/static/img/arrow/6.png new file mode 100644 index 0000000..a1b7f9a Binary files /dev/null and b/static/img/arrow/6.png differ