@yangyongtao/gaea 1.1.22 → 1.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/public/Gaea.js +22 -22
- package/src/GaeaMethods.js +154 -7
- package/src/components/LayerTree.vue +6 -1
- package/src/vite-plugin.js +12 -6
package/src/GaeaMethods.js
CHANGED
|
@@ -137,7 +137,7 @@ const defaultConfig = {
|
|
|
137
137
|
/** 天地图 token(在线模式使用) */
|
|
138
138
|
tiandituToken: '63201cfd7df1e1bff7d88bb8baa32151',
|
|
139
139
|
/** 天地图最小/最大层级 */
|
|
140
|
-
tiandituLevelRange: [0,
|
|
140
|
+
tiandituLevelRange: [0, 21],
|
|
141
141
|
/** 默认加载的影像图层(服务平台模式生效) */
|
|
142
142
|
defaultLayers: [
|
|
143
143
|
{ layerName: 'earthland', forMat: 'image/png', min: 0, max: 18, transparency: 0.3 },
|
|
@@ -164,6 +164,8 @@ const defaultConfig = {
|
|
|
164
164
|
dataHubApiUrl: '',
|
|
165
165
|
/** 是否显示图层树按钮(右上角重置按钮旁边) */
|
|
166
166
|
showLayerTreeBtn: false,
|
|
167
|
+
/** 默认隐藏的分类 key 列表,如 ['rainStations', 'rescue'] */
|
|
168
|
+
defaultHiddenCategories: [],
|
|
167
169
|
/** 图层树分类数据(默认数据,接口数据会合并进来) */
|
|
168
170
|
layerCategories: [
|
|
169
171
|
{ key: 'seawall', text: '海塘', visible: true, children: [
|
|
@@ -401,6 +403,14 @@ export class GaeaApp {
|
|
|
401
403
|
// 8. 初始化屏幕图标
|
|
402
404
|
this._initScreenIcons();
|
|
403
405
|
|
|
406
|
+
// 应用默认隐藏的分类
|
|
407
|
+
const hiddenCats = this.config.defaultHiddenCategories || []
|
|
408
|
+
hiddenCats.forEach(key => {
|
|
409
|
+
const cat = this.layerCategories.find(c => c.key === key)
|
|
410
|
+
if (cat) cat.visible = false
|
|
411
|
+
this.setCategoryVisible(key, false)
|
|
412
|
+
})
|
|
413
|
+
|
|
404
414
|
console.log('[GaeaApp] 后台资源加载完成');
|
|
405
415
|
} catch (e) {
|
|
406
416
|
console.error('[GaeaApp] 后台资源加载出错:', e);
|
|
@@ -603,13 +613,8 @@ export class GaeaApp {
|
|
|
603
613
|
{ name: 'YPDP0+750', position: { x: 27.220289, y: 120.459753, z: -44 }, rotate: [0, 226, 0], size: [1, 1, 1], show: true, url: 'gltf/大坝断面750.gltf' },
|
|
604
614
|
{ name: 'YPDP0+100', position: { x: 27.223027, y: 120.454653, z: -44 }, rotate: [0, 222, 0], size: [1, 1, 1], show: true, url: 'gltf/大坝断面100.gltf' },
|
|
605
615
|
{ name: 'YPDP0+200', position: { x: 27.222541, y: 120.455453, z: -44 }, rotate: [0, 246, 0], size: [1, 1, 1], show: true, url: 'gltf/大坝断面200.gltf' },
|
|
606
|
-
{ name: '沿浦水闸', position: { x: 27.222866, y: 120.453113, z: 13.25 }, rotate: [0, -30, 0], size: [1, 1, 1], show: false, url: 'gltf/沿浦水闸.gltf', enablePick: true },
|
|
607
616
|
{ name: '沿浦泵站', position: { x: 27.222001, y: 120.452509, z: 17 }, rotate: [0, -38, 0], size: [1, 1, 1], show: true, url: 'gltf/沿浦泵站.gltf', enablePick: true },
|
|
608
|
-
{ name: '下在水闸', position: { x: 27.221816, y: 120.445182, z: 20 }, rotate: [0, 0, 0], size: [1, 1, 1], show: false, url: 'gltf/下在水闸.gltf', enablePick: true },
|
|
609
617
|
{ name: '下在海塘纳排闸', position: { x: 27.219978, y: 120.445672, z: 15 }, rotate: [0, 0, 0], size: [1, 1, 1], show: true, url: 'gltf/下在海塘纳排闸.gltf', enablePick: true },
|
|
610
|
-
{ name: '联盟水闸', position: { x: 27.200462, y: 120.465635, z: 20 }, rotate: [0, 0, 0], size: [1, 1, 1], show: false, url: 'gltf/联盟水闸.gltf', enablePick: true },
|
|
611
|
-
{ name: '岭尾水闸', position: { x: 27.215762, y: 120.462235, z: 30 }, rotate: [0, -63, 0], size: [1, 1, 1], show: false, url: 'gltf/岭尾水闸.gltf', enablePick: true },
|
|
612
|
-
{ name: '岭尾新闸', position: { x: 27.210369, y: 120.458532, z: 0.5 }, rotate: [0, -153, 0], size: [1, 1, 1], show: false, url: 'gltf/岭尾新闸.gltf' },
|
|
613
618
|
{ name: '盒子模型', position: { x: 27.241836, y: 120.462750, z: 50 }, rotate: [0, 90, 0], size: [10, 10, 10], show: true, url: 'gltf/box.gltf' },
|
|
614
619
|
{ name: 'YPDP0+600游览模型', position: { x: 27.217433, y: 120.461448, z: 32 }, rotate: [0, 90, 0], size: [1, 1, 1], show: true, url: 'gltf/box.gltf' },
|
|
615
620
|
{ name: 'YPDP0+750游览模型', position: { x: 27.220072, y: 120.459602, z: 30 }, rotate: [0, 90, 0], size: [1, 1, 1], show: true, url: 'gltf/box.gltf' },
|
|
@@ -1488,7 +1493,14 @@ export class GaeaApp {
|
|
|
1488
1493
|
position: { x: lat, y: lng, z },
|
|
1489
1494
|
method,
|
|
1490
1495
|
offset,
|
|
1491
|
-
onClick,
|
|
1496
|
+
onClick: (clickedName, data) => {
|
|
1497
|
+
// 派发全局自定义事件,父组件可通过 document.addEventListener 监听
|
|
1498
|
+
document.dispatchEvent(new CustomEvent('gaea-marker-click', {
|
|
1499
|
+
detail: { name: clickedName, text: data.text, position: data.position, category },
|
|
1500
|
+
bubbles: true
|
|
1501
|
+
}))
|
|
1502
|
+
if (onClick) onClick(clickedName, data)
|
|
1503
|
+
},
|
|
1492
1504
|
category,
|
|
1493
1505
|
type: 'marker'
|
|
1494
1506
|
})
|
|
@@ -2033,6 +2045,141 @@ export class GaeaApp {
|
|
|
2033
2045
|
if (el) el.style.display = 'none'
|
|
2034
2046
|
})
|
|
2035
2047
|
};
|
|
2048
|
+
|
|
2049
|
+
// ---- 水面加载 ----
|
|
2050
|
+
|
|
2051
|
+
/**
|
|
2052
|
+
* 加载水面
|
|
2053
|
+
* @param {Object} opts
|
|
2054
|
+
* @param {string} opts.gltfUrl - GLTF 模型路径
|
|
2055
|
+
* @param {Object} opts.Position - { x: 纬度, y: 经度, z: 高程 }
|
|
2056
|
+
* @param {Array<number>} opts.rotate - [tilt, heading, bank] 旋转角度
|
|
2057
|
+
* @param {Array<number>} opts.scale - [sx, sy, sz] 缩放
|
|
2058
|
+
* @param {Array<number>} [opts.colorDeep=[0,157,187]] - 深水区颜色 [r, g, b](0-255)
|
|
2059
|
+
* @param {number} [opts.flowSpeed=0.1] - 流速
|
|
2060
|
+
*/
|
|
2061
|
+
addWaterHandle = async ({
|
|
2062
|
+
gltfUrl, Position, rotate, scale,
|
|
2063
|
+
colorDeep = [0, 157, 187],
|
|
2064
|
+
flowSpeed = 0.1
|
|
2065
|
+
}) => {
|
|
2066
|
+
const waterMtl = Gaea.GaeaResourceLoader.Instance.LoadLoaclResource('res://assets/material/river.tres')
|
|
2067
|
+
const material = Gaea.ShaderMaterial.ConvertBy(waterMtl)
|
|
2068
|
+
|
|
2069
|
+
const element = new Gaea.GLTFElement()
|
|
2070
|
+
element.ResourceName = gltfUrl
|
|
2071
|
+
element.GeographyPosition = new Gaea.Vector3(Position.x, Position.y, Position.z)
|
|
2072
|
+
|
|
2073
|
+
element.OnModelInit(() => {
|
|
2074
|
+
const n = element.GetChildCount()
|
|
2075
|
+
for (let i = 0; i < n; i++) {
|
|
2076
|
+
const meshInstance = Gaea.MeshInstance.ConvertBy(element.Root.GetChild(i))
|
|
2077
|
+
const count = meshInstance.Mesh.GetSurfaceCount()
|
|
2078
|
+
for (let j = 0; j < count; j++) {
|
|
2079
|
+
meshInstance.Mesh.SurfaceSetMaterial(j, material)
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
element.Scale = new Gaea.Vector3(scale[0], scale[1], scale[2])
|
|
2083
|
+
element.TiltHeadingBank = new Gaea.Vector3(rotate[0], rotate[1], rotate[2])
|
|
2084
|
+
|
|
2085
|
+
Gaea.World.Instance.SetMtlVector3(material, 'uv_scale', new Gaea.Vector3(-7, -7, 1))
|
|
2086
|
+
Gaea.World.Instance.SetMtlFloat(material, 'flow_speed', flowSpeed)
|
|
2087
|
+
Gaea.World.Instance.SetMtlColor(material, 'color_shallow', new Gaea.Color(0 / 255, 157 / 255, 187 / 255, 1))
|
|
2088
|
+
Gaea.World.Instance.SetMtlColor(material, 'color_deep', new Gaea.Color(colorDeep[0] / 255, colorDeep[1] / 255, colorDeep[2] / 255, 1))
|
|
2089
|
+
Gaea.World.Instance.SetMtlFloat(material, 'transparency_clarity', 3)
|
|
2090
|
+
Gaea.World.Instance.SetMtlFloat(material, 'foam_amount', 0.9)
|
|
2091
|
+
})
|
|
2092
|
+
|
|
2093
|
+
Gaea.World.Instance.RenderableObjectList.AddLast(element)
|
|
2094
|
+
return element
|
|
2095
|
+
};
|
|
2096
|
+
|
|
2097
|
+
// ---- 开门动画 ----
|
|
2098
|
+
|
|
2099
|
+
/**
|
|
2100
|
+
* 模型缓动动画(缩放/位移/旋转)
|
|
2101
|
+
* @param {Object} element - GLTF 元素
|
|
2102
|
+
* @param {Object} Scale - 目标缩放 { x, y, z }
|
|
2103
|
+
* @param {Object} Position - 目标位置 { x, y, z }
|
|
2104
|
+
* @param {Object} translation - 模型相对位移 { x, y, z }
|
|
2105
|
+
* @param {number} time - 动画时间(ms)
|
|
2106
|
+
* @param {Object} Door - 门旋转角度 { x, y, z }
|
|
2107
|
+
* @param {number} floor - 门在模型树中的层级索引
|
|
2108
|
+
*/
|
|
2109
|
+
tweentest = (element, Scale = {}, Position = {}, translation = {}, time, Door = {}, floor = 0) => {
|
|
2110
|
+
const { Tween, Easing } = window.TWEEN
|
|
2111
|
+
|
|
2112
|
+
if (Object.values(Scale).length) {
|
|
2113
|
+
const scale = { x: element.Scale.x, y: element.Scale.y, z: element.Scale.z }
|
|
2114
|
+
const tweenScale = new Tween(scale)
|
|
2115
|
+
.to(Scale, time)
|
|
2116
|
+
.easing(Easing.Quadratic.InOut)
|
|
2117
|
+
.onUpdate(() => {
|
|
2118
|
+
element.Scale = new Gaea.Vector3(scale.x, scale.y, scale.z)
|
|
2119
|
+
})
|
|
2120
|
+
.start()
|
|
2121
|
+
.onStart(() => { if (Scale.x !== 0.1) element.Visible = true })
|
|
2122
|
+
.onComplete(() => { if (Scale.x === 0.1) element.Visible = false; this.tweenGroup.remove(tweenScale) })
|
|
2123
|
+
this.tweenGroup.add(tweenScale)
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2126
|
+
if (Object.values(Position).length) {
|
|
2127
|
+
const pos = { x: element.GeographyPosition.x, y: element.GeographyPosition.y, z: element.GeographyPosition.z }
|
|
2128
|
+
const tweenPos = new Tween(pos)
|
|
2129
|
+
.to(Position, time)
|
|
2130
|
+
.easing(Easing.Quadratic.InOut)
|
|
2131
|
+
.onUpdate(() => { element.GeographyPosition = new Gaea.Vector3(pos.x, pos.y, pos.z) })
|
|
2132
|
+
.start()
|
|
2133
|
+
.onComplete(() => { this.tweenGroup.remove(tweenPos) })
|
|
2134
|
+
this.tweenGroup.add(tweenPos)
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
if (Object.values(Door).length) {
|
|
2138
|
+
const doorMesh = element.Root.GetChild(floor)
|
|
2139
|
+
const meshInstance = new Gaea.MeshInstance()
|
|
2140
|
+
meshInstance.InstanceID = doorMesh.InstanceID
|
|
2141
|
+
const doorAngle = { x: meshInstance.RotationDegrees.x, y: meshInstance.RotationDegrees.y, z: meshInstance.RotationDegrees.z }
|
|
2142
|
+
const tweenDoor = new Tween(doorAngle)
|
|
2143
|
+
.to(Door, time)
|
|
2144
|
+
.easing(Easing.Quadratic.InOut)
|
|
2145
|
+
.onUpdate(() => { meshInstance.RotationDegrees = new Gaea.Vector3(doorAngle.x, doorAngle.y, doorAngle.z) })
|
|
2146
|
+
.start()
|
|
2147
|
+
.onComplete(() => { this.tweenGroup.remove(tweenDoor) })
|
|
2148
|
+
this.tweenGroup.add(tweenDoor)
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2151
|
+
if (Object.values(translation).length) {
|
|
2152
|
+
const trans = element.Root
|
|
2153
|
+
? { x: element.Root.Translation.x, y: element.Root.Translation.y, z: element.Root.Translation.z }
|
|
2154
|
+
: { x: element.Translation.x, y: element.Translation.y, z: element.Translation.z }
|
|
2155
|
+
const tweenTrans = new Tween(trans)
|
|
2156
|
+
.to(translation, time)
|
|
2157
|
+
.easing(Easing.Quadratic.InOut)
|
|
2158
|
+
.onUpdate(() => {
|
|
2159
|
+
if (element.Root) element.Root.Translation = new Gaea.Vector3(trans.x, trans.y, trans.z)
|
|
2160
|
+
else element.Translation = new Gaea.Vector3(trans.x, trans.y, trans.z)
|
|
2161
|
+
})
|
|
2162
|
+
.start()
|
|
2163
|
+
.onComplete(() => { this.tweenGroup.remove(tweenTrans) })
|
|
2164
|
+
this.tweenGroup.add(tweenTrans)
|
|
2165
|
+
}
|
|
2166
|
+
};
|
|
2167
|
+
|
|
2168
|
+
// ---- 模型内置动画 ----
|
|
2169
|
+
|
|
2170
|
+
/**
|
|
2171
|
+
* 执行模型内置动画(如开闸/关闸动画)
|
|
2172
|
+
* @param {Object} opts
|
|
2173
|
+
* @param {string} opts.animationPath - 动画路径,如 '沿浦水闸/AnimationPlayer'
|
|
2174
|
+
* @param {string} opts.animationName - 动画名称,如 '开闸'
|
|
2175
|
+
* @param {number} [opts.speed=1.0] - 动画速度
|
|
2176
|
+
* @param {boolean} [opts.isReversePlay=false] - 是否反向播放
|
|
2177
|
+
*/
|
|
2178
|
+
executeModelAnimation = ({ animationPath, animationName, speed = 1.0, isReversePlay = false }) => {
|
|
2179
|
+
const node = Gaea.World.Instance.GetNode(animationPath)
|
|
2180
|
+
const nodeAnimate = Gaea.AnimationPlayer.ConvertBy(node)
|
|
2181
|
+
nodeAnimate.Play(animationName, -1, speed, isReversePlay)
|
|
2182
|
+
};
|
|
2036
2183
|
}
|
|
2037
2184
|
|
|
2038
2185
|
export default GaeaApp;
|
|
@@ -44,6 +44,8 @@ import vDrag from '../directives/vDrag.js';
|
|
|
44
44
|
|
|
45
45
|
const props = defineProps({
|
|
46
46
|
appInstance: { type: Object, required: true },
|
|
47
|
+
/** 需要隐藏的分类 key 列表 */
|
|
48
|
+
hiddenCategories: { type: Array, default: () => [] }
|
|
47
49
|
});
|
|
48
50
|
|
|
49
51
|
const emit = defineEmits(['close', 'node-click']);
|
|
@@ -78,7 +80,10 @@ function onCategoryToggle(categoryKey, checked) {
|
|
|
78
80
|
|
|
79
81
|
const filteredData = computed(() => {
|
|
80
82
|
const kw = searchKey.value.trim().toLowerCase();
|
|
81
|
-
|
|
83
|
+
const hidden = new Set(props.hiddenCategories);
|
|
84
|
+
return categories.value
|
|
85
|
+
.filter(rootNode => rootNode.visible !== false && !hidden.has(rootNode.key))
|
|
86
|
+
.map(rootNode => {
|
|
82
87
|
if (!kw) {
|
|
83
88
|
rootNode.filteredChildren = rootNode.children || [];
|
|
84
89
|
return rootNode;
|
package/src/vite-plugin.js
CHANGED
|
@@ -41,13 +41,19 @@ export default function gaeaVitePlugin() {
|
|
|
41
41
|
name: 'vite-plugin-gaea',
|
|
42
42
|
enforce: 'pre',
|
|
43
43
|
|
|
44
|
-
config() {
|
|
45
|
-
return {
|
|
46
|
-
server: { headers: COEP_HEADERS },
|
|
47
|
-
};
|
|
48
|
-
},
|
|
49
|
-
|
|
50
44
|
configureServer(server) {
|
|
45
|
+
// COEP/COOP 头只对非 WebSocket 请求设置,避免破坏 Vite HMR
|
|
46
|
+
server.middlewares.stack.unshift({
|
|
47
|
+
route: '',
|
|
48
|
+
handle: function coepMiddleware(req, res, next) {
|
|
49
|
+
if (req.headers.upgrade) return next(); // 跳过 WebSocket 升级请求
|
|
50
|
+
for (const [key, val] of Object.entries(COEP_HEADERS)) {
|
|
51
|
+
res.setHeader(key, val);
|
|
52
|
+
}
|
|
53
|
+
next();
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
51
57
|
server.middlewares.stack.unshift({
|
|
52
58
|
route: '',
|
|
53
59
|
handle: function gaeaServe(req, res, next) {
|