cesium-二三维联动优化(ol-cesium)

cesium-二三维联动优化(ol-cesium)

之前已经实现了ol和cesium联动的效果了,但还是有点问题:cesium和ol平面视角联动还算正常的,但是当cesium为三维视角时联动的效果就出现问题。

这里使用ol-cesium来实现完善的联动效果

ol-cesium

介绍

在 2D 和 3D 之间平滑切换并同步:

  • 地图上下文(边界框和缩放级别);
  • 栅格数据源;
  • 2D 和 3D 的矢量数据源;
  • 地图选择(选定项目);
  • 地图和地球视图之间的动画过渡。

ol-cesium官网地址

安装

我这里使用的是vue-cli框架

使用npm安装ol-cesium

npm i ol-cesium

使用例子如下:

import OLCesium from 'ol-cesium';
const ol3d = new OLCesium({map: ol2dMap}); // ol2dMap is the ol.Map instance
ol3d.setEnabled(true);

具体的参考demo可以去官网看看

实现效果

ol-cesium二三维联动

我的这个项目并不需要全部的ol-cesium功能,我只需要其中一部分功能:cesium和ol视角联动的效果

最终效果实现的二三维同步效果如下:

这里我对代码进行来修改,提取了部分功能出来

实现代码

项目结构

image-20220117112614825

lib目录中为从ol-cesium中提取出来的代码

核心代码是Camera.js,其它代码为相关依赖,主要就是修改一下相应代码的依赖

主要代码

testOLCs()

使用camera方法

  • new olcsCamera(this._viewer.scene, this.map);这里传入cesium的viewer和ol的map,让camera来管理两个地图的视角
  • checkCameraChange();开启viewer和map变化的监听
render_()

用于渲染铯场景

requestAnimationFrame()

请求动画帧回调方法

核心方法
    testOlCs() {
      this.camera_ = new olcsCamera(this._viewer.scene, this.map);
      this.camera_.checkCameraChange();
    },
    /**
     * 渲染铯场景
     */
    render_() {
      // 如果对 `requestAnimationFrame`(请求动画帧) 的调用处于挂起状态,请取消它
      if (this.renderId_ !== undefined) {
        cancelAnimationFrame(this.renderId_);
        this.renderId_ = undefined;
      }
      this.renderId_ = requestAnimationFrame(this.onAnimationFrame_.bind(this));
    },


    /**
     * Callback for `requestAnimationFrame`. 请求动画帧回调方法
     * @param {number} frameTime The frame time, from `performance.now()`.帧时间
     * @private
     */
    onAnimationFrame_(frameTime) {
      this.renderId_ = undefined;

      // 检查帧是否在目标帧速率内渲染
      const interval = 1000.0 / this.targetFrameRate_;
      const delta = frameTime - this.lastFrameTime_;
      if (delta < interval) {
        // 太早了,还没渲染
        this.render_();
        return;
      }

      // 渲染一帧的时间,节省时间
      this.lastFrameTime_ = frameTime;

      const julianDate = this.time_();
      this.scene_.initializeFrame();

      this.scene_.render(julianDate);
      this.camera_.checkCameraChange();

      // 在这个完成后请求下一个渲染调用,以确保浏览器不会得到备份
      this.render_();
    }

完整代码

<template>
  <div class="home">
    <cesiumComponent ref="refCesium"/>
    <div id="eye"></div>
  </div>
</template>

<script>
import cesiumComponent from '../cesium/cesium.vue'
import olcsCamera from './lib/Camera.js';

