Cesium 实体、3d瓦片、鼠标事件、三维模型、粒子效果、点聚合、数据加载

本文深入探讨Cesium的高级特性,包括使用实体(primitive)创建高性能图形,3D瓦片的加载与应用,鼠标事件交互,加载和展示三维模型,实现炫酷的粒子效果,以及对大量点数据的聚合处理。通过这些内容,帮助读者掌握Cesium在复杂场景中的应用技巧。
摘要由CSDN通过智能技术生成

1、实体 primitive

 entity
1.2  调用方便,封装完美
1.3  是基于primitive的封装

primitive
1.1 更接近底层,性能消耗较小,要素很多时使用primitive
1.2 可以绘制高级图形
1.3 由Geometry(几何形状)、(Appearance)外观组成…

<template>
  <div id="cesiumContainer">
  </div>
</template>
<script setup>
import * as Cesium from 'cesium'
import { onMounted } from 'vue'

let viewer
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmMDY1ZmUxNi1mMGNhLTQ1NDEtYTU2YS0wNTUwZDJhOWNkNmEiLCJpZCI6MTE1MTg3LCJpYXQiOjE3MDA0NDUxNDB9.wdc1z2bc8UV2q_FpcuB5QKtRx8OYLKq4KI3gDs6-gA8'
onMounted(() => {
  // viewer是操控地图api的开始
  viewer = new Cesium.Viewer('cesiumContainer', {
    selectionIndicator: false,//隐藏选中框
    infoBox: false//隐藏右上角信息框
  })

  const rectangleInstance = new Cesium.GeometryInstance({
    geometry: new Cesium.RectangleGeometry({
      rectangle: Cesium.Rectangle.fromDegrees(-140.0, 30.0, -100.0, 40.0),
      vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
    }),
    attributes: {
      color: new Cesium.ColorGeometryInstanceAttribute(0.0, 1.0, 1.0, 0.5)
    }
  });
  const polygonInstance = new Cesium.GeometryInstance({
    geometry: new Cesium.PolygonGeometry({
      polygonHierarchy: new Cesium.PolygonHierarchy(
        Cesium.Cartesian3.fromDegreesArray([
          -100.0, 43.0,
          -100.0, 27.0,
          -90, 35
        ])
      )
    }),
    attributes: {
      color: new Cesium.ColorGeometryInstanceAttribute(0.0, 1.0, 1.0, 0.5)
    }
  });
  viewer.scene.primitives.add(new Cesium.Primitive({
    geometryInstances: [rectangleInstance, polygonInstance],
    appearance: new Cesium.PerInstanceColorAppearance()
  }));
})
</script>
<style scoped>
#cesiumContainer {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
.btn {
  position: absolute;
  left: 50px;
  top: 50px;
  z-index: 999;
}
</style>

2、3d瓦片

<template>
  <div id="cesiumContainer">
  </div>
</template>
<script setup>
import * as Cesium from 'cesium'
import { onMounted } from 'vue'

let viewer
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmMDY1ZmUxNi1mMGNhLTQ1NDEtYTU2YS0wNTUwZDJhOWNkNmEiLCJpZCI6MTE1MTg3LCJpYXQiOjE3MDA0NDUxNDB9.wdc1z2bc8UV2q_FpcuB5QKtRx8OYLKq4KI3gDs6-gA8'
onMounted(() => {
  // viewer是操控地图api的开始
  viewer = new Cesium.Viewer('cesiumContainer', {
    // selectionIndicator: false,//隐藏选中框
    // infoBox: false//隐藏右上角信息框
  })

  // 3d瓦片添加在primitives里面
  // const tileset = viewer.scene.primitives.add(
  //   new Cesium.Cesium3DTileset({
  //     url: Cesium.IonResource.fromAssetId(69380)
  //   })
  // )
  // viewer.zoomTo(tileset)

  const tileset = viewer.scene.primitives.add(
    new Cesium.Cesium3DTileset({
      url: '/src/assets/b3dm/tileset.json'
    })
  )
  viewer.zoomTo(tileset)

})
</script>
<style scoped>
#cesiumContainer {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
.btn {
  position: absolute;
  left: 50px;
  top: 50px;
  z-index: 999;
}
</style>

