VUE3+Cesium+Three项目源码

23 篇文章 20 订阅
20 篇文章 1 订阅

继上一篇Vue+Cesium+Three项目构建的详解后,为了方便使用,进一步对该项目进行模块化封装。 

VUE3+Cesium+Three项目构建_HM-hhxx!的博客-CSDN博客VUE3+Cesium+Three项目创建及原理详解。https://blog.csdn.net/damadashen/article/details/126550168

目录

1.初始化Cesium:initCesium.js

2.初始化Three:initThree.js

3.HomeView.vue


该版本项目中,将cesium初始化与Three初始化剥离开,在日后使用中更为便捷,并在vue

初始化时加入router及vuex状态管理,便于后续大型项目开发使用,项目结构如下:

1.初始化Cesium:initCesium.js

import * as Cesium from "cesium";
import "../Widgets/widgets.css";
// 设置cesium的token
Cesium.Ion.defaultAccessToken =
  "your_token";
// cesium默认资源路径
window.CESIUM_BASE_URL = "/Cesium/";
// 设置默认的视角为中国
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(
  // 西边经度
  89.5,
  // 南边维度
  20.4,
  // 东边经度
  110.4,
  // 北边维度
  61.2
);
// 设置全局cesium对象
let cesium = {
  viewer: null,
};
function initCesium(minWGS84, maxWGS84, cesiumContainerid) {
  var cesiumContainer = cesiumContainerid;
  // 设置cesium容器
  var cesiumContainer = document.getElementById("cesiumContainer");
  // 初始化cesium渲染器
  cesium.viewer = new Cesium.Viewer(cesiumContainer, {
    useDefaultRenderLoop: false,
    selectionIndicator: false,
    homeButton: false,
    infoBox: false,
    sceneModePicker: false,
    navigationHelpButton: false,
    animation: false,
    timeline: false,
    fullscreenButton: false,
    baseLayerPicker: false,
    clock: false,
    geocoder: false,
    //     天地图矢量路径图
    imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
      url: "http://t0.tianditu.com/vec_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=vec&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=30d07720fa76f07732d83c748bb84211",
      layer: "tdtBasicLayer",
      style: "default",
      format: "image/jpeg",
      tileMatrixSetID: "GoogleMapsCompatible",
    }),
    //cesium中webgl选项
    contextOptions: {
      webgl: {
        //透明度
        alpha: false,
        // 抗锯齿
        antialias: true,
        //深度检测
        depth: true,
      },
    },
  });
  //设置隐藏logo
  cesium.viewer.cesiumWidget.creditContainer.style.display = "none";
  // 设置抗锯齿
  cesium.viewer.scene.postProcessStages.fxaa.enabled = true;
  // 地图叠加
  var imageryLayers = cesium.viewer.imageryLayers;
  //console.log(imageryLayers);
  var layer = imageryLayers.addImageryProvider(
    new Cesium.WebMapTileServiceImageryProvider({
      url: "http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=30d07720fa76f07732d83c748bb84211",
      layer: "tdtBasicLayer",
      style: "default",
      format: "image/jpeg",
      tileMatrixSetID: "GoogleMapsCompatible",
    })
  );
  layer.alpha = 0.5;
  // 设置前往地点
  let center = Cesium.Cartesian3.fromDegrees(
    (minWGS84[0] + maxWGS84[0]) / 2,
    (minWGS84[1] + maxWGS84[1]) / 2,
    20000
  );

  // 设置相机飞往该区域
  cesium.viewer.camera.flyTo({
    destination: center,
    duration: 2,
    orientation: {
      heading: Cesium.Math.toRadians(0),
      pitch: Cesium.Math.toRadians(-90),
      roll: 0,
    },
  });
}
function renderCesium() {
  cesium.viewer.render();
}
function exportCesium() {
    let cesiumdone = cesium;
    return cesiumdone;
}
export  { exportCesium,initCesium, renderCesium };

2.初始化Three:initThree.js

import * as THREE from "three";
import * as Cesium from "cesium";

// three全局对象
let three = {
  renderer: null,
  camera: null,
  scene: null,
};
// three.js物体
let objects3D = [];
//封装three物体(使three物体具有经纬度)
function Object3D(mesh, minWGS84, maxWGS84) {
  this.threeMesh = mesh; //物体
  this.minWGS84 = minWGS84; //范围
  this.maxWGS84 = maxWGS84; //范围
}
function initThree() {
  //初始化Three
  // 设置相机配置
  let fov = 45; //视角
  let aspect = window.innerWidth / window.innerHeight; //宽高比例
  let near = 0.1;
  let far = 10 * 1000 * 1000; //视域范围

  // 初始化场景
  three.scene = new THREE.Scene();
  three.camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  three.renderer = new THREE.WebGLRenderer({
    antialias: true, //抗锯齿
    alpha: true,
  });
  // 设置渲染器大小
  three.renderer.setSize(window.innerWidth, window.innerHeight);

  // 添加环境光
  let ambientLight = new THREE.AmbientLight(0xffffff, 1);
  three.scene.add(ambientLight);
  // 添加three.jscanvas元素到cesium容器
  cesiumContainer.appendChild(three.renderer.domElement);
}
// 创建three.js物体
function createMesh(minWGS84, maxWGS84) {
  let geometry = new THREE.BoxBufferGeometry(1, 1, 1);
  let material = new THREE.MeshBasicMaterial({
    color: 0x00ff00,
  });
  let mesh = new THREE.Mesh(geometry, material);

  // 放大物体
  mesh.scale.set(100, 100, 100); // 放大
  mesh.position.set(0, 0, 50); // 平移

  let meshGroup = new THREE.Group();
  meshGroup.add(mesh);
  // 添加至场景
  three.scene.add(meshGroup);
  // 创建3d物体
  let OB3d = new Object3D(
    meshGroup,
    [minWGS84[0], minWGS84[1]],
    [maxWGS84[0], maxWGS84[1]]
  );

  // 添加到3d物体数组
  objects3D.push(OB3d);
}

