Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
D
DSMS
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
詹银鑫
DSMS
Commits
f3c475d0
提交
f3c475d0
authored
6月 03, 2025
作者:
詹银鑫
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
新增烟雾效果无人机移动效果
上级
fb9d11bf
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
380 行增加
和
228 行删除
+380
-228
smoke.png
src/assets/texture/smoke.png
+0
-0
assets.js
src/views/gdMap/assets.js
+2
-0
map.js
src/views/gdMap/map.js
+378
-228
没有找到文件。
src/assets/texture/smoke.png
0 → 100644
浏览文件 @
f3c475d0
243.8 KB
src/views/gdMap/assets.js
浏览文件 @
f3c475d0
...
...
@@ -17,6 +17,7 @@ import arrow from "@/assets/texture/arrow.png"
import
point
from
"@/assets/texture/point1.png"
import
flyLineFocus
from
"@/assets/texture/guangquan01.png"
import
mapFlyline
from
"@/assets/texture/flyline6.png"
import
smoke
from
"@/assets/texture/smoke.png"
// 焦点贴图
import
focusArrowsTexture
from
"@/assets/texture/focus/focus_arrows.png"
import
focusBarTexture
from
"@/assets/texture/focus/focus_bar.png"
...
...
@@ -89,6 +90,7 @@ export class Assets {
{
type
:
"Texture"
,
name
:
"mapFlyline"
,
path
:
mapFlyline
},
{
type
:
"Texture"
,
name
:
"arrow"
,
path
:
arrow
},
{
type
:
"Texture"
,
name
:
"point"
,
path
:
point
},
{
type
:
"Texture"
,
name
:
"smoke"
,
path
:
smoke
},
// focus
{
type
:
"Texture"
,
name
:
"focusArrows"
,
path
:
focusArrowsTexture
},
...
...
src/views/gdMap/map.js
浏览文件 @
f3c475d0
...
...
@@ -58,6 +58,8 @@ import gsap from "gsap";
import
emitter
from
"@/utils/emitter"
;
import
{
InteractionManager
}
from
"three.interactive"
;
import
{
OrbitControls
}
from
"three/examples/jsm/controls/OrbitControls"
;
// 引入模型加载模块
import
{
Resource
}
from
"@/mini3d/utils/Resource"
;
...
...
@@ -68,6 +70,15 @@ function sortByValue(data) {
export
class
World
extends
Mini3d
{
constructor
(
canvas
,
assets
)
{
super
(
canvas
);
this
.
controls
=
new
OrbitControls
(
this
.
camera
.
instance
,
this
.
renderer
.
instance
.
domElement
);
this
.
controls
.
target
.
set
(
0
,
0
,
0
);
this
.
controls
.
minPolarAngle
=
Math
.
PI
/
6
;
this
.
controls
.
maxPolarAngle
=
Math
.
PI
*
0.44
;
// 中心坐标
// this.geoProjectionCenter = [113.280637, 23.125178]
this
.
geoProjectionCenter
=
[
110.840171
,
39.864362
];
...
...
@@ -118,6 +129,9 @@ export class World extends Mini3d {
this
.
initEnvironment
();
this
.
init
();
console
.
log
(
"执行了 这些代码"
);
this
.
droneMoveState
=
{
w
:
false
,
a
:
false
,
s
:
false
,
d
:
false
};
window
.
addEventListener
(
"keydown"
,
(
e
)
=>
this
.
onKeyDown
(
e
));
window
.
addEventListener
(
"keyup"
,
(
e
)
=>
this
.
onKeyUp
(
e
));
}
init
()
{
// 标签组
...
...
@@ -181,6 +195,12 @@ export class World extends Mini3d {
0.5
,
5
);
// 创建火焰和烟雾
this
.
createFireWithSmoke
([
[
110.9801
,
39.8002
],
[
111.0806
,
39.7005
],
// ...更多经纬度
]);
// 创造3d地形
// this.createTerrain()
// 创造geoJson图
...
...
@@ -1690,111 +1710,13 @@ export class World extends Mini3d {
waterGroup
,
};
}
createLineWater
()
{
// 获取水的GeoJSON线数据
let
mapJsonData
=
this
.
assets
.
instance
.
getResource
(
"linewater"
);
let
lineWaterJson
;
try
{
lineWaterJson
=
typeof
mapJsonData
===
"string"
?
JSON
.
parse
(
mapJsonData
)
:
mapJsonData
;
}
catch
(
e
)
{
console
.
error
(
"linewater 解析失败"
,
e
);
return
{
lineWaterGroup
:
null
};
}
// 加载法线贴图
const
textureLoader
=
new
THREE
.
TextureLoader
();
let
base_url
=
import
.
meta
.
env
.
BASE_URL
||
"/"
;
const
normalMap
=
textureLoader
.
load
(
base_url
+
"assets/json/waternormals.jpg"
);
normalMap
.
wrapS
=
normalMap
.
wrapT
=
THREE
.
RepeatWrapping
;
// 可选:加载一张水面颜色贴图
// const waterMap = textureLoader.load(base_url + "assets/json/watercolor.png");
// waterMap.wrapS = waterMap.wrapT = THREE.RepeatWrapping;
// 动画流动
this
.
time
.
on
(
"tick"
,
()
=>
{
normalMap
.
offset
.
x
+=
0.002
;
// 控制流动速度和方向
normalMap
.
offset
.
y
+=
0.001
;
// 如果有颜色贴图,也可以流动
// waterMap.offset.x += 0.001;
});
// 创建线水组
const
lineWaterGroup
=
new
Group
();
const
projection
=
geoMercator
()
.
center
(
this
.
geoProjectionCenter
)
.
scale
(
this
.
geoProjectionScale
)
.
translate
([
0
,
0
]);
(
lineWaterJson
.
features
||
[]).
forEach
((
feature
)
=>
{
const
geometry
=
feature
.
geometry
;
if
(
!
geometry
)
return
;
let
lines
=
[];
if
(
geometry
.
type
===
"LineString"
)
{
lines
=
[
geometry
.
coordinates
];
}
else
if
(
geometry
.
type
===
"MultiLineString"
)
{
lines
=
geometry
.
coordinates
;
}
lines
.
forEach
((
line
)
=>
{
const
points
=
line
.
map
(([
lng
,
lat
])
=>
{
const
[
x
,
y
]
=
projection
([
lng
,
lat
]);
return
new
THREE
.
Vector3
(
x
,
-
y
,
this
.
depth
+
0.26
);
// 保证高于地表
});
const
geometryLine
=
new
THREE
.
BufferGeometry
().
setFromPoints
(
points
);
const
material
=
new
THREE
.
LineBasicMaterial
({
color
:
0x3bb9ff
,
linewidth
:
2
,
transparent
:
true
,
opacity
:
0.8
,
depthWrite
:
false
,
});
const
lineObj
=
new
THREE
.
Line
(
geometryLine
,
material
);
lineObj
.
renderOrder
=
11
;
lineWaterGroup
.
add
(
lineObj
);
});
// lines.forEach((line) => {
// const points = line.map(([lng, lat]) => {
// const [x, y] = projection([lng, lat]);
// return new THREE.Vector3(x, -y, this.depth + 0.26);
// });
// if (points.length < 2) return;
// const curve = new THREE.CatmullRomCurve3(points);
// const tubeGeometry = new THREE.TubeGeometry(curve, 64, 0.05, 8); // 0.05为线粗
// // const material = new THREE.MeshBasicMaterial({
// // color: 0x3bb9ff,
// // transparent: true,
// // opacity: 0.8,
// // depthWrite: false,
// // });
// const material = new THREE.MeshStandardMaterial({
// color: 0x153e7e,
// transparent: true,
// opacity: 0.5,
// side: DoubleSide,
// depthWrite: false,
// normalMap: normalMap,
// normalScale: new THREE.Vector2(1, 1), // 可调节凹凸强度
// // map: waterMap, // 如果有颜色贴图可加上
// metalness: 0.3,
// roughness: 0.7,
// });
// const mesh = new THREE.Mesh(tubeGeometry, material);
// mesh.renderOrder = 11;
// lineWaterGroup.add(mesh);
// });
});
return
{
lineWaterGroup
,
};
}
// createLineWater() {
// // 获取水的GeoJSON线数据
// let mapJsonData = this.assets.instance.getResource("linewater");
// let lineWaterJson;
// try {
// lineWaterJson = typeof mapJsonData === "string" ? JSON.parse(mapJsonData) : mapJsonData;
// lineWaterJson =
// typeof mapJsonData === "string" ? JSON.parse(mapJsonData) : mapJsonData;
// } catch (e) {
// console.error("linewater 解析失败", e);
// return { lineWaterGroup: null };
...
...
@@ -1803,21 +1725,28 @@ export class World extends Mini3d {
// // 加载法线贴图
// const textureLoader = new THREE.TextureLoader();
// let base_url = import.meta.env.BASE_URL || "/";
// const normalMap = textureLoader.load(base_url + "assets/json/waternormals.jpg");
// const normalMap = textureLoader.load(
// base_url + "assets/json/waternormals.jpg"
// );
// normalMap.wrapS = normalMap.wrapT = THREE.RepeatWrapping;
// const waterMap = textureLoader.load(base_url + "assets/json/watercolor.png"); // 你需要准备一张水波纹PNG
// waterMap.wrapS = waterMap.wrapT = THREE.RepeatWrapping;
// // 可选:加载一张水面颜色贴图
// // const waterMap = textureLoader.load(base_url + "assets/json/watercolor.png");
// // waterMap.wrapS = waterMap.wrapT = THREE.RepeatWrapping;
// // 动画流动
// this.time.on("tick", () => {
// normalMap.offset.x += 0.002;
// normalMap.offset.x += 0.002;
// 控制流动速度和方向
// normalMap.offset.y += 0.001;
// waterMap.offset.x += 0.002; // 让颜色贴图也流动
// // 如果有颜色贴图,也可以流动
// // waterMap.offset.x += 0.001;
// });
// // 创建线水组
// const lineWaterGroup = new Group();
// const projection = geoMercator().center(this.geoProjectionCenter).scale(this.geoProjectionScale).translate([0, 0]);
// const projection = geoMercator()
// .center(this.geoProjectionCenter)
// .scale(this.geoProjectionScale)
// .translate([0, 0]);
// (lineWaterJson.features || []).forEach((feature) => {
// const geometry = feature.geometry;
// if (!geometry) return;
...
...
@@ -1828,31 +1757,52 @@ export class World extends Mini3d {
// lines = geometry.coordinates;
// }
// lines.forEach((line) => {
// // 生成带宽度的水带
// const points = line.map(([lng, lat]) => {
// const [x, y] = projection([lng, lat]);
// return new THREE.Vector3(x, -y, this.depth + 0.26); // 保证高于地表
// });
// if (points.length < 2) return;
// // 用TubeGeometry生成带宽度的水带
// const curve = new THREE.CatmullRomCurve3(points);
// const tubeGeometry = new THREE.TubeGeometry(curve, Math.max(32, points.length * 2), 0.01, 16);
// const material = new THREE.MeshStandardMaterial({
// color: 0x4fc3ff,
// const geometryLine = new THREE.BufferGeometry().setFromPoints(points);
// const material = new THREE.LineBasicMaterial({
// color: 0x3bb9ff,
// linewidth: 2,
// transparent: true,
// opacity: 0.35,
// side: DoubleSide,
// opacity: 0.8,
// depthWrite: false,
// normalMap: normalMap,
// normalScale: new THREE.Vector2(2, 2),
// map: waterMap, // 使用颜色贴图
// metalness: 0.3,
// roughness: 0.7,
// });
// const
mesh = new Mesh(tubeGeometry
, material);
//
mesh
.renderOrder = 11;
// lineWaterGroup.add(
mesh
);
// const
lineObj = new THREE.Line(geometryLine
, material);
//
lineObj
.renderOrder = 11;
// lineWaterGroup.add(
lineObj
);
// });
// // lines.forEach((line) => {
// // const points = line.map(([lng, lat]) => {
// // const [x, y] = projection([lng, lat]);
// // return new THREE.Vector3(x, -y, this.depth + 0.26);
// // });
// // if (points.length < 2) return;
// // const curve = new THREE.CatmullRomCurve3(points);
// // const tubeGeometry = new THREE.TubeGeometry(curve, 64, 0.05, 8); // 0.05为线粗
// // // const material = new THREE.MeshBasicMaterial({
// // // color: 0x3bb9ff,
// // // transparent: true,
// // // opacity: 0.8,
// // // depthWrite: false,
// // // });
// // const material = new THREE.MeshStandardMaterial({
// // color: 0x153e7e,
// // transparent: true,
// // opacity: 0.5,
// // side: DoubleSide,
// // depthWrite: false,
// // normalMap: normalMap,
// // normalScale: new THREE.Vector2(1, 1), // 可调节凹凸强度
// // // map: waterMap, // 如果有颜色贴图可加上
// // metalness: 0.3,
// // roughness: 0.7,
// // });
// // const mesh = new THREE.Mesh(tubeGeometry, material);
// // mesh.renderOrder = 11;
// // lineWaterGroup.add(mesh);
// // });
// });
// return {
// lineWaterGroup,
...
...
@@ -1860,6 +1810,7 @@ export class World extends Mini3d {
// }
// createLineWater() {
// // 获取水的GeoJSON线数据
// let mapJsonData = this.assets.instance.getResource("linewater");
// let lineWaterJson;
// try {
...
...
@@ -1869,21 +1820,21 @@ export class World extends Mini3d {
// return { lineWaterGroup: null };
// }
// // 加载法线贴图
// const textureLoader = new THREE.TextureLoader();
// let base_url = import.meta.env.BASE_URL || "/";
// const normalMap = textureLoader.load(base_url + "assets/json/waternormals.jpg");
// normalMap.wrapS = normalMap.wrapT = THREE.RepeatWrapping;
// const waterMap = textureLoader.load(base_url + "assets/json/watercolor.png");
// const waterMap = textureLoader.load(base_url + "assets/json/watercolor.png");
// 你需要准备一张水波纹PNG
// waterMap.wrapS = waterMap.wrapT = THREE.RepeatWrapping;
// // 流动速度更快
// // 动画流动
// this.time.on("tick", () => {
// normalMap.offset.x += 0.03;
// normalMap.offset.y += 0.015;
// waterMap.offset.x += 0.03;
// waterMap.offset.y += 0.015;
// normalMap.offset.x += 0.002;
// normalMap.offset.y += 0.001;
// waterMap.offset.x += 0.002; // 让颜色贴图也流动
// });
// // 创建线水组
// const lineWaterGroup = new Group();
// const projection = geoMercator().center(this.geoProjectionCenter).scale(this.geoProjectionScale).translate([0, 0]);
...
...
@@ -1897,109 +1848,28 @@ export class World extends Mini3d {
// lines = geometry.coordinates;
// }
// lines.forEach((line) => {
// // 生成带宽度的水带
// const points = line.map(([lng, lat]) => {
// const [x, y] = projection([lng, lat]);
// return new THREE.Vector3(x, -y, this.depth + 0.26);
// return new THREE.Vector3(x, -y, this.depth + 0.26);
// 保证高于地表
// });
// if (points.length < 2) return;
// // 宽度渐变:首尾变窄
// const riverWidthMax = 0.08, riverWidthMin = 0.02;
// const lefts = [], rights = [];
// for (let i = 0; i < points.length; i++) {
// let t = points.length === 1 ? 0 : i / (points.length - 1);
// let width = riverWidthMin + (1 - Math.abs(t * 2 - 1)) * (riverWidthMax - riverWidthMin);
// let dir;
// if (i === 0) {
// dir = points[1].clone().sub(points[0]);
// } else if (i === points.length - 1) {
// dir = points[i].clone().sub(points[i - 1]);
// } else {
// dir = points[i + 1].clone().sub(points[i - 1]);
// }
// dir.z = 0;
// dir.normalize();
// const normal = new THREE.Vector3(-dir.y, dir.x, 0);
// lefts.push(points[i].clone().add(normal.clone().multiplyScalar(width / 2)));
// rights.push(points[i].clone().add(normal.clone().multiplyScalar(-width / 2)));
// }
// // 顶点、uv、透明度
// const vertices = [];
// const uvs = [];
// const alphas = [];
// let totalLen = 0;
// for (let i = 0; i < points.length; i++) {
// if (i > 0) totalLen += points[i].distanceTo(points[i - 1]);
// let t = points.length === 1 ? 0 : i / (points.length - 1);
// let edgeAlpha = 0.7 + 0.3 * (1 - Math.abs(t * 2 - 1));
// // 左点
// vertices.push(lefts[i]);
// uvs.push(totalLen * 2, 0); // UV缩放更密集
// alphas.push(edgeAlpha);
// // 右点
// vertices.push(rights[i]);
// uvs.push(totalLen * 2, 1);
// alphas.push(edgeAlpha);
// }
// const indices = [];
// for (let i = 0; i < points.length - 1; i++) {
// const a = i * 2, b = i * 2 + 1, c = i * 2 + 2, d = i * 2 + 3;
// indices.push(a, b, c, b, d, c);
// }
// const geometry = new THREE.BufferGeometry();
// const posArr = new Float32Array(vertices.length * 3);
// for (let i = 0; i < vertices.length; i++) {
// posArr[i * 3] = vertices[i].x;
// posArr[i * 3 + 1] = vertices[i].y;
// posArr[i * 3 + 2] = vertices[i].z;
// }
// geometry.setAttribute('position', new THREE.BufferAttribute(posArr, 3));
// geometry.setAttribute('uv', new THREE.BufferAttribute(new Float32Array(uvs), 2));
// geometry.setAttribute('alpha', new THREE.BufferAttribute(new Float32Array(alphas), 1));
// geometry.setIndex(indices);
// // ShaderMaterial实现边缘羽化和流动水波
// const material = new THREE.ShaderMaterial({
// uniforms: {
// map: { value: waterMap },
// normalMap: { value: normalMap },
// color: { value: new THREE.Color(0x4fc3ff) },
// opacity: { value: 0.5 },
// },
// vertexShader: `
// attribute float alpha;
// varying vec2 vUv;
// varying float vAlpha;
// void main() {
// vUv = uv;
// vAlpha = alpha;
// gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
// }
// `,
// fragmentShader: `
// uniform sampler2D map;
// uniform sampler2D normalMap;
// uniform vec3 color;
// uniform float opacity;
// varying vec2 vUv;
// varying float vAlpha;
// void main() {
// vec4 texColor = texture2D(map, vUv);
// float alpha = texColor.a * opacity * vAlpha;
// vec3 finalColor = mix(color, texColor.rgb, 0.8); // 贴图主导
// if(alpha < 0.05) discard;
// gl_FragColor = vec4(finalColor, alpha);
// }
// `,
// // 用TubeGeometry生成带宽度的水带
// const curve = new THREE.CatmullRomCurve3(points);
// const tubeGeometry = new THREE.TubeGeometry(curve, Math.max(32, points.length * 2), 0.01, 16);
// const material = new THREE.MeshStandardMaterial({
// color: 0x4fc3ff,
// transparent: true,
// opacity: 0.35,
// side: DoubleSide,
// depthWrite: false,
// normalMap: normalMap,
// normalScale: new THREE.Vector2(2, 2),
// map: waterMap, // 使用颜色贴图
// metalness: 0.3,
// roughness: 0.7,
// });
// const mesh = new Mesh(geometry, material);
// const mesh = new Mesh(tubeGeometry, material);
// mesh.renderOrder = 11;
// lineWaterGroup.add(mesh);
// });
...
...
@@ -2008,6 +1878,181 @@ export class World extends Mini3d {
// lineWaterGroup,
// };
// }
createLineWater
()
{
let
mapJsonData
=
this
.
assets
.
instance
.
getResource
(
"linewater"
);
let
lineWaterJson
;
try
{
lineWaterJson
=
typeof
mapJsonData
===
"string"
?
JSON
.
parse
(
mapJsonData
)
:
mapJsonData
;
}
catch
(
e
)
{
console
.
error
(
"linewater 解析失败"
,
e
);
return
{
lineWaterGroup
:
null
};
}
const
textureLoader
=
new
THREE
.
TextureLoader
();
let
base_url
=
import
.
meta
.
env
.
BASE_URL
||
"/"
;
const
normalMap
=
textureLoader
.
load
(
base_url
+
"assets/json/waternormals.jpg"
);
normalMap
.
wrapS
=
normalMap
.
wrapT
=
THREE
.
RepeatWrapping
;
const
waterMap
=
textureLoader
.
load
(
base_url
+
"assets/json/watercolor.png"
);
waterMap
.
wrapS
=
waterMap
.
wrapT
=
THREE
.
RepeatWrapping
;
// 流动速度更快
this
.
time
.
on
(
"tick"
,
()
=>
{
normalMap
.
offset
.
x
+=
0.03
;
normalMap
.
offset
.
y
+=
0.015
;
waterMap
.
offset
.
x
+=
0.03
;
waterMap
.
offset
.
y
+=
0.015
;
});
const
lineWaterGroup
=
new
Group
();
const
projection
=
geoMercator
()
.
center
(
this
.
geoProjectionCenter
)
.
scale
(
this
.
geoProjectionScale
)
.
translate
([
0
,
0
]);
(
lineWaterJson
.
features
||
[]).
forEach
((
feature
)
=>
{
const
geometry
=
feature
.
geometry
;
if
(
!
geometry
)
return
;
let
lines
=
[];
if
(
geometry
.
type
===
"LineString"
)
{
lines
=
[
geometry
.
coordinates
];
}
else
if
(
geometry
.
type
===
"MultiLineString"
)
{
lines
=
geometry
.
coordinates
;
}
lines
.
forEach
((
line
)
=>
{
const
points
=
line
.
map
(([
lng
,
lat
])
=>
{
const
[
x
,
y
]
=
projection
([
lng
,
lat
]);
return
new
THREE
.
Vector3
(
x
,
-
y
,
this
.
depth
+
0.26
);
});
if
(
points
.
length
<
2
)
return
;
// 宽度渐变:首尾变窄
const
riverWidthMax
=
0.08
,
riverWidthMin
=
0.02
;
const
lefts
=
[],
rights
=
[];
for
(
let
i
=
0
;
i
<
points
.
length
;
i
++
)
{
let
t
=
points
.
length
===
1
?
0
:
i
/
(
points
.
length
-
1
);
let
width
=
riverWidthMin
+
(
1
-
Math
.
abs
(
t
*
2
-
1
))
*
(
riverWidthMax
-
riverWidthMin
);
let
dir
;
if
(
i
===
0
)
{
dir
=
points
[
1
].
clone
().
sub
(
points
[
0
]);
}
else
if
(
i
===
points
.
length
-
1
)
{
dir
=
points
[
i
].
clone
().
sub
(
points
[
i
-
1
]);
}
else
{
dir
=
points
[
i
+
1
].
clone
().
sub
(
points
[
i
-
1
]);
}
dir
.
z
=
0
;
dir
.
normalize
();
const
normal
=
new
THREE
.
Vector3
(
-
dir
.
y
,
dir
.
x
,
0
);
lefts
.
push
(
points
[
i
].
clone
().
add
(
normal
.
clone
().
multiplyScalar
(
width
/
2
))
);
rights
.
push
(
points
[
i
].
clone
().
add
(
normal
.
clone
().
multiplyScalar
(
-
width
/
2
))
);
}
// 顶点、uv、透明度
const
vertices
=
[];
const
uvs
=
[];
const
alphas
=
[];
let
totalLen
=
0
;
for
(
let
i
=
0
;
i
<
points
.
length
;
i
++
)
{
if
(
i
>
0
)
totalLen
+=
points
[
i
].
distanceTo
(
points
[
i
-
1
]);
let
t
=
points
.
length
===
1
?
0
:
i
/
(
points
.
length
-
1
);
let
edgeAlpha
=
0.7
+
0.3
*
(
1
-
Math
.
abs
(
t
*
2
-
1
));
// 左点
vertices
.
push
(
lefts
[
i
]);
uvs
.
push
(
totalLen
*
2
,
0
);
// UV缩放更密集
alphas
.
push
(
edgeAlpha
);
// 右点
vertices
.
push
(
rights
[
i
]);
uvs
.
push
(
totalLen
*
2
,
1
);
alphas
.
push
(
edgeAlpha
);
}
const
indices
=
[];
for
(
let
i
=
0
;
i
<
points
.
length
-
1
;
i
++
)
{
const
a
=
i
*
2
,
b
=
i
*
2
+
1
,
c
=
i
*
2
+
2
,
d
=
i
*
2
+
3
;
indices
.
push
(
a
,
b
,
c
,
b
,
d
,
c
);
}
const
geometry
=
new
THREE
.
BufferGeometry
();
const
posArr
=
new
Float32Array
(
vertices
.
length
*
3
);
for
(
let
i
=
0
;
i
<
vertices
.
length
;
i
++
)
{
posArr
[
i
*
3
]
=
vertices
[
i
].
x
;
posArr
[
i
*
3
+
1
]
=
vertices
[
i
].
y
;
posArr
[
i
*
3
+
2
]
=
vertices
[
i
].
z
;
}
geometry
.
setAttribute
(
"position"
,
new
THREE
.
BufferAttribute
(
posArr
,
3
));
geometry
.
setAttribute
(
"uv"
,
new
THREE
.
BufferAttribute
(
new
Float32Array
(
uvs
),
2
)
);
geometry
.
setAttribute
(
"alpha"
,
new
THREE
.
BufferAttribute
(
new
Float32Array
(
alphas
),
1
)
);
geometry
.
setIndex
(
indices
);
// ShaderMaterial实现边缘羽化和流动水波
const
material
=
new
THREE
.
ShaderMaterial
({
uniforms
:
{
map
:
{
value
:
waterMap
},
normalMap
:
{
value
:
normalMap
},
color
:
{
value
:
new
THREE
.
Color
(
0x4fc3ff
)
},
opacity
:
{
value
:
0.5
},
},
vertexShader
:
`
attribute float alpha;
varying vec2 vUv;
varying float vAlpha;
void main() {
vUv = uv;
vAlpha = alpha;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`
,
fragmentShader
:
`
uniform sampler2D map;
uniform sampler2D normalMap;
uniform vec3 color;
uniform float opacity;
varying vec2 vUv;
varying float vAlpha;
void main() {
vec4 texColor = texture2D(map, vUv);
float alpha = texColor.a * opacity * vAlpha;
vec3 finalColor = mix(color, texColor.rgb, 0.8); // 贴图主导
if(alpha < 0.05) discard;
gl_FragColor = vec4(finalColor, alpha);
}
`
,
transparent
:
true
,
side
:
DoubleSide
,
depthWrite
:
false
,
});
const
mesh
=
new
Mesh
(
geometry
,
material
);
mesh
.
renderOrder
=
11
;
lineWaterGroup
.
add
(
mesh
);
});
});
return
{
lineWaterGroup
,
};
}
// 加载3d模型
showDroneAtLngLat
(
url
,
lng
,
lat
,
height
,
scale
)
{
// 经纬度转平面坐标
...
...
@@ -2036,8 +2081,6 @@ export class World extends Mini3d {
drone
.
position
.
copy
(
position
);
drone
.
scale
.
set
(
scale
,
scale
,
scale
);
// 可根据需要调整旋转
// drone.rotation.set(0, Math.PI, 0);
// let propeller1 = drone.getObjectByName("phase8_Master25");
let
propeller1
=
drone
.
getObjectByName
(
"prop_1_jnt34"
);
let
propeller2
=
drone
.
getObjectByName
(
"prop_2_jnt35"
);
let
propeller3
=
drone
.
getObjectByName
(
"prop_3_jnt36"
);
...
...
@@ -2060,6 +2103,15 @@ export class World extends Mini3d {
drone
.
addEventListener
(
"mousedown"
,
(
event
)
=>
{
this
.
showDronePopup
(
drone
);
});
this
.
drone
=
drone
;
// 保存无人机实例
this
.
time
.
on
(
"tick"
,
()
=>
{
if
(
!
drone
)
return
;
const
speed
=
0.1
;
// 控制移动速度
if
(
this
.
droneMoveState
.
w
)
this
.
drone
.
position
.
z
-=
speed
;
if
(
this
.
droneMoveState
.
s
)
this
.
drone
.
position
.
z
+=
speed
;
if
(
this
.
droneMoveState
.
a
)
this
.
drone
.
position
.
x
-=
speed
;
if
(
this
.
droneMoveState
.
d
)
this
.
drone
.
position
.
x
+=
speed
;
});
this
.
moveDroneAlongPath
(
drone
,
[
...
...
@@ -2149,6 +2201,11 @@ export class World extends Mini3d {
<video src="https://media.w3.org/2010/05/sintel/trailer.mp4" controls poster="" preload="metadata" custom-cache="false" ></video>
</div>
`
;
let
lnglatPossition
=
this
.
worldToLngLat
(
drone
.
position
.
x
,
drone
.
position
.
z
);
console
.
log
(
"无人机经纬度位置:"
,
lnglatPossition
);
document
.
body
.
appendChild
(
popup
);
this
.
dronePopup
=
popup
;
// 优化全屏性能卡顿
...
...
@@ -2269,6 +2326,98 @@ export class World extends Mini3d {
if
(
drone
.
_moveReq
)
cancelAnimationFrame
(
drone
.
_moveReq
);
drone
.
_moveReq
=
requestAnimationFrame
(
animate
);
}
onKeyDown
(
e
)
{
if
(
!
this
.
drone
)
return
;
if
(
e
.
key
===
"w"
)
this
.
droneMoveState
.
w
=
true
;
if
(
e
.
key
===
"a"
)
this
.
droneMoveState
.
a
=
true
;
if
(
e
.
key
===
"s"
)
this
.
droneMoveState
.
s
=
true
;
if
(
e
.
key
===
"d"
)
this
.
droneMoveState
.
d
=
true
;
}
onKeyUp
(
e
)
{
if
(
!
this
.
drone
)
return
;
if
(
e
.
key
===
"w"
)
this
.
droneMoveState
.
w
=
false
;
if
(
e
.
key
===
"a"
)
this
.
droneMoveState
.
a
=
false
;
if
(
e
.
key
===
"s"
)
this
.
droneMoveState
.
s
=
false
;
if
(
e
.
key
===
"d"
)
this
.
droneMoveState
.
d
=
false
;
}
worldToLngLat
(
x
,
y
,
z
=
0
)
{
const
projection
=
geoMercator
()
.
center
(
this
.
geoProjectionCenter
)
.
scale
(
this
.
geoProjectionScale
)
.
translate
([
0
,
0
]);
// 反向投影
return
projection
.
invert
([
x
,
-
y
]);
}
/**
* 在指定经纬度数组生成着火点和烟雾效果
* @param {Array} lngLatArr [[lng,lat], ...]
*/
createFireWithSmoke
(
lngLatArr
)
{
const
fireGroup
=
new
THREE
.
Group
();
this
.
scene
.
add
(
fireGroup
);
// 加载火焰和烟雾贴图
// 建议准备 fire.png 贴图
// const fireTexture = this.assets.instance.getResource("fire");
const
smokeTexture
=
this
.
assets
.
instance
.
getResource
(
"smoke"
);
// 存储所有烟雾sprite
const
smokeSprites
=
[];
lngLatArr
.
forEach
(([
lng
,
lat
])
=>
{
const
[
x
,
y
]
=
this
.
geoProjection
([
lng
,
lat
]);
const
z
=
this
.
depth
;
// 火焰Sprite(如有火焰贴图可解开注释)
// if (fireTexture) {
// const fireMaterial = new THREE.SpriteMaterial({
// map: fireTexture,
// color: 0xff6600,
// transparent: true,
// opacity: 0.85,
// blending: THREE.AdditiveBlending,
// depthWrite: false,
// });
// const fireSprite = new THREE.Sprite(fireMaterial);
// fireSprite.position.set(x, -y, z);
// fireSprite.scale.set(1, 1.5, 1); // 可调大
// fireGroup.add(fireSprite);
// }
// 烟雾Sprite
const
smokeMaterial
=
new
THREE
.
SpriteMaterial
({
map
:
smokeTexture
,
color
:
0xffffff
,
transparent
:
true
,
opacity
:
1
,
blending
:
THREE
.
NormalBlending
,
depthWrite
:
false
,
depthTest
:
false
,
});
const
smokeSprite
=
new
THREE
.
Sprite
(
smokeMaterial
);
smokeSprite
.
position
.
set
(
x
,
z
,
-
y
);
// y轴为“上”
smokeSprite
.
scale
.
set
(
0.5
,
1
,
0.5
);
smokeSprite
.
renderOrder
=
99
;
fireGroup
.
add
(
smokeSprite
);
smokeSprites
.
push
({
sprite
:
smokeSprite
,
baseY
:
z
+
1
});
});
// 只注册一次动画
this
.
time
.
on
(
"tick"
,
()
=>
{
const
t
=
Date
.
now
()
*
0.001
;
smokeSprites
.
forEach
(({
sprite
,
baseY
},
i
)
=>
{
sprite
.
position
.
y
+=
0.01
;
if
(
sprite
.
position
.
y
>
baseY
+
1
)
{
sprite
.
position
.
y
=
baseY
;
}
sprite
.
material
.
opacity
=
0.4
+
0.3
*
Math
.
abs
(
Math
.
sin
(
t
+
i
));
sprite
.
rotation
.
z
+=
0.002
;
});
});
}
// 跳转到指定group
zoomToFocusMapGroup
(
group
)
{
// 创建一个 Box3 来计算 focusMapGroup 的边界盒
...
...
@@ -2308,6 +2457,7 @@ export class World extends Mini3d {
}
update
()
{
super
.
update
();
this
.
controls
&&
this
.
controls
.
update
();
// 每帧更新 controls
this
.
interactionManager
&&
this
.
interactionManager
.
update
();
}
destroy
()
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论