export default {
  name: "olCesium01",
  data() {
    return {
      _viewer: undefined,
      scene_: undefined,
      view_: undefined,
      camera_: null,
      targetFrameRate_: Number.POSITIVE_INFINITY,
      lastFrameTime_: 0,
      time_: function () {
        return Cesium.JulianDate.now()
      },
      layer: {
        tiandituVecLayer: '',
        tiandituCvaLayer: '',
        tiandituImgLayer: '',
        tiandituCiaLayer: '',
      },
      map: '',
    };
  },
  components: {
    cesiumComponent
  },
  mounted() {
    this.init();
    this.addTiles();
  },
  methods: {

    init() {
      let that=this;
      this.$refs.refCesium.initMap();
      let viewer = this.$refs.refCesium._viewer;
      this._viewer = viewer;
       that.scene_ = viewer.scene;
      //渲染铯场景
       that.render_();
      this.addOlMap();
      this.testOlCs()
    },
    addOlMap() {
      var that = this;
      //普通地图
      this.layer.tiandituVecLayer = new ol.layer.Tile({
        title: 'generalMap',
        source: new ol.source.XYZ({
          url: 'http://t3.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=token',
          crossOrigin: 'anonymous'
        }),
        // zIndex: 1,
        visible: true
      });
      //普通地图标记
      that.layer.tiandituCvaLayer = new ol.layer.Tile({
        title: 'generalMapZj',
        source: new ol.source.XYZ({
          url: 'http://t3.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=token',
          crossOrigin: 'anonymous'
        }),
        visible: true
      });
      //影像地图
      that.layer.tiandituImgLayer = new ol.layer.Tile({
        title: 'generalMapImg',
        source: new ol.source.XYZ({
          url: 'http://t3.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=token',
          crossOrigin: 'anonymous'
        }),
        visible: true
      });
      //影像地图标注
      that.layer.tiandituCiaLayer = new ol.layer.Tile({
        title: 'generalMapImgZj',
        source: new ol.source.XYZ({
          url: 'http://t3.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=token',
          crossOrigin: 'anonymous'
        }),
        visible: true
      });
      this.map = new ol.Map({
        target: 'eye',
        layers: [
          that.layer.tiandituImgLayer,
          that.layer.tiandituCiaLayer,
          that.layer.tiandituVecLayer,
          that.layer.tiandituCvaLayer,
        ],
        view: new ol.View({
          center: [13410926.774433982, 3715530.4937355495],
          zoom: 12
        }),
        controls: ol.control.defaults({
          attributionOptions: {
            collapsible: false
          }
        })
      });
      this.view_ = this.map.getView();
    },
    addTiles() {
      // cesium加载代码
      let tileSet = this._viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
        url: '../res/data/3dtiles/tianjie/tileset.json',
        modelMatrix: Cesium.Matrix4.fromArray(
            [0.9972458032561666, 0.04372029028528979, 0.05991113506964879, 0,
              -0.03623787897545647, 0.9920229449104262, -0.12073646051879428, 0,
              -0.06471185374661931, 0.11823287609043515, 0.9908750491338749, 0,
              -663.0794944260269, 1211.490494620055, 2974.1003134818748, 1]),
      }));
      this._viewer.flyTo(tileSet);
    },

    testOlCs() {
      this.camera_ = new olcsCamera(this._viewer.scene, this.map);
      this.camera_.checkCameraChange();
    },
    /**
     * Render the Cesium scene
     */
    render_() {
      // if a call to `requestAnimationFrame` is pending, cancel it
      if (this.renderId_ !== undefined) {
        cancelAnimationFrame(this.renderId_);
        this.renderId_ = undefined;
      }

      this.renderId_ = requestAnimationFrame(this.onAnimationFrame_.bind(this));
    },


    /**
     * Callback for `requestAnimationFrame`.
     * @param {number} frameTime The frame time, from `performance.now()`.
     * @private
     */
    onAnimationFrame_(frameTime) {
      this.renderId_ = undefined;

      // check if a frame was rendered within the target frame rate
      const interval = 1000.0 / this.targetFrameRate_;
      const delta = frameTime - this.lastFrameTime_;
      if (delta < interval) {
        // too soon, don't render yet
        this.render_();
        return;
      }

      // time to render a frame, save the time
      this.lastFrameTime_ = frameTime;

      const julianDate = this.time_();
      this.scene_.initializeFrame();

      this.scene_.render(julianDate);
      this.camera_.checkCameraChange();

      // request the next render call after this one completes to ensure the browser doesn't get backed up
      this.render_();
    }
  },
  created() {

  },
}
</script>

<style scoped>
.home {
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
}

#eye {
  position: absolute;
  width: 20%;
  height: 20%;
  bottom: 0;
  right: 0;
  z-index: 999;
  background: red;
  border: solid blue 1px;
}

#cesiumContainer {
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
}
</style>

image-20220117135301545

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

孙霸天

你的打赏是我不断创作的动力!

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

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

打赏作者

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

抵扣说明:

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

余额充值