function renderThree(cesium) {
  // 设置相机跟cesium保持一致
  
  three.camera.fov = Cesium.Math.toDegrees(cesium.viewer.camera.frustum.fovy);
  //console.log(cesium);
  // 声明一个将cesium框架的cartesian3转换为three.js的vector3(笛卡尔坐标转换为三维向量)
  let cartToVec = function (cart) {
    return new THREE.Vector3(cart.x, cart.y, cart.z);
  };
  // 将3D的物体通过经纬度转换成对应的位置
  objects3D.forEach((item, index) => {
    // 通过经纬度获取中心点的位置
    let center = Cesium.Cartesian3.fromDegrees(
      (item.minWGS84[0] + item.maxWGS84[0]) / 2,
      (item.minWGS84[1] + item.maxWGS84[1]) / 2
    );
    item.threeMesh.position.copy(cartToVec(center));

    //计算朝向(切面方向-切线向量)
    //中心高度点
    let centerHeight = Cesium.Cartesian3.fromDegrees(
      (item.minWGS84[0] + item.maxWGS84[0]) / 2,
      (item.minWGS84[1] + item.maxWGS84[1]) / 2,
      1
    );
    //左下
    let bottomLeft = cartToVec(
      Cesium.Cartesian3.fromDegrees(item.minWGS84[0], item.minWGS84[1])
    );
    //左上
    let topLeft = cartToVec(
      Cesium.Cartesian3.fromDegrees(item.minWGS84[0], item.maxWGS84[1])
    );
    //朝向()
    let latDir = new THREE.Vector3()
      .subVectors(bottomLeft, topLeft)
      .normalize();

    // console.log(item);
    //设置查看方向
    item.threeMesh.lookAt(centerHeight.x, centerHeight.y, centerHeight.z);
    //设置朝向
    item.threeMesh.up.copy(latDir);
  });

  //设置摄像机矩阵
  // 设置相机跟cesium保持一致
  three.camera.matrixAutoUpdate = false; //自动更新
  //复制cesium相机矩阵
  let cvm = cesium.viewer.camera.viewMatrix;
  let civm = cesium.viewer.camera.inverseViewMatrix;
  // three相机默认朝向0,0,0
  three.camera.lookAt(0, 0, 0);

  // 设置threejs相机矩阵
  three.camera.matrixWorld.set(
    civm[0],
    civm[4],
    civm[8],
    civm[12],
    civm[1],
    civm[5],
    civm[9],
    civm[13],
    civm[2],
    civm[6],
    civm[10],
    civm[14],
    civm[3],
    civm[7],
    civm[11],
    civm[15]
  );

  three.camera.matrixWorldInverse.set(
    cvm[0],
    cvm[4],
    cvm[8],
    cvm[12],
    cvm[1],
    cvm[5],
    cvm[9],
    cvm[13],
    cvm[2],
    cvm[6],
    cvm[10],
    cvm[14],
    cvm[3],
    cvm[7],
    cvm[11],
    cvm[15]
  );
  //设置宽高比例
  let width = cesiumContainer.clientWidth;
  let height = cesiumContainer.clientHeight;
  three.camera.aspect = width / height;
  //更新相机矩阵
  three.camera.updateProjectionMatrix();
  //设置尺寸大小
  three.renderer.setSize(width, height);
  three.renderer.clear();
  three.renderer.render(three.scene, three.camera);
}
export {initThree,createMesh,renderThree};

3.HomeView.vue

<template>
  <div id="cesiumContainer" ref="cesiumContainer"></div>
</template>

<script setup>
import { onMounted } from "vue";
import * as Cesium from "cesium";
//import "cesium/Build/Cesium/Widgets/widgets.css";
import "../Widgets/widgets.css";
import * as THREE from "three";
import { exportCesium, initCesium, renderCesium } from "../cesium/cesium_init.js";
import { initThree, createMesh, renderThree } from "../three/three_init.js"

onMounted(() => {
  main();
});

function main() {
  // 设置北京显示模型的渲染范围(用于设置范围)
  var minWGS84 = [115.39, 38.9];
  var maxWGS84 = [117.39, 40.9];
  //初始化Cesium
  initCesium(minWGS84, maxWGS84, cesiumContainer);
  var cesium = exportCesium();
  //初始化Three
  initThree(minWGS84, maxWGS84);
  //创建物体
  createMesh(minWGS84, maxWGS84);
    //循环函数,不断请求动画帧渲染
  function loop() {
    requestAnimationFrame(loop);
    // cesium渲染
    renderCesium();
    // three.js渲染
    renderThree(cesium);
  }
  loop();
}
</script>

<style>
* {
  margin: 0;
  padding: 0;
}

#cesiumContainer {
  width: 100vw;
  height: 100vh;
  position: relative;
}

#cesiumContainer>canvas {
  position: absolute;
  top: 0;
  left: 0;
  /* 设置鼠标事件穿透 */
  pointer-events: none;
}
</style>

源码地址:

GitHub - Harsh-M1/vue_cesium_three_templateContribute to Harsh-M1/vue_cesium_three_template development by creating an account on GitHub.https://github.com/Harsh-M1/vue_cesium_three_template


vue_cesium_three_template: 使用VUE3+cesium+three.js构建的基础想木模板!https://gitee.com/lei-aimiao/vue_cesium_three_template

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HM-hhxx!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值