3、鼠标事件

<template>
  <div id="cesiumContainer">
  </div>
  <!-- <button @click="toDel" class="btn">销毁事件</button> -->
</template>
<script setup>
import * as Cesium from 'cesium'
import { onMounted } from 'vue'
const toDel = () => {
  handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
}

let viewer, handler
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmMDY1ZmUxNi1mMGNhLTQ1NDEtYTU2YS0wNTUwZDJhOWNkNmEiLCJpZCI6MTE1MTg3LCJpYXQiOjE3MDA0NDUxNDB9.wdc1z2bc8UV2q_FpcuB5QKtRx8OYLKq4KI3gDs6-gA8'
onMounted(() => {
  // viewer是操控地图api的开始
  viewer = new Cesium.Viewer('cesiumContainer', {
    selectionIndicator: false,//隐藏选中框
    infoBox: false//隐藏右上角信息框
  })
  const tileset = viewer.scene.primitives.add(
    new Cesium.Cesium3DTileset({
      url: Cesium.IonResource.fromAssetId(69380)
    })
  )
  viewer.zoomTo(tileset)
  const line = viewer.entities.add({
    polyline: {
      positions: [],
      width: 5,
      material: Cesium.Color.YELLOW,
      clampToGround: true //贴地
    }
  })
  let arr = []
  handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
  handler.setInputAction((event) => {
    let position = viewer.scene.pickPosition(event.position)  //拾取坐标
    if (position) {
      viewer.entities.add({
        position,
        point: {
          color: Cesium.Color.RED,
          pixelSize: 20
        }
      })
      arr.push(position)
      line.polyline.positions = arr
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
  handler.setInputAction((event) => {
    // 结束绘制
    alert('结束绘制')
    viewer.entities.removeAll() //不合理  用影响其他实体  用空数组删节点
    viewer.entities.add(line)
    handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
    handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK)
  }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
})
</script>
<style scoped>
#cesiumContainer {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
.btn {
  position: absolute;
  left: 50px;
  top: 50px;
  z-index: 999;
}
</style>

<template>
  <div id="cesiumContainer">
  </div>
</template>
<script setup>
import * as Cesium from 'cesium'
import { onMounted } from 'vue'

let viewer, handler
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmMDY1ZmUxNi1mMGNhLTQ1NDEtYTU2YS0wNTUwZDJhOWNkNmEiLCJpZCI6MTE1MTg3LCJpYXQiOjE3MDA0NDUxNDB9.wdc1z2bc8UV2q_FpcuB5QKtRx8OYLKq4KI3gDs6-gA8'
onMounted(() => {
  // viewer是操控地图api的开始
  viewer = new Cesium.Viewer('cesiumContainer', {
    selectionIndicator: false,//隐藏选中框
    infoBox: false//隐藏右上角信息框
  })
  const tileset = viewer.scene.primitives.add(
    new Cesium.Cesium3DTileset({
      url: Cesium.IonResource.fromAssetId(75343)
    })
  )
  viewer.zoomTo(tileset)
  let lastPick
  handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
  handler.setInputAction((event) => {
    let pick = viewer.scene.pick(event.endPosition) //移动事件中没有event.position
    if (pick) {
      if (lastPick) {
        lastPick.color = Cesium.Color.WHITE
      }
      pick.color = Cesium.Color.ORANGERED
      lastPick = pick
    }
  }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)

})
</script>
<style scoped>
#cesiumContainer {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
.btn {
  position: absolute;
  left: 50px;
  top: 50px;
  z-index: 999;
}
</style>

4、加载三维模型

<template>
  <div id="cesiumContainer">
  </div>
</template>
<script setup>
import * as Cesium from 'cesium'
import { onMounted } from 'vue'
let viewer
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmMDY1ZmUxNi1mMGNhLTQ1NDEtYTU2YS0wNTUwZDJhOWNkNmEiLCJpZCI6MTE1MTg3LCJpYXQiOjE3MDA0NDUxNDB9.wdc1z2bc8UV2q_FpcuB5QKtRx8OYLKq4KI3gDs6-gA8'
onMounted(() => {
  // viewer是操控地图api的开始
  viewer = new Cesium.Viewer('cesiumContainer', {
    selectionIndicator: false,//隐藏选中框
    infoBox: false,//隐藏右上角信息框
    shouldAnimate: true,
    shadows: true//显示阴影
  })

  const position = Cesium.Cartesian3.fromDegrees(114, 30, 300)
  const orientation = Cesium.Transforms.headingPitchRollQuaternion(
    position,
    Cesium.HeadingPitchRoll.fromDegrees(0, 0, 0)
  )

  const model = viewer.entities.add({
    position,
    orientation,
    model: {
      uri: '/src/assets/Cesium_Air.glb',
      scale: 0.5,
      minimumPixelSize: 10 //模型最小像素
    }
  })
  viewer.zoomTo(model)



})
</script>
<style scoped>
#cesiumContainer {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
.btn {
  position: absolute;
  left: 50px;
  top: 50px;
  z-index: 999;
}
</style>

5、粒子效果

<template>
  <div id="cesiumContainer">
  </div>
</template>
<script setup>
import * as Cesium from 'cesium'
import { onMounted } from 'vue'
let viewer
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmMDY1ZmUxNi1mMGNhLTQ1NDEtYTU2YS0wNTUwZDJhOWNkNmEiLCJpZCI6MTE1MTg3LCJpYXQiOjE3MDA0NDUxNDB9.wdc1z2bc8UV2q_FpcuB5QKtRx8OYLKq4KI3gDs6-gA8'
onMounted(() => {
  // viewer是操控地图api的开始
  viewer = new Cesium.Viewer('cesiumContainer', {
    selectionIndicator: false,//隐藏选中框
    infoBox: false,//隐藏右上角信息框
    shouldAnimate: true,
    shadows: true//显示阴影
  })

  const position = Cesium.Cartesian3.fromDegrees(114, 30, 300)
  const orientation = Cesium.Transforms.headingPitchRollQuaternion(
    position,
    Cesium.HeadingPitchRoll.fromDegrees(0, 0, 0)
  )

  const model = viewer.entities.add({
    position,
    orientation,
    model: {
      uri: '/src/assets/Cesium_Air.glb',
      scale: 0.5,
      minimumPixelSize: 10 //模型最小像素
    }
  })
  viewer.zoomTo(model)

  viewer.scene.primitives.add(new Cesium.ParticleSystem({
    image: '/src/assets/fire.png',
    imageSize: new Cesium.Cartesian2(20, 20), //尺寸
    startScale: 1.0, //初始大小
    endScale: 4.0, //最后大小 
    particleLife: 3.0, 设置每一个粒子存在的时间
    speed: 5.0, //发射粒子的速度
    emitter: new Cesium.CircleEmitter(2),  //设置发射器(圆形发射器) 
    // emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(10, 10, 10)),
    emissionRate: 5,//例子发射数量
    modelMatrix: model.computeModelMatrix(
      viewer.clock.startTime,  //时间控件中的起始时间
      new Cesium.Matrix4()  //4*4矩阵数据
    ),  //设置位置
    lifetime: 16, //生命期属性为所需的持续时间
    // loop: false,  //只循环一次
  }));
})
</script>
<style scoped>
#cesiumContainer {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
.btn {
  position: absolute;
  left: 50px;
  top: 50px;
  z-index: 999;
}
</style>

6、点聚合

<template>
  <div id="cesiumContainer">
  </div>
</template>
<script setup>
import * as Cesium from 'cesium'
import { onMounted } from 'vue'
let viewer
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmMDY1ZmUxNi1mMGNhLTQ1NDEtYTU2YS0wNTUwZDJhOWNkNmEiLCJpZCI6MTE1MTg3LCJpYXQiOjE3MDA0NDUxNDB9.wdc1z2bc8UV2q_FpcuB5QKtRx8OYLKq4KI3gDs6-gA8'
onMounted(() => {
  // viewer是操控地图api的开始
  viewer = new Cesium.Viewer('cesiumContainer', {
    selectionIndicator: false,//隐藏选中框
    infoBox: false,//隐藏右上角信息框
    shouldAnimate: true,
    shadows: true//显示阴影
  })

  const position = Cesium.Cartesian3.fromDegrees(114, 30, 300)
  const orientation = Cesium.Transforms.headingPitchRollQuaternion(
    position,
    Cesium.HeadingPitchRoll.fromDegrees(0, 0, 0)
  )

  const model = viewer.entities.add({
    position,
    orientation,
    model: {
      uri: '/src/assets/Cesium_Air.glb',
      scale: 0.5,
      minimumPixelSize: 10 //模型最小像素
    }
  })
  viewer.zoomTo(model)

  viewer.scene.primitives.add(new Cesium.ParticleSystem({
    image: '/src/assets/fire.png',
    imageSize: new Cesium.Cartesian2(20, 20), //尺寸
    startScale: 1.0, //初始大小
    endScale: 4.0, //最后大小 
    particleLife: 3.0, 设置每一个粒子存在的时间
    speed: 5.0, //发射粒子的速度
    emitter: new Cesium.CircleEmitter(2),  //设置发射器(圆形发射器) 
    // emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(10, 10, 10)),
    emissionRate: 5,//例子发射数量
    modelMatrix: model.computeModelMatrix(
      viewer.clock.startTime,  //时间控件中的起始时间
      new Cesium.Matrix4()  //4*4矩阵数据
    ),  //设置位置
    lifetime: 16, //生命期属性为所需的持续时间
    // loop: false,  //只循环一次
  }));
})
</script>
<style scoped>
#cesiumContainer {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
.btn {
  position: absolute;
  left: 50px;
  top: 50px;
  z-index: 999;
}
</style>

7、加载 load3dtiles

<template>
  <div id="cesiumContainer">
  </div>
  <el-card class="box-card">
    <template #header>
      <div class="card-header">
        <span>小区设施</span>
      </div>
    </template>
    <div v-for="(item,index) in data.arr" :key="index" class="text" @click="changeView(item)">
      {{item.name}}
    </div>
  </el-card>
</template>
<script setup>
import * as Cesium from 'cesium'
import { onMounted, reactive } from 'vue'
import { load3dtiles, update3dtiles } from './tool/load'
import facilities from './assets/facilities.json'
const data = reactive({
  arr: []
})

let viewer
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmMDY1ZmUxNi1mMGNhLTQ1NDEtYTU2YS0wNTUwZDJhOWNkNmEiLCJpZCI6MTE1MTg3LCJpYXQiOjE3MDA0NDUxNDB9.wdc1z2bc8UV2q_FpcuB5QKtRx8OYLKq4KI3gDs6-gA8'
onMounted(() => {
  // viewer是操控地图api的开始
  viewer = new Cesium.Viewer('cesiumContainer', {
    selectionIndicator: false,//隐藏选中框
    infoBox: false,//隐藏右上角信息框
  })
  load3dtiles(viewer, '/src/assets/b3dm/tileset.json', (tileset) => {
    update3dtiles(tileset)
    viewer.zoomTo(tileset)
    initData()
  })
})
const changeView = (item) => {
  const position = item.cameraPosition.split(',').map(a => Number(a))
  const ortArr = item.cameraOrt.split(',').map(a => Number(a))
  viewer.camera.flyTo({
    destination: new Cesium.Cartesian3(...position),
    orientation: {
      heading: ortArr[0],
      pitch: ortArr[1],
      roll: ortArr[2],
    }
  })
}
const initData = () => {
  data.arr = facilities
  console.log(data.arr)
}

</script>
<style scoped>
#cesiumContainer {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
.box-card {
  position: absolute;
  width: 300px;
  top: 40px;
  left: 40px;
}

.text {
  margin: 10px;
  cursor: pointer;
}

.text:hover {
  color: blueviolet;
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

@仗剑走天涯

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

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

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

打赏作者

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

抵扣说明:

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

余额充值