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>

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

相关推荐
xw540 分钟前
uni-app项目跑APP报useStore报错
前端·uni-app
!win !44 分钟前
uni-app项目跑APP报useStore报错
前端·uni-app
拾光拾趣录1 小时前
Flexbox 布局:从“垂直居中都搞不定”到写出响应式万能布局
前端·css
huxihua20061 小时前
各种前端框架界面
前端
拾光拾趣录1 小时前
GET/POST 的区别:从“为什么登录请求不能用 GET”说起
前端·网络协议
Carlos_sam2 小时前
OpenLayers:ol-wind之渲染风场图全解析
前端·javascript
拾光拾趣录2 小时前
闭包:从“变量怎么还没死”到写出真正健壮的模块
前端·javascript
拾光拾趣录2 小时前
for..in 和 Object.keys 的区别:从“遍历对象属性的坑”说起
前端·javascript
OpenTiny社区2 小时前
把 SearchBox 塞进项目,搜索转化率怒涨 400%?
前端·vue.js·github
编程猪猪侠3 小时前
Tailwind CSS 自定义工具类与主题配置指南
前端·css