Cesium 自定义Primitive-线

本文详细介绍了如何创建一个自定义的CustomPolylinePrimitive,演示了如何动态更新线的点位,以及如何在Three.js中实现线的绘制和更新。通过实例展示了如何在场景中添加并实时修改点位以达到预期效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、创作思路

        1、创建一个自定义CustomPrimitive

        2、可动态更新线的点位

        3、方便后期绘制线

二、实现代码

        1、创建一个CustomPolylinePrimitive类,并加入更新的代码

export default class CustomPolylinePrimitive {
  constructor(options) {
    this._props = options;
    /**
     * 渲染列表
     * @type {*[]}
     * @private
     */
    this._primitiveCollection = [];

    this._dynamicPrimitive = undefined;
  }
  updateProperty(options) {
    this._props = {
      ...this._props,
      ...options,
    };
  }
  /**
   * 更新
   * @param frameState
   */
  update(frameState) {
    this._primitiveCollection.forEach((primitive) => {
      primitive && !primitive.isDestroyed() && primitive.update(frameState);
    });
    if (this._dynamicPrimitive) {
      this._dynamicPrimitive.update(frameState);
    }
  }
}

        2、编写更新代码

updateProperty(options) {
    this._props = {
      ...this._props,
      ...options,
    };
    let positions = this._props.positions;
    let complete = this._props.complete;
    if (positions.length > 1) {
      let dynamicPrimitive = this._dynamicPrimitive;
      if (dynamicPrimitive) {
        dynamicPrimitive.destroy();
        dynamicPrimitive = null;
        this._dynamicPrimitive = null;
      }
      let primitive = this.initPolylinePrimitive(positions);
      if (complete) {
        this._primitiveCollection.push(primitive);
      } else {
        this._dynamicPrimitive = primitive;
      }
    }
  }
  initPolylinePrimitive(positions) {
    let instance = new GeometryInstance({
      geometry: new GroundPolylineGeometry({
        positions: positions,
        width: 4,
      }),
    });
    return new GroundPolylinePrimitive({
      geometryInstances: instance,
      appearance: new PolylineMaterialAppearance({
        material: new Material({
          fabric: {
            type: "Color",
            uniforms: {
              color: Color.fromCssColorString("#ff0000"),
            },
          },
        }),
      }),
      asynchronous: false,
    });
  }

        3、测试代码,自定义动态更新点位

viewer.camera.flyTo({
    destination: origin2,
    complete: () => {
      let primitive = new CustomPolylinePrimitive({});
      viewer.scene.primitives.add(primitive);
      let count = 0;
      let lon = 106;
      let lat = 26;
      let positions = [];
      let interval = setInterval(() => {
        let lonTemp = lon + count * 0.00001;
        let latTemp = lat + (count % 2) * 0.00001;
        positions.push(Cartesian3.fromDegrees(lonTemp, latTemp));
        primitive.updateProperty({
          positions: positions,
          complete: count === 11,
        });
        if (count > 10) {
          clearInterval(interval);
        }
        count++;
      }, 1000);
    },
  });

三、实现效果

### Cesium 中使用 Primitive 绘制流动线效果实现方法 要在 Cesium 中使用 `Primitive` 绘制具有流动效果的线条,可以通过自定义材质并结合时间参数来模拟动态变化的效果。以下是详细的说明和代码示例。 #### 原理概述 为了实现流动线效果,通常会利用纹理贴图(Texture)或者基于顶点的颜色渐变来创建视觉上的运动感。具体来说,可以借助 `Cesium.Fabric` 自定义材质,并通过调整材质中的时间变量控制颜色的变化位置[^2]。这种技术的核心在于更新每帧渲染时的时间戳,从而让颜色沿路径移动。 --- #### 代码实现 以下是一个完整的例子,展示如何使用 `Primitive` 和自定义材质绘制一条带有流动效果的线: ```typescript import * as Cesium from "cesium"; // 初始化 Viewer const viewer = new Cesium.Viewer("cesiumContainer", { terrainProvider: Cesium.createWorldTerrain(), }); // 定义线条的起点和终点 const start = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883); const end = Cesium.Cartesian3.fromDegrees(-80.50, 35.14); // 创建几何实例 const geometryInstance = new Cesium.GeometryInstance({ geometry: new Cesium.PolylineGeometry({ positions: [start, end], width: 5, }), }); // 自定义材质函数 const customMaterial = new Cesium.Material({ fabric: { type: "FlowLine", uniforms: { color: new Cesium.Color(0.0, 1.0, 1.0, 1.0), // 颜色 (青色) speed: 0.005, // 流动速度 }, source: ` czm_material czm_getMaterial(czm_materialInput materialInput){ czm_material material = czm_getDefaultMaterial(materialInput); float time =czm_frameNumber * ${customMaterial.uniforms.speed}; // 动态时间 vec2 st = materialInput.st; float dist = distance(st.x, fract(time)); // 计算距离 if(dist < 0.05){ // 控制流动宽度 material.alpha = 1.0; }else{ material.alpha = 0.0; } material.diffuse = color.rgb; return material; } `, }, }); // 添加 Primitive 到场景中 const polylinePrimitive = new Cesium.Primitive({ geometryInstances: geometryInstance, appearance: new Cesium.PolylineMaterialAppearance({ flat: true, material: customMaterial, }), }); viewer.scene.primitives.add(polylinePrimitive); // 设置相机视角 viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees( (-75.59777 - 80.5) / 2, (40.03883 + 35.14) / 2, 500000 ), }); ``` --- #### 关键点解析 1. **自定义材质 (`Fabric`)** 上述代码中,我们通过 `Cesium.Material` 的 `fabric` 属性定义了一个名为 `"FlowLine"` 的新材质类型。该材质接受两个参数:`color` 表示线条颜色;`speed` 是流速因子,用于控制动画的速度[^2]。 2. **动态时间计算** 材质脚本内的 `time` 变量由全局帧数乘以指定速度得到。这使得每次重绘时都能获得不同的偏移值,进而形成流动效果。 3. **透明度处理** 在 GLSL 片段着色器部分,当像素到当前时间对应的虚拟波峰的距离小于设定阈值时赋予其完全不透明状态,反之则设为全透明。这样就实现了类似光带滑过的现象。 4. **性能优化建议** 如果需要同时显示大量此类流动线,则应考虑批量化管理以及减少不必要的重复计算操作,比如共享同一套 Shader 或者提前缓存某些固定数据结构等措施[^1]。 --- #### 注意事项 - 确保引入了最新版本的 Cesium 库文件。 - 对于复杂项目可能还需要额外配置 WebGL 渲染环境等相关依赖项。 - 考虑不同浏览器兼容性和硬件加速支持情况下的表现差异。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

生活真难

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值