GuLiMmo
2024-02-28 d5e1d8a5f773738f6766175ea409f47740a24c97
src/utils/cesium/ImageTrailMaterial.ts
@@ -1,127 +1,162 @@
import * as Cesium from 'cesium'
/**
 * 定义Cesium材质对象
 */
class ImageTrailMaterial {
  _definitionChanged: Cesium.Event<(...args: any[]) => void>;
  _color: undefined;
  _colorSubscription: undefined;
  _speed: undefined;
  _speedSubscription: undefined;
  _image: undefined;
  _imageSubscription: undefined;
  _repeat: undefined;
  _repeatSubscription: undefined;
  color: any;
  speed: any;
  image: any;
  repeat: Cesium.Cartesian2;
  constructor (options : any = {}) {
    this._definitionChanged = new Cesium.Event()
    this._color = undefined
    this._colorSubscription = undefined
    this._speed = undefined
    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
    )
  }
import * as cesium from 'cesium'
  get isConstant () {
    return false
  }
const Cesium: any = cesium
  get definitionChanged () {
    return this._definitionChanged
  }
const getResource = (name: string) => {
  return new URL(`/src/assets/icons/${name}`, import.meta.url).href
}
  getType () {
    return Cesium.Material.ImageTrailMaterialType
  }
const defaultColor = Cesium.Color.TRANSPARENT
const defaultImage = getResource('arrow-right.png')
const defaultImageimageW = 10
const defaultAnimation = false
const defaultDuration = 3000
  getValue (time: any, result: any) {
    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
  }
function ImageTrailMaterial (this: any, opt: any = {}) {
  opt = Cesium.defaultValue(opt, Cesium.defaultValue.EMPTY_OBJECT)
  this._definitionChanged = new Cesium.Event()
  // 自定义材质
  // 自定义图片颜色
  this._color = undefined
  this._colorSubscription = undefined
  // 自定义背景颜色
  this._backgroundColor = undefined
  this._backgroundColorSubscription = undefined
  // 图片
  this._image = undefined
  this._imageSubscription = undefined
  // 图片宽度
  this._imageW = undefined
  this._imageWSubscription = undefined
  // 是否开启动画
  this._animation = undefined
  this._animationSubscription = undefined
  // 动画持续时间
  this._duration = undefined
  this._durationSubscription = undefined
  equals (other: this) {
    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))
    )
  // 变量初始化
  this.color = opt.color || defaultColor // 颜色
  this.backgroundColor = opt.backgroundColor || defaultColor // 颜色
  this._image = opt.image || defaultImage // 材质图片
  this.imageW = opt.imageW || defaultImageimageW
  this.animation = opt.animation || defaultAnimation
  this.duration = opt.duration || defaultDuration
  this._time = undefined
}
ImageTrailMaterial.prototype.getType = function () {
  return Cesium.Material.ImageTrailMaterialType
}
// 这个方法在每次渲染时被调用,result的参数会传入glsl中。
ImageTrailMaterial.prototype.getValue = function (
  time: any,
  result: {
    color?: any
    backgroundColor?: any
    image?: any
    imageW?: any
    animation?: any
    time?: any
  },
) {
  if (!Cesium.defined(result)) {
    result = {}
  }
  // result.color = Cesium.Property.getValueOrClonedDefault(
  //   this._color,
  //   time,
  //   defaultColor,
  //   result.color,
  // )
  // result.backgroundColor = Cesium.Property.getValueOrClonedDefault(
  //   this._backgroundColor,
  //   time,
  //   defaultColor,
  //   result.backgroundColor,
  // )
  result.color = Cesium.Property.getValueOrUndefined(this._color, time)
  result.backgroundColor = Cesium.Property.getValueOrUndefined(this._backgroundColor, time)
  result.image = this._image
  result.imageW = this._imageW
  result.animation = this._animation
  if (this._time === undefined) {
    this._time = new Date().getTime()
  }
  result.time =
    ((new Date().getTime() - this._time) % this._duration) / this._duration
  return result
}
ImageTrailMaterial.prototype.equals = function (other: {
  _color: any
  _backgroundColor: any
}) {
  return (
    this === other ||
    (other instanceof ImageTrailMaterial &&
      Cesium.Property.equals(this._color, other._color) &&
      Cesium.Property.equals(this._backgroundColor, other._backgroundColor))
  )
}
Object.defineProperties(ImageTrailMaterial.prototype, {
  isConstant: {
    get: function get () {
      return false
    },
  },
  definitionChanged: {
    get: function get () {
      return this._definitionChanged
    },
  },
  color: Cesium.createPropertyDescriptor('color'),
  speed: Cesium.createPropertyDescriptor('speed'),
  backgroundColor: Cesium.createPropertyDescriptor('backgroundColor'),
  image: Cesium.createPropertyDescriptor('image'),
  repeat: Cesium.createPropertyDescriptor('repeat'),
  imageW: Cesium.createPropertyDescriptor('imageW'),
  animation: Cesium.createPropertyDescriptor('animation'),
  duration: Cesium.createPropertyDescriptor('duration'),
})
// 材质类型
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: `
                    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));
                        vec4 fragColor;
                        fragColor.rgb=color.rgb / 1.0;
                        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;
                    }
                    `
    },
    translucent: function () {
      return true
    },
  }
)
export default ImageTrailMaterial
// 写到Cesium对象上,就可以像其他MaterialProperty一样使用了
Cesium.Material.ImageTrailMaterialType = 'PolylineImageTrail'
Cesium.Material._materialCache.addMaterial(Cesium.Material.ImageTrailMaterialType, {
  fabric: {
    type: 'ImageLine',
    uniforms: {
      // uniforms参数跟我们上面定义的参数以及getValue方法中返回的result对应,这里值是默认值
      color: new Cesium.Color(1, 0, 0, 1.0),
      backgroundColor: new Cesium.Color(0, 0, 0, 0.0),
      image: '',
      imageW: 1,
      animation: false,
      duration: 30,
      time: 0,
    },
    // source编写glsl,可以使用uniforms参数,值来自getValue方法的result
    source: `
      czm_material czm_getMaterial(czm_materialInput materialInput)
      {
          czm_material material = czm_getDefaultMaterial(materialInput);
          vec2 st = materialInput.st;
          float s = st.s/ (abs(fwidth(st.s)) * imageW * czm_pixelRatio);
          if(animation==true){
            s = s-time;//增加运动效果
          }
          float t = st.t;
          vec4 colorImage = texture(image, vec2(fract(s), t));
          material.diffuse = colorImage.rgb;
          material.emission = max(backgroundColor.rgb*material.alpha*1.,backgroundColor.rgb);
          return material;
      }
    `,
  },
  translucent: function translucent () {
    return true
  },
})
export default (ImageTrailMaterial as any)