Cesium保姆教程之图片轨迹线

Cesium保姆教程之图片轨迹线

本教程主要将工作中用的cesium功能特点本着简洁的原则进行总结,尽量对每一步代码进行注释,以此来达到通透理解。本篇是本教程的第二个功能,主要实现图片轨迹线材质的实现和对象展示效果,可将轨迹绘制成一条流动的轨迹线并将轨迹赋予图片纹理,以此来实现图片在流动的效果。

实现效果

实现原理

图片轨迹线的实现原理是通过自定义对应的图像轨迹材质ImageTrailMaterial,借助于Cesium的entity类的polyline对象对轨迹进行绘制,再将材质按照纹理对象附到轨迹线上。

实现过程

材质对象

材质绘制(WebGL)

fragementShader(参考网上教程)

glsl 复制代码
uniform sampler2D image; 
      uniform float speed;
      uniform vec4 color;
      uniform vec2 repeat;
      
      czm_material czm_getMaterial(czm_materialInput materialInput){
        czm_material material=czm_getDefaultMaterial(materialInput);
        vec2 st=repeat * materialInput.st;
        float time=fract(czm_frameNumber*speed/1000.);
        //st.s是横轴方向运动,st.t是纵轴,
        //vec2(fract(st.s-time),st.t)是横轴按照时间变化而变化,纵轴保持正常不变化
        vec4 colorImage=texture2D(image,vec2(fract(st.s-time),st.t));
        if(color.a==0.){
          material.alpha=colorImage.a;
          material.diffuse=colorImage.rgb;
        }else{
          material.alpha=colorImage.a*color.a;
          material.diffuse=max(color.rgb*material.alpha*3.,color.rgb);
        }
        return material;
      }

完整代码

js 复制代码
import * as Cesium from "cesium"
/**
 * 定义Cesium材质对象
 */
class ImageTrailMaterial {
  constructor(options = {}) {
    this._definitionChanged = new Cesium.Event();
    this._color = undefined;
    this._colorSubscription = undefined;
    this._speed = undefiend;
    this._speedSubscription = undefined;
    this._image = undefined;
    this._imageSubscription = undefined;
    this._repeat = undefined;
    this._repeatSubscription = undefined;
    this.color = options.color || Cesium.Color.fromBytes(0, 0, 255, 255);
    this.speed = options.speed || 1;
    this.image = options.image; 
    this.repeat = new Cesium.Cartesian2(
      options.repeat?.x || 1,
      options.repeat?.y || 1
    );
  }
  
  get isConstant() {
      return falsse;
  }
  
  get definitionChanged() {
      return this._definitionChanged;
  }
  
  getType() {
    return Cesium.Material.ImageTrailMaterialType;
  }
 
  getValue(time, result) {
    if (!result) {
      result = {};
    }
    result.color = Cesium.Property.getValueOrUndefined(this._color, time);
    result.image = Cesium.Property.getValueOrUndefined(this._image, time);
    result.repeat = Cesium.Property.getValueOrUndefined(this._repeat, time);
    result.speed = this._speed;
    return result;
  }
 
  equals(other) {
    return (
      this === other ||
      (other instanceof ImageTrailMaterial &&
        Cesium.Property.equals(this._color, other._color) &&
        Cesium.Property.equals(this._image, other._image) &&
        Cesium.Property.equals(this._repeat, other._repeat) &&
        Cesium.Property.equals(this._speed, other._speed))
    );
  }
}
 
Object.defineProperties(ImageTrailMaterial.prototype, {
  color: Cesium.createPropertyDescriptor("color"),
  speed: Cesium.createPropertyDescriptor("speed"),
  image: Cesium.createPropertyDescriptor("image"),
  repeat: Cesium.createPropertyDescriptor("repeat"),
});
//材质类型
Cesium.Material.ImageTrailMaterialType = "PolylineImageTrail";
//添加材质到缓冲区中
Cesium.Material._materialCache.addMaterial(
  Cesium.Material.ImageTrailMaterialType,
  {
    fabric: {
      type: Cesium.Material.ImageTrailMaterialType,
      //uniform变量
      uniforms: {
        color: new Cesium.Color(1.0, 0.0, 0.0, 0.7),
        image: Cesium.Material.DefaultImageId,
        speed: 1,
        repeat: new Cesium.Cartesian2(1, 1),
      },
      //
      source: fragementShader
    },
    translucent: function () {
      return true;
    },
  }
);
export default ImageTrailMaterial;

前端调用

js 复制代码
<template>
  <div id="cesiumContainer"></div>
</template>
<script setup>
import * as Cesium from "cesium
import { onMounted } from "vue
import ImageTrailMaterial from "@/ImageTrailMaterial";
let viewer = undefined;
onMounted(() => {
})
const addEntities =(viewer) => {
    viewer.entities.add({
        polyline: {
            clampToGround: true,
            //轨迹线的分布位置
            positions: Cesium.Cartesian3.fromDegreesArray([
                137, 36, 138, 36, 138, 37, 137, 37, 137, 38, 138, 38
            ]),
            material: new ImageTrailMaterial({
                //图片的颜色
                color: Cesium.Color.RED,
                //轨迹运行的速率
                speed: 10,
                //随意一张图片
                image: require("@/star.png"),
                //将轨迹分成一行50个图片
                repeat: { x: 40, y: 1 },
            }),
           width: 20,
        },
    });
}
</script>
<style scoped>
#cesiumContainer {
  width: 100%;
  height: 100%;
  position: relative;
}
</style>

好了,本篇的内容到这里就要结束了,如果有任何问题,请在评论区指出来,在这里也希望这篇文章也能帮助到大家,希望与大家一起进步。

相关推荐
橙某人2 分钟前
LogicFlow 工作流撤销与重做:从「全量快照」到「命令模式」🎯
前端·vue.js
铁皮饭盒14 分钟前
Rust版Bun1.4之前, 盘点Bun1.3新特性
前端·javascript·后端
恋猫de小郭14 分钟前
如何让 AI 快速搭建一套生产 Agent ?全面理解 Agent 架构。
前端·人工智能·ai编程
Csvn16 分钟前
Vite 构建缓存优化:二次构建从 15s 降到 2s 的实战方案
前端
晓得迷路了22 分钟前
栗子前端技术周刊第 135 期 - Vite 8.1、Rspack 2.1、Babel 8.0...
前端·javascript·vite
你听得到111 小时前
用户说 App 卡,但说不清在哪?我把 Flutter 监控 SDK 升级成了链路观测工作台
前端·flutter·性能优化
天渺工作室10 小时前
实现一个adblock/adblock plus等浏览器广告拦截器检测插件
前端·javascript
阳光是sunny10 小时前
Vue 项目怎么做用户行为全链路监控?轻量插件方案详解
前端·面试·架构