From dae8d5ad8df88593261f6df3697fbfe2cab3047b Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Wed, 11 Jun 2025 17:13:00 +0800
Subject: [PATCH] feat:后台管理通用航线加载相关方法、hook、航线材质等处理
---
src/hooks/useRouteLine/useRouteLine.js | 225 +++++++++++++++
src/utils/cesium/Material/index.js | 442 +++++++++++++++++++++++++++++
src/utils/util.js | 26 +
src/hooks/common.js | 172 +++++++++++
4 files changed, 862 insertions(+), 3 deletions(-)
diff --git a/src/hooks/common.js b/src/hooks/common.js
new file mode 100644
index 0000000..aeb93be
--- /dev/null
+++ b/src/hooks/common.js
@@ -0,0 +1,172 @@
+import * as Cesium from 'cesium'
+
+import { analyzeKmzFile, removeTextKey, XMLToJSON } from '@/utils/cesium/kmz'
+import { camelToSnake } from '@/utils/util'
+import _, { cloneDeep, throttle } from 'lodash'
+import * as turf from '@turf/turf'
+
+/**
+ * 判断action里面是否有key
+ * @param action
+ * @param key
+ * @returns {{hasKey: boolean, val: *}|{hasKey: boolean, val: null}}
+ */
+export function actionHasKey (action, key) {
+ const curActionParams = action?.action_actuator_func_param
+ const val = curActionParams?.[key]
+ if (val !== undefined) {
+ return { hasKey: true, val }
+ } else {
+ return { hasKey: false, val: null }
+ }
+}
+
+// 解析kmz文件的时候处理pointList 写在这里
+export function handlePointListForKmz ({ placemark, startPoint, execute_height_mode, auto_flight_speed }) {
+ if (!placemark?.length) return []
+ const isWGS84 = execute_height_mode === 'WGS84'
+ const list = placemark.map(item => {
+ const [longitude, latitude] = item.point.coordinates.trim().split(',')
+ let action_modes = item?.action_group?.action || []
+ action_modes = Array.isArray(action_modes) ? action_modes : [action_modes]
+ return {
+ longitude: _.round(longitude, 8),
+ latitude: _.round(latitude, 8),
+ height: isWGS84 ? item.execute_height : item.execute_height + startPoint.height,
+ waypoint_speed: item.waypoint_speed,
+ action_modes,
+ }
+ })
+ const pointStart = {
+ ...startPoint,
+ flyRotateYaw: 0,
+ pointType: 'start',
+ waypoint_speed: auto_flight_speed,
+ heading: 0, // 椎体 heading
+ arrowHeading: 0, // 飞行器 heading
+ pitch: 0, //椎体俯仰角
+ fov: 19.5, // 这个是椎体的展示截面大小
+ }
+ list.forEach(item => {
+ item?.action_modes?.forEach(item1 => {
+ let { hasKey: has_focal_length, val: focal_length } = actionHasKey(item1, 'focal_length')
+ // 处理focalLength需要/24 focalLength可能是‘1,024’
+ if (has_focal_length && focal_length) {
+ focal_length = typeof focal_length === 'string' ? focal_length.replace(/,/g, '') : focal_length
+ item1.action_actuator_func_param.focal_length = Number(focal_length) / 24
+ }
+ })
+ item.arrowHeading = 0
+ })
+ return [pointStart, ...list]
+}
+
+export async function analysisPointLineKmz (kmzUrl) {
+ const res = await analyzeKmzFile(`${kmzUrl}?_t=${new Date().getTime()}`)
+ const templateXML = await res.fileInfoObj['wpmz/template.kml']
+ const waylinesXML = await res.fileInfoObj['wpmz/waylines.wpml']
+ const templateXMLJSON = XMLToJSON(templateXML)?.['Document']
+ const waylinesXMLJSON = XMLToJSON(waylinesXML)?.['Document']
+ const templateXMLObj = camelToSnake(removeTextKey(templateXMLJSON))
+ const waylinesXMLObj = camelToSnake(removeTextKey(waylinesXMLJSON))
+ const {
+ mission_config: {
+ take_off_ref_point,
+ drone_info: { drone_enum_value, drone_sub_enum_value } = {}
+ } = {},
+ folder: {
+ payload_param: { image_format } = {},
+ placemark: {
+ polygon
+ },
+ global_height, auto_flight_speed,
+ template_type: templateType
+ } = {},
+ } = templateXMLObj
+
+ const {
+ mission_config: { take_off_security_height } = {},
+ folder: polygonPointFolder
+ } = waylinesXMLObj
+
+ let execute_height_mode = '', pointPlacemark
+
+ if (templateType === "mapping3d") {
+ execute_height_mode = polygonPointFolder[0].execute_height_mode
+ pointPlacemark = polygonPointFolder.map(i => i.placemark)
+ } else {
+ execute_height_mode = polygonPointFolder.execute_height_mode
+ pointPlacemark = polygonPointFolder.placemark
+ }
+
+ const [latitude, longitude, height] = take_off_ref_point.split(',').map(item => _.round(item, 6))
+ let startPoint = { latitude, longitude, height }
+
+ // 取出点位
+ const coordinates = polygon?.outer_boundary_is.linear_ring
+ .coordinates?.split('\n') || []
+
+ // 数组转换
+ let polygonList = coordinates.map((coordinate) =>
+ coordinate
+ .replace(/\s+/g, '')
+ .split(',')
+ .map((v) => Number(v)),
+ )
+
+ polygonList.pop()
+
+ return {
+ image_format,
+ startPoint,
+ global_height,
+ auto_flight_speed,
+ take_off_ref_point,
+ drone_enum_value,
+ drone_sub_enum_value,
+ take_off_security_height,
+ execute_height_mode,
+ templateType,
+ pointPlacemark,
+ polygonList
+ }
+}
+
+// 获取连接地面线
+export function getPolyLine (viewer, pointList, index) {
+ return {
+ positions: new Cesium.CallbackProperty(() => {
+ const point = pointList.value[index]
+ const pointPosition = Cesium.Cartesian3.fromDegrees(point.longitude, point.latitude, point.height)
+ if (!pointPosition) return []
+ // 获取点的位置
+ const cartographic = Cesium.Cartographic.fromCartesian(pointPosition)
+ // 获取地形高度
+ const terrainHeight = viewer.scene.globe.getHeight(cartographic) || 0
+ // 创建地面点位置
+ const groundPosition = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, terrainHeight)
+
+ return [pointPosition, groundPosition]
+ }, false),
+ width: 0.5,
+ material: Cesium.Color.WHITE,
+ }
+}
+
+export function getNewPolygonData (data) {
+ const polygonData = data.reduce((pre, cur) => {
+ let arr = cur.data.map(i => {
+ if ('point' in i) return i.point.coordinates.split(',')
+ if ('Point' in i) {
+ if (_.isObject(i.Point.coordinates) && '#text' in i.Point.coordinates) return i.Point.coordinates['#text'].split(',')
+ return i.Point.coordinates.split(',')
+ }
+ }).map(i => turf.point([Number(i[0]), Number(i[1])]))
+
+ return pre.push(...arr), pre
+ }, [])
+
+ const hull = turf.convex(turf.featureCollection(polygonData))
+
+ return hull.geometry.coordinates[0]
+}
\ No newline at end of file
diff --git a/src/hooks/useRouteLine/useRouteLine.js b/src/hooks/useRouteLine/useRouteLine.js
new file mode 100644
index 0000000..3397ee7
--- /dev/null
+++ b/src/hooks/useRouteLine/useRouteLine.js
@@ -0,0 +1,225 @@
+import * as Cesium from 'cesium'
+
+import {
+ analysisPointLineKmz,
+ handlePointListForKmz,
+ getPolyLine,
+ getNewPolygonData,
+} from '@/hooks/common'
+
+import rwqfdImg from '@/assets/images/signMachineNest/rwqfd.png'
+import endPointImg from '@/assets/images/EndPointicon.png'
+
+import { ArrowLineMaterialProperty } from '@/utils/cesium/Material'
+import { flyVisual } from '@/utils/cesium/mapUtil'
+
+let arrowLineMaterialProperty = new ArrowLineMaterialProperty({
+ color: new Cesium.Color(128 / 255, 215 / 255, 255 / 255, 1),
+ directionColor: new Cesium.Color(1, 1, 1, 1),
+ outlineColor: new Cesium.Color(1, 1, 1, 1),
+ outlineWidth: 0,
+ speed: 5,
+})
+
+export function useRouteLine () {
+ let viewer = null
+ let previewDataSource = null
+
+ const curRouteLineData = ref({
+ data: [],
+ polygonList: '',
+ templateType: '',
+ startPoint: '',
+ execute_height_mode: '',
+ auto_flight_speed: '',
+ wayline_type: '',
+ })
+
+ const routeLineListClick = async data => {
+ if (data.select) return
+ curRouteLineData.value.data.forEach(i => (i.select = false))
+ data.select = true
+ await renderRouteLine(data.data)
+ }
+
+ async function renderPreviewLine (kmzUrl, wayline_type, cb = () => { }) {
+ resetCurRouteLineData()
+
+ const { pointPlacemark, polygonList, templateType, startPoint, execute_height_mode, auto_flight_speed } =
+ await analysisPointLineKmz(kmzUrl)
+
+ curRouteLineData.value = {
+ polygonList,
+ templateType,
+ startPoint,
+ execute_height_mode,
+ auto_flight_speed,
+ wayline_type,
+ }
+
+ cb(curRouteLineData.value.polygonList.map(item => [Number(item[0]), Number(item[1])]))
+
+ if (templateType === 'mapping3d') {
+ curRouteLineData.value.data = pointPlacemark.map(item => ({
+ data: item,
+ select: false,
+ }))
+ routeLineListClick(curRouteLineData.value.data[0])
+ } else {
+ curRouteLineData.value.data = []
+ await renderRouteLine(pointPlacemark)
+ }
+ }
+
+ async function renderRouteLine (data) {
+ if (previewDataSource) {
+ removePreviewLine()
+ } else {
+ previewDataSource = new Cesium.CustomDataSource('previewDataSource')
+ await viewer.dataSources.add(previewDataSource)
+ }
+
+ let lineMaterial = [2, 4].includes(Number(curRouteLineData.value.wayline_type))
+ ? Cesium.Color.fromCssColorString('#00D690')
+ : arrowLineMaterialProperty
+
+ if ([2, 4].includes(Number(curRouteLineData.value.wayline_type))) {
+ if (curRouteLineData.value.templateType === 'mapping3d') {
+ let newPolygonData = getNewPolygonData(curRouteLineData.value.data)
+
+ let newPolygonDisposePositions = newPolygonData.map(i =>
+ Cesium.Cartesian3.fromDegrees(Number(i[0]), Number(i[1]))
+ )
+
+ previewDataSource.entities.add({
+ polygon: {
+ hierarchy: new Cesium.CallbackProperty(() => {
+ return new Cesium.PolygonHierarchy(newPolygonDisposePositions)
+ }, false),
+ material: Cesium.Color.fromBytes(255, 228, 22, 44),
+ outline: false,
+ outlineWidth: 2,
+ heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+ },
+ })
+ }
+
+ let polygonDisposePositions = curRouteLineData.value.polygonList.map(item => {
+ return Cesium.Cartesian3.fromDegrees(Number(item[0]), Number(item[1]), Number(item[2]))
+ })
+
+ previewDataSource.entities.add({
+ polygon: {
+ hierarchy: new Cesium.CallbackProperty(() => {
+ return new Cesium.PolygonHierarchy(polygonDisposePositions)
+ }, false),
+ material: Cesium.Color.fromBytes(45, 140, 240, 99),
+ outline: false,
+ outlineWidth: 2,
+ heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+ },
+
+ polyline: {
+ width: 2,
+ material: Cesium.Color.fromBytes(45, 140, 240, 255),
+ clampToGround: true,
+ positions: new Cesium.CallbackProperty(() => {
+ return [...polygonDisposePositions, polygonDisposePositions[0]]
+ }, false),
+ },
+ })
+ }
+
+
+
+ let pointList = handlePointListForKmz({
+ placemark: data,
+ startPoint: curRouteLineData.value.startPoint,
+ execute_height_mode: curRouteLineData.value.execute_height_mode,
+ auto_flight_speed: curRouteLineData.value.auto_flight_speed,
+ })
+
+ pointList.shift()
+
+ const routePositions = pointList.map(i => Cesium.Cartesian3.fromDegrees(Number(i.longitude), Number(i.latitude), Number(i.height)))
+
+ previewDataSource.entities.add({
+ polyline: {
+ width: 4,
+ positions: routePositions,
+ material: lineMaterial,
+ clampToGround: false,
+ },
+ })
+
+ // 落点线
+ ; (pointList || [])?.forEach((item, index) => {
+ const topPosition = Cesium.Cartesian3.fromDegrees(Number(item.longitude), Number(item.latitude), Number(item.height))
+ let setting = {
+ position: topPosition,
+ polyline: getPolyLine(viewer, { value: pointList }, index),
+ }
+ previewDataSource.entities.add(setting)
+ })
+
+ // 终点
+ previewDataSource.entities.add({
+ position: routePositions[routePositions.length - 1],
+ billboard: {
+ image: new Cesium.ConstantProperty(endPointImg),
+ width: 30,
+ height: 30,
+ verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 底部对齐
+ },
+ })
+ // 起点
+ previewDataSource.entities.add({
+ position: routePositions[0],
+ billboard: {
+ image: rwqfdImg,
+ width: 50,
+ height: 50,
+ },
+ })
+
+ flyVisual(
+ pointList.map(i => [Number(i.longitude), Number(i.latitude), Number(i.height)]),
+ viewer,
+ 20
+ )
+ }
+
+ function removePreviewLine () {
+ previewDataSource?.entities.removeAll()
+ }
+
+ function resetCurRouteLineData () {
+ curRouteLineData.value = {
+ data: [],
+ polygonList: '',
+ templateType: '',
+ startPoint: '',
+ execute_height_mode: '',
+ auto_flight_speed: '',
+ wayline_type: '',
+ }
+ }
+
+ const initViewer = (v) => {
+ viewer = v
+ }
+
+ onBeforeUnmount(() => {
+ resetCurRouteLineData()
+ removePreviewLine()
+ })
+
+ return {
+ curRouteLineData,
+ routeLineListClick,
+ initViewer,
+ renderPreviewLine,
+ removePreviewLine,
+ resetCurRouteLineData
+ }
+}
\ No newline at end of file
diff --git a/src/utils/cesium/Material/index.js b/src/utils/cesium/Material/index.js
new file mode 100644
index 0000000..f96f7a8
--- /dev/null
+++ b/src/utils/cesium/Material/index.js
@@ -0,0 +1,442 @@
+import * as Cesium from 'cesium'
+
+// 多边形渐变材质
+let pM = "PolyGradientMaterial"
+Cesium.Material._materialCache.addMaterial(pM, {
+ strict: true,
+ fabric: {
+ type: pM,
+ uniforms: {
+ color: new Cesium.Color(1.0, 1.0, 0.0, 0.5),
+ diffusePower: 1.6,
+ alphaPower: 1.5,
+ center: new Cesium.Cartesian2(0.5, 0.5),
+ isInner: false,
+ globalAlpha: 1.0,
+ },
+ source: `
+ uniform vec4 color;
+ uniform float diffusePower;
+ uniform float alphaPower;
+ uniform float globalAlpha;
+ uniform vec2 center;
+ uniform bool isInner;
+
+ czm_material czm_getMaterial(czm_materialInput materialInput) {
+ czm_material material = czm_getDefaultMaterial(materialInput);
+ vec2 st = materialInput.st;
+ float alphaMars3D = distance(st, center);
+
+ if(isInner) {
+ material.alpha = (1.0 - (color.a * alphaMars3D * alphaPower)) * globalAlpha;
+ if(material.alpha < 0.0) material.alpha = 0.0;
+ } else {
+ material.alpha = color.a * alphaMars3D * alphaPower * globalAlpha;
+ }
+
+ material.diffuse = color.rgb * diffusePower;
+ return material;
+ }
+ `,
+ },
+ translucent: true,
+})
+class MaterialProperty {
+ constructor(options = {}) {
+ this._definitionChanged = new Cesium.Event()
+
+ this._color = undefined
+ this._glowPower = undefined
+ this._taperPower = undefined
+ this._directionColor = undefined
+ this._outlineColor = undefined
+ this._outlineWidth = undefined
+ this._opacity = undefined
+ this._alphaPower = undefined
+ this._speed = undefined
+
+ this.color = options.color || Cesium.Color.fromBytes(0, 255, 255, 255)
+ this.glowPower = .25
+ this.taperPower = 1
+ this.directionColor = options.directionColor || Cesium.Color.fromBytes(255, 255, 255, 255)
+ this.outlineColor = options.outlineColor || Cesium.Color.fromBytes(255, 255, 255, 255)
+ this.outlineWidth = 0
+ this.opacity = options.opacity || 0.5
+ this.alphaPower = options.alphaPower || 1.5
+ this.speed = options.speed || 5
+ }
+
+ get isConstant () {
+ return false
+ }
+
+ get definitionChanged () {
+ return this._definitionChanged
+ }
+
+ getType (time) {
+ return null
+ }
+
+ getValue (time, result) {
+ result = Cesium.defaultValue(result, {})
+ return result
+ }
+
+ equals (other) {
+ return this === other
+ }
+}
+class PolyGradientMaterial extends MaterialProperty {
+ constructor(options = {}) {
+ super(options)
+ }
+
+ getType (time) {
+ return pM
+ }
+
+ getValue (time, result) {
+ if (!result) {
+ result = {}
+ }
+
+ result.color = Cesium.Property.getValueOrUndefined(this._color, time)
+ result.globalAlpha = Cesium.Property.getValueOrUndefined(this._opacity, time)
+ result.alphaPower = Cesium.Property.getValueOrUndefined(this._alphaPower, time)
+ return result
+ }
+
+ equals (other) {
+ return (
+ this === other ||
+ (other instanceof PolyGradientMaterial &&
+ Cesium.Property.equals(this._color, other._color) &&
+ Cesium.Property.equals(this._opacity, other._opacity) &&
+ Cesium.Property.equals(this._alphaPower, other._alphaPower))
+ )
+ }
+}
+
+Object.defineProperties(PolyGradientMaterial.prototype, {
+ color: Cesium.createPropertyDescriptor('color'),
+ opacity: Cesium.createPropertyDescriptor('opacity'),
+ alphaPower: Cesium.createPropertyDescriptor('alphaPower'),
+})
+
+// 轨迹线材质
+let lT = "LineTrailMaterial"
+Cesium.Material._materialCache.addMaterial(lT, {
+ fabric: {
+ uniforms: {
+ color: new Cesium.Color(1.0, 1.0, 0.0, 0.7),
+ bgColor: new Cesium.Color(0.0, 1.0, 0.0, 0.0),
+ speed: 5,
+ globalAlpha: 1.0
+ },
+ source: `
+ uniform vec4 bgColor;
+ uniform vec4 color;
+ uniform float speed;
+ uniform float globalAlpha;
+
+ czm_material czm_getMaterial(czm_materialInput materialInput) {
+ czm_material material = czm_getDefaultMaterial(materialInput);
+ vec2 st = materialInput.st;
+ float time = fract(czm_frameNumber * speed / 1000.0);
+ vec3 colorMars3D = color.rgb;
+
+ if (st.t > 0.45 && st.t < 0.55) {
+ colorMars3D = vec3(1.0);
+ }
+
+ material.alpha = color.a * 1.5 * smoothstep(0.0, 1.0, fract(st.s - time));
+ material.diffuse = max(colorMars3D.rgb * material.alpha, colorMars3D.rgb);
+
+ if (material.alpha < bgColor.a) {
+ material.alpha = bgColor.a;
+ material.diffuse = bgColor.rgb;
+ }
+
+ material.alpha = material.alpha * globalAlpha;
+ return material;
+ }
+ `
+ },
+ translucent: true
+})
+class LineTrailMaterial extends MaterialProperty {
+ constructor(options = {}) {
+ super(options)
+ }
+
+ getType (time) {
+ return lT
+ }
+
+ getValue (time, result) {
+ if (!result) {
+ result = {}
+ }
+
+ result.color = Cesium.Property.getValueOrUndefined(this._color, time)
+ result.globalAlpha = Cesium.Property.getValueOrUndefined(this._opacity, time)
+ result.speed = Cesium.Property.getValueOrUndefined(this._speed, time)
+ return result
+ }
+
+ equals (other) {
+ return (
+ this === other ||
+ (other instanceof LineTrailMaterial &&
+ Cesium.Property.equals(this._color, other._color) &&
+ Cesium.Property.equals(this._opacity, other._opacity) &&
+ Cesium.Property.equals(this._speed, other._speed))
+ )
+ }
+}
+
+Object.defineProperties(LineTrailMaterial.prototype, {
+ color: Cesium.createPropertyDescriptor('color'),
+ opacity: Cesium.createPropertyDescriptor('opacity'),
+ speed: Cesium.createPropertyDescriptor('speed'),
+})
+
+
+let arrowLineMaterialType = "ArrowLineMaterial"
+Cesium.Material._materialCache.addMaterial(arrowLineMaterialType, {
+ fabric: {
+ type: arrowLineMaterialType,
+ uniforms: {
+ color: new Cesium.Color(0, 1, 1, 1),
+ directionColor: new Cesium.Color(1, 1, 1, 1),
+ outlineColor: new Cesium.Color(1, 1, 1, 1),
+ outlineWidth: 0,
+ speed: 0, // Added speed uniform with default 0 (no animation)
+ },
+ source: `
+#ifdef GL_OES_standard_derivatives
+#extension GL_OES_standard_derivatives : enable
+#endif
+
+uniform vec4 color;
+uniform vec4 directionColor;
+uniform vec4 outlineColor;
+uniform float outlineWidth;
+uniform float speed; // Added speed uniform
+
+in float v_width;
+in float v_polylineAngle;
+
+const float fragLength = 100.0;
+const float startPosition = 0.45;
+const float endPosition = 0.55;
+
+mat2 rotate(float rad) {
+ float c = cos(rad);
+ float s = sin(rad);
+ return mat2(c, s, -s, c);
+}
+
+float getPointOnLine(vec2 p0, vec2 p1, float x) {
+ float slope = (p0.y - p1.y) / (p0.x - p1.x);
+ return slope * (x - p0.x) + p0.y;
+}
+
+czm_material czm_getMaterial(czm_materialInput materialInput) {
+ czm_material material = czm_getDefaultMaterial(materialInput);
+ vec2 st = materialInput.st;
+ float time = fract(czm_frameNumber * speed / 1000.0);
+
+ float halfInteriorWidth = 0.5 * (v_width - outlineWidth) / v_width;
+ float b = step(0.5 - halfInteriorWidth, st.t);
+ b *= 1.0 - step(0.5 + halfInteriorWidth, st.t);
+
+ float d1 = abs(st.t - (0.5 - halfInteriorWidth));
+ float d2 = abs(st.t - (0.5 + halfInteriorWidth));
+ float dist = min(d1, d2);
+
+ vec4 currentColor = mix(outlineColor, color, b);
+ vec4 outColor = czm_antialias(outlineColor, color, currentColor, dist);
+ outColor = czm_gammaCorrect(outColor);
+
+ vec2 pos = rotate(v_polylineAngle) * gl_FragCoord.xy;
+
+ // Modified to include animation based on speed and time
+ float animationOffset = speed * time;
+ float maskS = fract((pos.x / (fragLength * czm_pixelRatio)) - animationOffset);
+
+ float maskT = st.t;
+ bool isDirection = (maskS > startPosition) && (maskS <= endPosition);
+
+ vec4 fragColor;
+ if (isDirection) {
+ float arrowWidth = (endPosition - startPosition) / 2.0;
+ float midS = startPosition + arrowWidth;
+
+ float t = 1.0;
+ if (maskS < midS) {
+ vec2 center = vec2(midS, 0.5);
+ float ptOnUpperLine = getPointOnLine(vec2(startPosition, 1.0), center, maskS);
+ float ptOnLowerLine = getPointOnLine(vec2(startPosition, 0.0), center, maskS);
+
+ t *= 1.0 - step(ptOnUpperLine, maskT);
+ t *= step(ptOnLowerLine, maskT);
+ t = 1.0 - t;
+ } else {
+ vec2 center = vec2(endPosition, 0.5);
+ float ptOnUpperLine = getPointOnLine(vec2(midS, 1.0), center, maskS);
+ float ptOnLowerLine = getPointOnLine(vec2(midS, 0.0), center, maskS);
+
+ t *= 1.0 - step(ptOnUpperLine, maskT);
+ t *= step(ptOnLowerLine, maskT);
+ }
+
+ vec4 outsideColor = outColor;
+ vec4 currentColor = mix(outsideColor, directionColor, clamp(t, 0.0, 1.0));
+ fragColor = currentColor;
+ } else {
+ fragColor = outColor;
+ }
+
+ fragColor = czm_gammaCorrect(fragColor);
+ material.diffuse = fragColor.rgb;
+ material.alpha = fragColor.a;
+ return material;
+}`
+ },
+ translucent: true
+})
+
+class ArrowLineMaterialProperty extends MaterialProperty {
+ constructor(options = {}) {
+ super(options)
+ }
+
+ getType (time) {
+ return arrowLineMaterialType
+ }
+
+ getType (time) {
+ return arrowLineMaterialType
+ }
+
+ getValue (time, result) {
+ if (!result) {
+ result = {}
+ }
+
+ result.color = Cesium.Property.getValueOrUndefined(this._color, time)
+ result.directionColor = Cesium.Property.getValueOrUndefined(this._directionColor, time)
+ result.outlineColor = Cesium.Property.getValueOrUndefined(this._outlineColor, time)
+ result.outlineWidth = Cesium.Property.getValueOrUndefined(this._outlineWidth, time)
+ result.speed = Cesium.Property.getValueOrUndefined(this._speed, time)
+
+ return result
+ }
+
+ equals (other) {
+ return (
+ this === other ||
+ (other instanceof ArrowLineMaterialProperty &&
+ Cesium.Property.equals(this._color, other._color) &&
+ Cesium.Property.equals(this._directionColor, other._directionColor) &&
+ Cesium.Property.equals(this._outlineColor, other._outlineColor) &&
+ Cesium.Property.equals(this._outlineWidth, other._outlineWidth) &&
+ Cesium.Property.equals(this._speed, other._speed))
+ )
+ }
+}
+
+Object.defineProperties(ArrowLineMaterialProperty.prototype, {
+ color: Cesium.createPropertyDescriptor('color'),
+ directionColor: Cesium.createPropertyDescriptor('directionColor'),
+ outlineColor: Cesium.createPropertyDescriptor('outlineColor'),
+ outlineWidth: Cesium.createPropertyDescriptor('outlineWidth'),
+ speed: Cesium.createPropertyDescriptor('speed')
+})
+
+
+// 轨迹线材质
+let pLG = "PolylineGlow"
+Cesium.Material._materialCache.addMaterial(pLG, {
+ fabric: {
+ uniforms: {
+ color: new Cesium.Color(0, .5, 1, 1),
+ glowPower: .25,
+ taperPower: 1
+ },
+
+ source: ` uniform vec4 color;
+ uniform float glowPower;
+ uniform float taperPower;
+
+ czm_material czm_getMaterial(czm_materialInput materialInput)
+ {
+ czm_material material = czm_getDefaultMaterial(materialInput);
+
+ vec2 st = materialInput.st;
+ float glow = glowPower / abs(st.t - 0.5) - (glowPower / 0.5);
+
+ if (taperPower <= 0.99999) {
+ glow *= min(1.0, taperPower / (0.5 - st.s * 0.5) - (taperPower / 0.5));
+ }
+
+ vec4 fragColor;
+ fragColor.rgb = max(vec3(glow - 1.0 + color.rgb), color.rgb);
+ fragColor.a = clamp(0.0, 1.0, glow) * color.a;
+ fragColor = czm_gammaCorrect(fragColor);
+
+ material.emission = fragColor.rgb;
+ material.alpha = fragColor.a;
+
+ return material;
+ }
+ `
+ },
+ translucent: true
+})
+class PolylineGlowMaterial extends MaterialProperty {
+ constructor(options = {}) {
+ super(options)
+ }
+
+ getType (time) {
+ return pLG
+ }
+
+ getValue (time, result) {
+ if (!result) {
+ result = {}
+ }
+
+ result.color = Cesium.Property.getValueOrUndefined(this._color, time)
+ result.glowPower = Cesium.Property.getValueOrUndefined(this._glowPower, time)
+ result.taperPower = Cesium.Property.getValueOrUndefined(this._taperPower, time)
+ return result
+ }
+
+ equals (other) {
+ return (
+ this === other ||
+ (other instanceof LineTrailMaterial &&
+ Cesium.Property.equals(this._color, other._color) &&
+ Cesium.Property.equals(this._glowPower, other._glowPower) &&
+ Cesium.Property.equals(this._taperPower, other._taperPower))
+ )
+ }
+}
+
+Object.defineProperties(PolylineGlowMaterial.prototype, {
+ color: Cesium.createPropertyDescriptor('color'),
+ glowPower: Cesium.createPropertyDescriptor('glowPower'),
+ taperPower: Cesium.createPropertyDescriptor('taperPower'),
+})
+
+
+export {
+ PolyGradientMaterial,
+ LineTrailMaterial,
+ ArrowLineMaterialProperty,
+ PolylineGlowMaterial
+}
\ No newline at end of file
diff --git a/src/utils/util.js b/src/utils/util.js
index 94137a6..fc0bc9e 100644
--- a/src/utils/util.js
+++ b/src/utils/util.js
@@ -125,9 +125,9 @@
* @returns {string}
*/
export const getSmallImg = url => {
- if (!url) return ''
- const lastDotIndex = url.lastIndexOf('.')
- return `${url.substring(0, lastDotIndex)}_small${url.substring(lastDotIndex)}`
+ if (!url) return ''
+ const lastDotIndex = url.lastIndexOf('.')
+ return `${url.substring(0, lastDotIndex)}_small${url.substring(lastDotIndex)}`
}
/**
* 浏览器判断是否全屏
@@ -438,3 +438,23 @@
// 设置默认范围 [上个月, 当前月]
return [new Date(lastMonthYear, lastMonth, 1), new Date(currentYear, currentMonth, 1)]
}
+
+// key驼峰转换为下划线
+export function camelToSnake (obj) {
+ if (typeof obj !== 'object' || obj === null) {
+ return obj
+ }
+
+ if (Array.isArray(obj)) {
+ return obj.map(item => camelToSnake(item))
+ }
+
+ const newObj = {}
+ for (const key in obj) {
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
+ const newKey = key.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase()
+ newObj[newKey] = camelToSnake(obj[key])
+ }
+ }
+ return newObj
+}
\ No newline at end of file
--
Gitblit v1.9.3