| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- import * as Cesium from "cesium";
- import { WindLayer } from "../../kLayer/index.js";
- /**
- * 创建风场
- * @param {*} viewer
- * @param {*} controlColor
- */
- async function createWind(viewer, windData, controlColor) {
- // 加载风场
- // Create wind layer with options
- const windLayer = await new WindLayer(viewer, windData, {
- // ==================== 粒子相关 ====================
- particlesTextureSize: 1500, // 粒子纹理尺寸,决定粒子总数(size * size)
- particleHeight: 2500, // 粒子高度(相对于地表)
- lineWidth: { min: 1.5, max: 2.5 }, // 粒子尾迹宽度范围
- lineLength: { min: 300, max: 600 }, // 粒子尾迹长度范围
- speedFactor: 1.0, // 粒子速度倍数
- dropRate: 0.003, // 粒子掉落率
- dropRateBump: 0.001, // 慢粒子额外掉落率
- dynamic: true, // 是否启用动态动画
- flipY: false, // 是否翻转 Y 坐标(视数据情况而定)
- // ==================== 风场数据相关 ====================
- domain: undefined, // 可选:风速范围 domain = [min, max]
- displayRange: undefined, // 可选:可视化速度范围 displayRange = [min, max]
- uMax: undefined, // 可选:u 方向速度最大值(用于归一化)
- vMax: undefined, // 可选:v 方向速度最大值(用于归一化)
- // ==================== 颜色相关 ====================
- colors: [
- // 粒子颜色映射,可按速度渐变
- "rgb(255,255,0)",
- "rgb(255,0,0)",
- "rgb(0,0,255)",
- // "rgb(0,255,255)",
- ],
- // ==================== 位置和范围 ====================
- bounds: undefined, // 可选:指定风场边界 [xmin, ymin, xmax, ymax]
- projection: undefined, // 可选:投影函数,用于坐标转换
- extent: undefined, // 可选:覆盖区域(Cesium.Rectangle)
- // ==================== 粒子纹理/形状 ====================
- particleTexture: controlColor, // 可选:自定义粒子纹理
- fadeOpacity: 0.996, // 粒子尾迹渐隐率(0~1,越小越快消失)
- // ==================== 性能优化 ====================
- maxParticles: 50000000, // 最大粒子数量(默认由 particlesTextureSize 决定)
- skipRate: 1, // 粒子更新跳帧率(提升性能)
- // ==================== 其他 ====================
- animation: true, // 是否开启动画
- autoUpdate: true, // 是否自动更新风场
- });
- return windLayer;
- }
- /**
- * @description 相机飞行动画
- * @param {Object} options 配置对象
- * @param {Cesium.Viewer} options.viewer Cesium实例
- * @param {Array} options.points 动画路径数组
- * - lon {number} 经度
- * - lat {number} 纬度
- * - height {number} 高度
- * - heading {number} 朝向角度(度)
- * - pitch {number} 俯仰角度(度)
- * - roll {number} 翻滚角度(度)
- * - duration {number} 飞行动画时长(秒)
- * @param {Function} [options.easingFunction] 缓动函数
- */
- function flyCameraPath({
- viewer,
- points,
- easingFunction = Cesium.EasingFunction.LINEAR_NONE,
- }) {
- if (!viewer || !points || points.length === 0) {
- console.error("flyCameraPath: 参数错误,viewer或points缺失");
- return;
- }
- // 生成动画步骤
- const steps = [];
- for (let i = 0; i < points.length; i++) {
- const p = points[i];
- // 基础飞行动画
- steps.push({
- destination: Cesium.Cartesian3.fromDegrees(p.lon, p.lat, p.height),
- duration: p.duration || 3,
- orientation: {
- heading: Cesium.Math.toRadians(p.heading || 0),
- pitch: Cesium.Math.toRadians(p.pitch || -90),
- roll: Cesium.Math.toRadians(p.roll || 0),
- },
- maximumHeight: p.maximumHeight || p.height,
- });
- }
- // 执行动画(递归)
- function runStep(index) {
- if (index >= steps.length) return;
- const step = steps[index];
- viewer.camera.flyTo({
- ...step,
- easingFunction,
- complete: () => runStep(index + 1),
- });
- }
- runStep(0);
- }
- /**
- * 添加降雪效果
- * @param {Viewer} viewer - 视图对象,通常是一个包含 DOM 元素和其他相关信息的对象。
- * @see {@link https://sandcastle.cesium.com/?src=Particle%20System%20Weather.html|Cesium 天气示例}
- */
- function addPrimitivesSnowCesium(viewer) {
- const scene = viewer.scene;
- // snow
- const snowParticleSize = 12.0;
- const snowRadius = 100000.0;
- const minimumSnowImageSize = new Cesium.Cartesian2(
- snowParticleSize,
- snowParticleSize
- );
- const maximumSnowImageSize = new Cesium.Cartesian2(
- snowParticleSize * 2.0,
- snowParticleSize * 2.0
- );
- let snowGravityScratch = new Cesium.Cartesian3();
- const snowUpdate = function (particle) {
- snowGravityScratch = Cesium.Cartesian3.normalize(
- particle.position,
- snowGravityScratch
- );
- Cesium.Cartesian3.multiplyByScalar(
- snowGravityScratch,
- Cesium.Math.randomBetween(-30.0, -300.0),
- snowGravityScratch
- );
- particle.velocity = Cesium.Cartesian3.add(
- particle.velocity,
- snowGravityScratch,
- particle.velocity
- );
- const distance = Cesium.Cartesian3.distance(
- scene.camera.position,
- particle.position
- );
- if (distance > snowRadius) {
- particle.endColor.alpha = 0.0;
- } else {
- particle.endColor.alpha = 1.0 / (distance / snowRadius + 0.1);
- }
- };
- const data = scene.primitives.add(
- new Cesium.ParticleSystem({
- modelMatrix: new Cesium.Matrix4.fromTranslation(scene.camera.position),
- minimumSpeed: -1.0,
- maximumSpeed: 0.0,
- lifetime: 15.0,
- emitter: new Cesium.SphereEmitter(snowRadius),
- startScale: 0.5,
- endScale: 1.0,
- image: "snowflake_particle.png",
- emissionRate: 7000.0,
- startColor: Cesium.Color.WHITE.withAlpha(0.0),
- endColor: Cesium.Color.WHITE.withAlpha(1.0),
- minimumImageSize: minimumSnowImageSize,
- maximumImageSize: maximumSnowImageSize,
- updateCallback: snowUpdate,
- })
- );
- scene.skyAtmosphere.hueShift = -0.8;
- scene.skyAtmosphere.saturationShift = -0.7;
- scene.skyAtmosphere.brightnessShift = -0.33;
- scene.fog.density = 0.001;
- scene.fog.minimumBrightness = 0.8;
- return data;
- }
- /**
- * 添加降雨效果
- * @param {Viewer} viewer - 视图对象,通常是一个包含 DOM 元素和其他相关信息的对象。
- * @see {@link https://sandcastle.cesium.com/?src=Particle%20System%20Weather.html|Cesium 天气示例}
- */
- function addPrimitivesRianCesium(viewer, size = 4) {
- // 先清空其他效果
- const scene = viewer.scene;
- // rain
- const rainParticleSize = 15.0;
- const rainRadius = 100000.0;
- const rainImageSize = new Cesium.Cartesian2(
- rainParticleSize,
- rainParticleSize * size //图片大小
- );
- let rainGravityScratch = new Cesium.Cartesian3();
- const rainUpdate = function (particle) {
- rainGravityScratch = Cesium.Cartesian3.normalize(
- particle.position,
- rainGravityScratch
- );
- rainGravityScratch = Cesium.Cartesian3.multiplyByScalar(
- rainGravityScratch,
- -1050.0,
- rainGravityScratch
- );
- particle.position = Cesium.Cartesian3.add(
- particle.position,
- rainGravityScratch,
- particle.position
- );
- const distance = Cesium.Cartesian3.distance(
- scene.camera.position,
- particle.position
- );
- if (distance > rainRadius) {
- particle.endColor.alpha = 0.0;
- } else {
- particle.endColor.alpha =
- Cesium.Color.BLUE.alpha / (distance / rainRadius + 0.1);
- }
- };
- const data = scene.primitives.add(
- new Cesium.ParticleSystem({
- modelMatrix: new Cesium.Matrix4.fromTranslation(scene.camera.position),
- speed: -1.0,
- lifetime: 15.0,
- emitter: new Cesium.SphereEmitter(rainRadius),
- startScale: 1.0,
- endScale: 0.0,
- image: "circular_particle.png",
- emissionRate: 9000.0,
- startColor: new Cesium.Color(0.27, 0.5, 0.7, 0.0),
- endColor: new Cesium.Color(0.27, 0.5, 0.7, 0.98),
- imageSize: rainImageSize,
- updateCallback: rainUpdate,
- })
- );
- scene.skyAtmosphere.hueShift = -0.97;
- scene.skyAtmosphere.saturationShift = 0.25;
- scene.skyAtmosphere.brightnessShift = -0.4;
- scene.fog.density = 0.00025;
- scene.fog.minimumBrightness = 0.01;
- return data;
- }
- // 加载glb模型
- function addGlbModel(viewer) {
- if (!viewer || !devJson || !Array.isArray(devJson)) return;
- devJson.forEach((item) => {
- const { name, position } = item;
- if (!position || position.length < 3) return;
- const [lon, lat, height] = position;
- const modal = viewer.entities.add({
- name: name,
- position: Cesium.Cartesian3.fromDegrees(lon, lat, height),
- model: {
- uri: "/modal/turbine.glb", // 模型路径
- scale: 0.1, // 缩放比例
- minimumPixelSize: 64, // 保证远距离也能显示
- maximumScale: 200, // 最大缩放
- runAnimations: true, // 如果模型有动画,自动播放
- // 关键:直接调整模型的亮度和光照相关属性
- color: Cesium.Color.WHITE, // 可以尝试给模型一个整体颜色乘数
- colorBlendMode: Cesium.ColorBlendMode.MIX, // 颜色混合模式
- silhouetteColor: Cesium.Color.WHITE, // 轮廓颜色
- // 最有效的属性:直接放大光源的影响
- luminanceAtZenith: 1.0, // 天顶亮度(增大此值可使模型更亮)
- },
- label: {
- show: true,
- scale: 1,
- heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
- fillColor: Cesium.Color.WHITE,
- text: name,
- showBackground: true,
- backgroundColor: Cesium.Color.BLACK.withAlpha(0.5),
- pixelOffset: new Cesium.Cartesian2(0, -420),
- distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
- 100,
- 10000
- ),
- },
- });
- console.log(`加载模型`, modal);
- });
- }
- /**
- * 绑定右键事件,输出当前相机完整参数
- * @param {Cesium.Viewer} viewer
- */
- function bindRightClickLogCamera(viewer) {
- const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
- handler.setInputAction(function () {
- const camera = viewer.camera;
- const pos = camera.positionCartographic;
- const lon = Cesium.Math.toDegrees(pos.longitude).toFixed(6);
- const lat = Cesium.Math.toDegrees(pos.latitude).toFixed(6);
- const height = pos.height.toFixed(2);
- const heading = Cesium.Math.toDegrees(camera.heading).toFixed(2);
- const pitch = Cesium.Math.toDegrees(camera.pitch).toFixed(2);
- const roll = Cesium.Math.toDegrees(camera.roll).toFixed(2);
- console.log(
- `相机参数:经度=${lon}, 纬度=${lat}, 高度=${height}, heading=${heading}, pitch=${pitch}, roll=${roll}`
- );
- }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
- return handler; // 可以用 handler.destroy() 解绑
- }
- export {
- createWind,
- flyCameraPath,
- addGlbModel,
- addPrimitivesSnowCesium,
- addPrimitivesRianCesium,
- bindRightClickLogCamera,
- };
|