Cesium billboard 实现动态效果

Cesium billboard 实现动态效果

自转、跳动、闪烁、旋转等动态效果

  /**
   * 利用BillboardGraphics的scale、rotation、width、position属性和和CallbackProperty实现动态改变entity billboard
   */
  loadDynamicBillboardByEntity (viewer: Cesium.Viewer, options: TBillboardOptions) {
    const { image, position } = options
    let imageWidth = 0
    const imageWidthMin = 0
    const imageWidthMax = 50

    viewer?.entities.add({
      position: position.toCartesian3(),
      billboard: {
        image: image,
        // image: options.image,
        width: new Cesium.CallbackProperty(() => {
          return imageWidth
        }, false),
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
      },
    })
    viewer.scene.preRender.addEventListener(function (scene, time) {
      // 计算当前时间和开始时间的差值(秒数)
      // const elapsedSeconds = Cesium.JulianDate.secondsDifference(time, startTime)
      // const elapsedSeconds = Cesium.JulianDate.now().secondsOfDay
      const elapsedSeconds = time.secondsOfDay

      imageWidth = Math.abs(Math.sin(elapsedSeconds)) * (imageWidthMax - imageWidthMin) + imageWidthMin
    })
    // 设置定时器
    // // 用于控制的变量
    // let j = 1

    // setInterval(() => {
    //   // 方法1:直接给entity的参数赋新值
    //   // 方法2: 修改参数对应的回调函数中的变量
    //   // 使变量间隔2秒重复
    //   if (width >= 30) {
    //     j = -1
    //   }
    //   if (width <= 0) {
    //     j = 1
    //   }
    //   width = width + j
    // }, 100)
  }
  /**
 * 利用preRender动态改变 primitive billboard 的 scale、rotation、width属性
 */
  dynamicBillboardByPrimitive (viewer: Cesium.Viewer) {
    // 获取场景和时间线
    const scene = viewer.scene
    const clock = viewer.clock

    // 创建 BillboardCollection
    const billboards = scene.primitives.add(new Cesium.BillboardCollection())
    const imageWidth = 30
    const imageHeight = 40
    // 添加一个 billboard
    const billboard = billboards.add({
      position: Cesium.Cartesian3.fromDegrees(70, 70, 10000),
      image: '/public/bg_billboard.png',
      scale: 0.5,
      color: new Cesium.Color(1.0, 1.0, 1.0, 1.0), // 白色不透明
      rotation: 0.0,
      imageSubRegion: new Cesium.BoundingRectangle(0, 0, imageWidth, imageHeight), // 初始显示区域
    })

    // 设置开始时间和结束时间
    // const startTime = Cesium.JulianDate.fromDate(new Date(2024, 8, 1, 12, 0, 0))  // 开始时间
    // const endTime = Cesium.JulianDate.addSeconds(startTime, 60, new Cesium.JulianDate()) // 结束时间,动画持续 60 秒

    // clock.startTime = startTime.clone()
    // clock.stopTime = endTime.clone()
    // clock.currentTime = startTime.clone()
    // clock.clockRange = Cesium.ClockRange.LOOP_STOP // 循环播放
    clock.multiplier = 1 // 时间加速系数
    // 动态更新属性
    scene.preRender.addEventListener(function (scene, time) {
      // 计算当前时间和开始时间的差值(秒数)
      // const elapsedSeconds = Cesium.JulianDate.secondsDifference(time, startTime)
      // const elapsedSeconds = Cesium.JulianDate.now().secondsOfDay
      const elapsedSeconds = time.secondsOfDay
      // 动态改变位置(沿经度方向移动)
      const newLongitude = -75.59777 + 0.01 * elapsedSeconds // 每秒移动 0.01 度

      billboard.position = Cesium.Cartesian3.fromDegrees(newLongitude, 40.03883)

      // 动态改变透明度(在 0 和 1 之间变化)
      const alpha = Math.abs(Math.sin(elapsedSeconds)) // 透明度在 0-1 之间循环变化

      billboard.color = new Cesium.Color(1.0, 1.0, 1.0, alpha)  // 动态设置透明度

      // 动态改变旋转角度(每秒旋转 0.1 弧度)
      billboard.rotation = elapsedSeconds * 0.1

      // 动态缩放(在 1 和 1.5 之间变化)
      billboard.scale = 1.0 + 0.5 * Math.sin(elapsedSeconds)

      // 动态修改图片宽度(在 0 和 1 之间变化)
      billboard.width = Math.abs(Math.sin(elapsedSeconds)) * imageWidth

      // 动态改变宽度, 保持高度不变
      // const newWidth = imageWidth * (1 + 0.5 * Math.sin(elapsedSeconds)) // 宽度变化范围

      // console.log('newWidth', newWidth)
      // billboard.imageSubRegion =  new Cesium.BoundingRectangle( 0,0,newWidth, imageHeight) // 只改变宽度
    })
  }

加载GIF

import SuperGif from './libgif.js'

  /**
   * entity Billboard 加载gif
   */
  loadGifByEntity (viewer: Cesium.Viewer, options: TBillboardOptions) {
    console.log('billboard loadGif', options)
    const { image, position } = options

    if (image) {
      const gifDiv = document.createElement('div')
      const gifImg = document.createElement('img')

      gifImg.setAttribute('rel:animated_src', image)
      gifImg.setAttribute('rel:auto_play', '1') // 设置自动播放属性
      gifDiv.appendChild(gifImg)
      const superGif = new SuperGif({ gif: gifImg })

      superGif.load(function () {
        viewer.entities.add({
          position: position.toCartesian3(),
          billboard: {
            image: new Cesium.CallbackProperty(() => {
              return superGif.get_canvas().toDataURL('image/png')
            }, false),
            scale: 0.1,
          },
        })
      })
    }
  }
import SuperGif from './libgif.js'
  /**
 * primitive Billboard 加载图片数组或gif
 * @param viewer
 */
  loadGifByPrimitive (viewer: Cesium.Viewer) {
    const url = '/public/img.gif'
    const gifDiv = document.createElement('div')
    const gifImg = document.createElement('img')

    // gif库需要img标签配置下面两个属性
    gifImg.setAttribute('rel:animated_src', url)
    gifImg.setAttribute('rel:auto_play', '1') // 设置自动播放属性
    gifDiv.appendChild(gifImg)

    const superGif = new SuperGif({ gif: gifImg })

    superGif.load(() => {
      const scene = viewer.scene
      const clock = viewer.clock

      clock.multiplier = 1.5 // 时间加速系数

      // 创建 BillboardCollection
      const billboards = scene.primitives.add(new Cesium.BillboardCollection())
      // 添加一个 billboard
      const billboard = billboards.add({
        position: Cesium.Cartesian3.fromDegrees(30, 70, 1000000),
        image: url,
      })
      let imageIndex = 0
      const imgLength = superGif.get_length()

      // 循环切换图片
      // let images = ['image1.png', 'image2.png', 'image3.png'];
      scene.preRender.addEventListener(function (scene, time) {
        imageIndex = (time.secondsOfDay) % imgLength
        // imageIndex = (imageIndex + 1) % imgLength
        // billboard.image = images[imageIndex]
        superGif.move_to(imageIndex)
        billboard.image = superGif.get_canvas().toDataURL('image/png')
      })
    })
  }

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值