ol-cesium 暴露 Cesium viewer 对象以及二三维切换、viewer 添加点功能示例

news2025/1/12 4:50:26

ol-cesium 暴露 Cesium viewer 对象以及二三维切换、viewer 添加点功能示例

    • 核心代码
    • 完整代码
    • 在线示例

二三维一体化的概念一直都比较火热,虽然大多数都是狭义的概念,但是很多需求方也想要这样的功能。

Openlayers 官方出了一个二三维一体化的工具:ol-cesium。

基本能满足大多数项目的基础需求。

在使用过程中,发现工具在初始化之后,可以获取 Openlayers 地图对象、Cesium camera 对象、Cesium scene 对象等。

但是拿不到 Cesium viewer 对象,使用起来不太习惯,于是经过修改源码,拿到 viewer 对象。

本文包括核心代码、完整代码、在线示例三部分。


核心代码


let viewer,thisObject = this;

if (targetElement) {
  if (typeof targetElement === 'string') {

    targetElement = document.getElementById(targetElement);

    //使用原始cesium方式初始化
    viewer = new Cesium.Viewer(targetElement, {
      infoBox: thisObject.infoBox, //Disable InfoBox widget
      selectionIndicator: thisObject.selectionIndicator, //Disable selection indicator
      shouldAnimate: thisObject.shouldAnimate, // Enable animations
      //需要进行可视化的数据源的集合
      animation: false, //是否显示动画控件
      homeButton: false, //是否显示Home按钮
      fullscreenButton: false, //是否显示全屏按钮
      baseLayerPicker: false, //是否显示图层选择控件
      geocoder: false, //是否显示地名查找控件
      timeline: false, //是否显示时间线控件
      sceneModePicker: false, //是否显示投影方式控件
      navigationHelpButton: false, //是否显示帮助信息控件
      requestRenderMode: false, //启用请求渲染模式
      scene3DOnly: false, //每个几何实例将只能以3D渲染以节省GPU内存
    });

    //获取cesium视野对象
    let cesiumChidren = $(viewer.container).find('.cesium-viewer-cesiumWidgetContainer')
        .find('.cesium-widget').children();

    //将cesium视野对象移入ol-cesium对象中
    cesiumChidren.each(function (e, f) {
      if (e == 0) {
        $(this).css('position', 'absolute');
        $(this).css('top', '0px');
        $(this).css('left', '0px');
        $(this).css('width', '100%');
        $(this).css('height', '100%');
      }
      thisObject.container_.append(this);
    });
    targetElement = document.getElementById(targetElement);
    targetElement.appendChild(this.container_);
  }
} else {
  const seOverlayContainer =
      this.map_.getViewport().querySelector('.ol-overlaycontainer-stopevent');
  seOverlayContainer.insertBefore(this.container_, seOverlayContainer.firstChild);
  viewer = new Cesium.Viewer(this.container_);
}


完整代码

可以参考这个类,自己进行修改,当然直接复制替换也没问题。


/**
 * @module olcs.OLCesium
 */
import olGeomPoint from 'ol/geom/Point.js';
import {getTransform} from 'ol/proj.js';
import {supportsImageRenderingPixelated, imageRenderingValue} from './util.js';
import {ol4326CoordinateToCesiumCartesian} from './core.js';
import olcsAutoRenderLoop from './AutoRenderLoop.js';
import olcsCamera from './Camera.js';
import olcsRasterSynchronizer from './RasterSynchronizer.js';
import olcsVectorSynchronizer from './VectorSynchronizer.js';
import olcsOverlaySynchronizer from './OverlaySynchronizer.js';
import LSSEC from "lssec-cesium-api/src/lssec/lssec";
const Cesium = LSSEC.Cesium;
import $ from "jquery";

/**
 * @typedef {Object} OLCesiumOptions
 * @property {import('ol/Map.js').default} map The OpenLayers map we want to show on a Cesium scene.
 * @property {Element|string} [target] Target element for the Cesium scene.
 * @property {function(!import('ol/Map.js').default, !Cesium.Scene, !Cesium.DataSourceCollection): Array<import('olcs/AbstractSynchronizer.js').default>}
 *      [createSynchronizers] Callback function which will be called by the {@link olcs.OLCesium}
 *      constructor to create custom synchronizers. Receives an `ol.Map` and a `Cesium.Scene` as arguments,
 *      and needs to return an array of {@link import('olcs/AbstractSynchronizer.js').default}.
 * @property {function(): Cesium.JulianDate} [time] Control the current time used by Cesium.
 * @property {boolean} [stopOpenLayersEventsPropagation] Prevent propagation of mouse/touch events to
 *      OpenLayers when Cesium is active.
 * @property {Cesium.SceneOptions} [sceneOptions] Allows the passing of property value to the
 *      `Cesium.Scene`.
 */


class OLCesium {
  /**
   * @param {!OLCesiumOptions} options Options.
   * @constructor
   * @api
   */
  constructor(options) {

    /**
     * @type {olcs.AutoRenderLoop}
     * @private
     */
    this.autoRenderLoop_ = null;

    /**
     * @type {!ol.Map}
     * @private
     */
    this.map_ = options.map;

    /**
     * @type {!function(): Cesium.JulianDate}
     * @private
     */
    this.time_ = options.time || function() {
      return Cesium.JulianDate.now();
    };

    /**
     * No change of the view projection.
     * @private
     */
    this.to4326Transform_ = getTransform(
        this.map_.getView().getProjection(), 'EPSG:4326');

    /**
     * @type {number}
     * @private
     */
    this.resolutionScale_ = 1.0;

    /**
     * @type {number}
     * @private
     */
    this.canvasClientWidth_ = 0.0;

    /**
     * @type {number}
     * @private
     */
    this.canvasClientHeight_ = 0.0;

    /**
     * @type {boolean}
     * @private
     */
    this.resolutionScaleChanged_ = true; // force resize


    // 隐藏一些控件
    this.infoBox = options.infoBox || false;//Disable InfoBox widget
    this.selectionIndicator = options.selectionIndicator || false;//Disable selection indicator
    this.shouldAnimate = options.shouldAnimate || true;// Enable animations

    const fillArea = 'position:absolute;top:0;left:0;width:100%;height:100%;pointer-events: auto;';
    // const fillArea = 'position:absolute;top:0;left:0;width:100%;height:100%;';

    /**
     * @type {!Element}
     * @private
     */
    this.container_ = document.createElement('DIV');
    const containerAttribute = document.createAttribute('style');
    containerAttribute.value = `${fillArea}visibility:hidden;`;
    this.container_.setAttributeNode(containerAttribute);

    // 这里主要为了将 ol 和 cesium 拆开
    let targetElement = options.target || null;
    // let targetElement = options.target || this.map_.getViewport();

    //移除广告
    let removeViewerButtons = function () {
      $(".cesium-viewer").children().each(function () {
        if (!$(this).hasClass('cesium-viewer-cesiumWidgetContainer')
            && !$(this).hasClass('cesium-viewer-infoBoxContainer')
            && !$(this).hasClass('cesium-viewer-selectionIndicatorContainer')) {
          $(this).remove();
        }
      })
    }

    let viewer,thisObject = this;

    if (targetElement) {
      if (typeof targetElement === 'string') {


        // targetElement = document.getElementById(targetElement);
        //使用原始cesium方式初始化
        // viewer = new Cesium.Viewer(targetElement, {
        //   infoBox: thisObject.infoBox, //Disable InfoBox widget
        //   selectionIndicator: thisObject.selectionIndicator, //Disable selection indicator
        //   shouldAnimate: thisObject.shouldAnimate, // Enable animations
        //   //需要进行可视化的数据源的集合
        //   animation: false, //是否显示动画控件
        //   homeButton: false, //是否显示Home按钮
        //   fullscreenButton: false, //是否显示全屏按钮
        //   baseLayerPicker: false, //是否显示图层选择控件
        //   geocoder: false, //是否显示地名查找控件
        //   timeline: false, //是否显示时间线控件
        //   sceneModePicker: false, //是否显示投影方式控件
        //   navigationHelpButton: false, //是否显示帮助信息控件
        //   requestRenderMode: false, //启用请求渲染模式
        //   scene3DOnly: false, //每个几何实例将只能以3D渲染以节省GPU内存
        // });

        const optional = {
          terrain: true,
          // 在线底图
          defaultLayer: 'online',
          // 使用官方影像图
          // officialLayer: true,
          // officialTerrain: false,
          // beautify: true,
          // color: 'dark', // # 黑色 dark,蓝色 darkBlue,绿色 darkGreen
          // sunlight: true,
          animation: true,
          timeline: true,
          minimumLevel: -1,
          maximumLevel: 23,
          // terrainExaggeration: 1.2,
          // limitExtent: Constant.EXTENT_CHINA
          // url: 'http://192.168.242.24:8180/world84/ter/',
          // annotation: 'http://192.168.242.24:8180/world84/cta/',
        };

        viewer = new LSSEC.GLMap(targetElement, optional);

        //获取cesium视野对象
        let cesiumChidren = $(viewer.container).find('.cesium-viewer-cesiumWidgetContainer')
            .find('.cesium-widget').children();

        //将cesium视野对象移入ol-cesium对象中
        cesiumChidren.each(function (e, f) {
          if (e == 0) {
            $(this).css('position', 'absolute');
            $(this).css('top', '0px');
            $(this).css('left', '0px');
            $(this).css('width', '100%');
            $(this).css('height', '100%');
          }
          thisObject.container_.append(this);
        });
        targetElement = document.getElementById(targetElement);
        targetElement.appendChild(this.container_);
      }
    } else {
      const seOverlayContainer =
          this.map_.getViewport().querySelector('.ol-overlaycontainer-stopevent');
      seOverlayContainer.insertBefore(this.container_, seOverlayContainer.firstChild);
      viewer = new Cesium.Viewer(this.container_);
    }
    removeViewerButtons();

    // if (typeof targetElement === 'string') {
    //   targetElement = document.getElementById(targetElement);
    // }
    // targetElement.appendChild(this.container_);

    /**
     * Whether the Cesium container is placed over the ol map.
     * a target => side by side mode
     * no target => over map mode
     * @type {boolean}
     * @private
     */
    this.isOverMap_ = !options.target;


    if (this.isOverMap_ && options.stopOpenLayersEventsPropagation) {
      const overlayEvents = ['click', 'dblclick', 'mousedown', 'touchstart',
        'MSPointerDown', 'pointerdown', 'mousewheel', 'wheel'];
      for (let i = 0, ii = overlayEvents.length; i < ii; ++i) {
        this.container_.addEventListener(overlayEvents[i], evt => evt.stopPropagation());
      }
    }


    /**
     * @type {!HTMLCanvasElement}
     * @private
     */
    // this.canvas_ = /** @type {!HTMLCanvasElement} */ (document.createElement('CANVAS'));
    // const canvasAttribute = document.createAttribute('style');
    // canvasAttribute.value = fillArea;
    // this.canvas_.setAttributeNode(canvasAttribute);
    //
    // if (supportsImageRenderingPixelated()) {
    //   // non standard CSS4
    //   this.canvas_.style['imageRendering'] = imageRenderingValue();
    // }
    //
    // this.canvas_.oncontextmenu = function() { return false; };
    // this.canvas_.onselectstart = function() { return false; };
    //
    // this.container_.appendChild(this.canvas_);

    // 重新制定 canvas
    this.canvas_ = viewer.scene._canvas;

    /**
     * @type {boolean}
     * @private
     */
    this.enabled_ = false;

    /**
     * @type {!Array.<ol.interaction.Interaction>}
     * @private
     */
    this.pausedInteractions_ = [];

    /**
     * @type {?ol.layer.Group}
     * @private
     */
    this.hiddenRootGroup_ = null;

    const sceneOptions = options.sceneOptions !== undefined ? options.sceneOptions :
      /** @type {Cesium.SceneOptions} */ ({});
    sceneOptions.canvas = this.canvas_;
    sceneOptions.scene3DOnly = true;

    /**
     * @type {!Cesium.Scene}
     * @private
     */

    this.viewer_ = viewer || {};
    this.scene_ = this.viewer_.scene;

    // this.scene_ = new Cesium.Scene(sceneOptions);

    const sscc = this.scene_.screenSpaceCameraController;

    sscc.tiltEventTypes.push({
      'eventType': Cesium.CameraEventType.LEFT_DRAG,
      'modifier': Cesium.KeyboardEventModifier.SHIFT
    });

    sscc.tiltEventTypes.push({
      'eventType': Cesium.CameraEventType.LEFT_DRAG,
      'modifier': Cesium.KeyboardEventModifier.ALT
    });

    sscc.enableLook = false;

    this.scene_.camera.constrainedAxis = Cesium.Cartesian3.UNIT_Z;

    /**
     * @type {!olcs.Camera}
     * @private
     */
    this.camera_ = new olcsCamera(this.scene_, this.map_);

    /**
     * @type {!Cesium.Globe}
     * @private
     */
    this.globe_ = new Cesium.Globe(Cesium.Ellipsoid.WGS84);
    this.globe_.baseColor = Cesium.Color.WHITE;
    this.scene_.globe = this.globe_;
    this.scene_.skyAtmosphere = new Cesium.SkyAtmosphere();

    // The first layer of Cesium is special; using a 1x1 transparent image to workaround it.
    // See https://github.com/AnalyticalGraphicsInc/cesium/issues/1323 for details.
    const firstImageryProvider = new Cesium.SingleTileImageryProvider({
      tileHeight: 1,
      tileWidth: 1,
      url: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=',
      rectangle: Cesium.Rectangle.fromDegrees(0, 0, 1, 1) // the Rectangle dimensions are arbitrary
    });
    this.globe_.imageryLayers.addImageryProvider(firstImageryProvider, 0);

    this.dataSourceCollection_ = new Cesium.DataSourceCollection();
    this.dataSourceDisplay_ = new Cesium.DataSourceDisplay({
      scene: this.scene_,
      dataSourceCollection: this.dataSourceCollection_
    });

    const synchronizers = options.createSynchronizers ?
      options.createSynchronizers(this.map_, this.scene_, this.dataSourceCollection_) : [
        new olcsRasterSynchronizer(this.map_, this.scene_),
        new olcsVectorSynchronizer(this.map_, this.scene_),
        new olcsOverlaySynchronizer(this.map_, this.scene_)
      ];

    //暴露此对象,用于删除三维对象
    this.synchronizers = synchronizers;

    // Assures correct canvas size after initialisation
    this.handleResize_();

    for (let i = synchronizers.length - 1; i >= 0; --i) {
      synchronizers[i].synchronize();
    }

    /**
     * Time of the last rendered frame, as returned by `performance.now()`.
     * @type {number}
     * @private
     */
    this.lastFrameTime_ = 0;

    /**
     * The identifier returned by `requestAnimationFrame`.
     * @type {number|undefined}
     * @private
     */
    this.renderId_ = undefined;

    /**
     * Target frame rate for the render loop.
     * @type {number}
     * @private
     */
    this.targetFrameRate_ = Number.POSITIVE_INFINITY;

    /**
     * If the Cesium render loop is being blocked.
     * @type {boolean}
     * @private
     */
    this.blockCesiumRendering_ = false;

    /**
     * If the warmup routine is active.
     * @type {boolean}
     * @private
     */
    this.warmingUp_ = false;

    /**
     * @type {ol.Feature}
     * @private
     */
    this.trackedFeature_ = null;

    /**
     * @type {Cesium.Entity}
     * @private
     */
    this.trackedEntity_ = null;

    /**
     * @type {Cesium.EntityView}
     * @private
     */
    this.entityView_ = null;

    /**
     * @type {boolean}
     * @private
     */
    this.needTrackedEntityUpdate_ = false;

    /**
     * @type {!Cesium.BoundingSphere}
     */
    this.boundingSphereScratch_ = new Cesium.BoundingSphere();

    const eventHelper = new Cesium.EventHelper();
    eventHelper.add(this.scene_.postRender, OLCesium.prototype.updateTrackedEntity_, this);

    // Cesium.Camera.enableSuspendTerrainAdjustment = false;

  }

  /**
   * Render the Cesium scene.
   * @private
   */
  render_() {
    // if a call to `requestAnimationFrame` is pending, cancel it
    if (this.renderId_ !== undefined) {
      cancelAnimationFrame(this.renderId_);
      this.renderId_ = undefined;
    }

    // only render if Cesium is enabled/warming and rendering hasn't been blocked
    if ((this.enabled_ || this.warmingUp_) && !this.blockCesiumRendering_) {
      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.handleResize_();
    this.dataSourceDisplay_.update(julianDate);

    // Update tracked entity
    if (this.entityView_) {
      const trackedEntity = this.trackedEntity_;
      const trackedState = this.dataSourceDisplay_.getBoundingSphere(trackedEntity, false, this.boundingSphereScratch_);
      if (trackedState === Cesium.BoundingSphereState.DONE) {
        this.boundingSphereScratch_.radius = 1; // a radius of 1 is enough for tracking points
        this.entityView_.update(julianDate, this.boundingSphereScratch_);
      }
    }

    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_();
  }

  /**
   * @private
   */
  updateTrackedEntity_() {
    if (!this.needTrackedEntityUpdate_) {
      return;
    }

    const trackedEntity = this.trackedEntity_;
    const scene = this.scene_;

    const state = this.dataSourceDisplay_.getBoundingSphere(trackedEntity, false, this.boundingSphereScratch_);
    if (state === Cesium.BoundingSphereState.PENDING) {
      return;
    }

    scene.screenSpaceCameraController.enableTilt = false;

    const bs = state !== Cesium.BoundingSphereState.FAILED ? this.boundingSphereScratch_ : undefined;
    if (bs) {
      bs.radius = 1;
    }
    this.entityView_ = new Cesium.EntityView(trackedEntity, scene, scene.mapProjection.ellipsoid);
    this.entityView_.update(this.time_(), bs);
    this.needTrackedEntityUpdate_ = false;
  }

  /**
   * @private
   */
  handleResize_() {
    let width = this.canvas_.clientWidth;
    let height = this.canvas_.clientHeight;

    if (width === 0 | height === 0) {
      // The canvas DOM element is not ready yet.
      return;
    }

    if (width === this.canvasClientWidth_ &&
        height === this.canvasClientHeight_ &&
        !this.resolutionScaleChanged_) {
      return;
    }

    let resolutionScale = this.resolutionScale_;
    if (!supportsImageRenderingPixelated()) {
      resolutionScale *= window.devicePixelRatio || 1.0;
    }
    this.resolutionScaleChanged_ = false;

    this.canvasClientWidth_ = width;
    this.canvasClientHeight_ = height;

    width *= resolutionScale;
    height *= resolutionScale;

    this.canvas_.width = width;
    this.canvas_.height = height;
    this.scene_.camera.frustum.aspectRatio = width / height;
  }

  /**
   * @return {!olcs.Camera}
   * @api
   */
  getCamera() {
    return this.camera_;
  }

  /**
   * @return {!ol.Map}
   * @api
   */
  getOlMap() {
    return this.map_;
  }

  /**
   * @return {!ol.View}
   * @api
   */
  getOlView() {
    const view = this.map_.getView();
    console.assert(view);
    return view;
  }

  /**
   * @return {!Cesium.Scene}
   * @api
   */
  getCesiumScene() {
    return this.scene_;
  }

  /**
   * @return {!Cesium.Viewer}
   * @api
   */
  getViewer() {
    return this.viewer_;
  }

  /**
   * @return {!Cesium.DataSourceCollection}
   * @api
   */
  getDataSources() {
    return this.dataSourceCollection_;
  }

  /**
   * @return {!Cesium.DataSourceDisplay}
   * @api
   */
  getDataSourceDisplay() {
    return this.dataSourceDisplay_;
  }

  /**
   * @return {boolean}
   * @api
   */
  getEnabled() {
    return this.enabled_;
  }

  /**
   * Enables/disables the Cesium.
   * This modifies the visibility style of the container element.
   * @param {boolean} enable
   * @api
   */
  setEnabled(enable) {
    if (this.enabled_ === enable) {
      return;
    }
    this.enabled_ = enable;

    // some Cesium operations are operating with canvas.clientWidth,
    // so we can't remove it from DOM or even make display:none;
    this.container_.style.visibility = this.enabled_ ? 'visible' : 'hidden';
    let interactions;
    if (this.enabled_) {
      this.throwOnUnitializedMap_();
      if (this.isOverMap_) {
        interactions = this.map_.getInteractions();
        interactions.forEach((el, i, arr) => {
          this.pausedInteractions_.push(el);
        });
        interactions.clear();

        this.map_.addInteraction = interaction => this.pausedInteractions_.push(interaction);
        this.map_.removeInteraction = interaction =>
          this.pausedInteractions_ = this.pausedInteractions_.filter(i => i !== interaction);

        const rootGroup = this.map_.getLayerGroup();
        if (rootGroup.getVisible()) {
          this.hiddenRootGroup_ = rootGroup;
          this.hiddenRootGroup_.setVisible(false);
        }

        this.map_.getOverlayContainer().classList.add('olcs-hideoverlay');
      }

      this.camera_.readFromView();
      this.render_();
    } else {
      if (this.isOverMap_) {
        interactions = this.map_.getInteractions();
        this.pausedInteractions_.forEach((interaction) => {
          interactions.push(interaction);
        });
        this.pausedInteractions_.length = 0;

        this.map_.addInteraction = interaction => this.map_.getInteractions().push(interaction);
        this.map_.removeInteraction = interaction => this.map_.getInteractions().remove(interaction);

        this.map_.getOverlayContainer().classList.remove('olcs-hideoverlay');
        if (this.hiddenRootGroup_) {
          this.hiddenRootGroup_.setVisible(true);
          this.hiddenRootGroup_ = null;
        }
      }

      this.camera_.updateView();
    }
  }

  /**
   * Preload Cesium so that it is ready when transitioning from 2D to 3D.
   * @param {number} height Target height of the camera
   * @param {number} timeout Milliseconds after which the warming will stop
   * @api
  */
  warmUp(height, timeout) {
    if (this.enabled_) {
      // already enabled
      return;
    }
    this.throwOnUnitializedMap_();
    this.camera_.readFromView();
    const ellipsoid = this.globe_.ellipsoid;
    const csCamera = this.scene_.camera;
    const position = ellipsoid.cartesianToCartographic(csCamera.position);
    if (position.height < height) {
      position.height = height;
      csCamera.position = ellipsoid.cartographicToCartesian(position);
    }

    this.warmingUp_ = true;
    this.render_();

    setTimeout(() => {
      this.warmingUp_ = false;
    }, timeout);
  }

  /**
   * Block Cesium rendering to save resources.
   * @param {boolean} block True to block.
   * @api
  */
  setBlockCesiumRendering(block) {
    if (this.blockCesiumRendering_ !== block) {
      this.blockCesiumRendering_ = block;

      // reset the render loop
      this.render_();
    }
  }

  /**
   * Render the globe only when necessary in order to save resources.
   * Experimental.
   * @api
   */
  enableAutoRenderLoop() {
    if (!this.autoRenderLoop_) {
      this.autoRenderLoop_ = new olcsAutoRenderLoop(this);
    }
  }

  /**
   * Get the autorender loop.
   * @return {?olcs.AutoRenderLoop}
   * @api
  */
  getAutoRenderLoop() {
    return this.autoRenderLoop_;
  }

  /**
   * The 3D Cesium globe is rendered in a canvas with two different dimensions:
   * clientWidth and clientHeight which are the dimension on the screen and
   * width and height which are the dimensions of the drawing buffer.
   *
   * By using a resolution scale lower than 1.0, it is possible to render the
   * globe in a buffer smaller than the canvas client dimensions and improve
   * performance, at the cost of quality.
   *
   * Pixel ratio should also be taken into account; by default, a device with
   * pixel ratio of 2.0 will have a buffer surface 4 times bigger than the client
   * surface.
   *
   * @param {number} value
   * @this {olcs.OLCesium}
   * @api
   */
  setResolutionScale(value) {
    value = Math.max(0, value);
    if (value !== this.resolutionScale_) {
      this.resolutionScale_ = Math.max(0, value);
      this.resolutionScaleChanged_ = true;
      if (this.autoRenderLoop_) {
        this.autoRenderLoop_.restartRenderLoop();
      }
    }
  }

  /**
   * Set the target frame rate for the renderer. Set to `Number.POSITIVE_INFINITY`
   * to render as quickly as possible.
   * @param {number} value The frame rate, in frames per second.
   * @api
   */
  setTargetFrameRate(value) {
    if (this.targetFrameRate_ !== value) {
      this.targetFrameRate_ = value;

      // reset the render loop
      this.render_();
    }
  }

  /**
   * Check if OpenLayers map is not properly initialized.
   * @private
   */
  throwOnUnitializedMap_() {
    const map = this.map_;
    const view = map.getView();
    const center = view.getCenter();
    if (!view.isDef() || isNaN(center[0]) || isNaN(center[1])) {
      throw new Error(`The OpenLayers map is not properly initialized: ${center} / ${view.getResolution()}`);
    }
  }

  /**
   * @type {ol.Feature}
   */
  get trackedFeature() {
    return this.trackedFeature_;
  }

  /**
   * @param {ol.Feature} feature
   */
  set trackedFeature(feature) {
    if (this.trackedFeature_ !== feature) {

      const scene = this.scene_;

      //Stop tracking
      if (!feature || !feature.getGeometry()) {
        this.needTrackedEntityUpdate_ = false;
        scene.screenSpaceCameraController.enableTilt = true;

        if (this.trackedEntity_) {
          this.dataSourceDisplay_.defaultDataSource.entities.remove(this.trackedEntity_);
        }
        this.trackedEntity_ = null;
        this.trackedFeature_ = null;
        this.entityView_ = null;
        scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
        return;
      }

      this.trackedFeature_ = feature;

      //We can't start tracking immediately, so we set a flag and start tracking
      //when the bounding sphere is ready (most likely next frame).
      this.needTrackedEntityUpdate_ = true;

      const to4326Transform = this.to4326Transform_;
      const toCesiumPosition = function() {
        const geometry = feature.getGeometry();
        console.assert(geometry instanceof olGeomPoint);
        const coo = geometry.getCoordinates();
        const coo4326 = to4326Transform(coo, undefined, coo.length);
        return ol4326CoordinateToCesiumCartesian(coo4326);
      };

      // Create an invisible point entity for tracking.
      // It is independant from the primitive/geometry created by the vector synchronizer.
      const options = {
        'position': new Cesium.CallbackProperty((time, result) => toCesiumPosition(), false),
        'point': {
          'pixelSize': 1,
          'color': Cesium.Color.TRANSPARENT
        }
      };

      this.trackedEntity_ = this.dataSourceDisplay_.defaultDataSource.entities.add(options);
    }
  }
}

export default OLCesium;

这里是 ol-cesium 编译之后,初始化二三维、二三维切换、二三维添加多边形、以及三维通过 viewer 添加点功能示例。


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>二三维一体化示例</title>

    <style>
        body, html {
            /*overflow-y: auto !important;*/
            width: 100%;
            height: 100%;
        }

        .mapContainer {
            width: 100%;
            height: 98%;
            /*display: flex;*/
            /*display: inline;*/
        }

        .outter {
            position: fixed;
            top: 10px;
            z-index: 999;
        }

        .mapContainerFull {
            width: 100%;
            height: 95%;
        }

        .mapContainerChild-two {
            width: 49.99%;
            height: 95%;
            float: left;
            border-right: 1px solid #1e9fff
        }

        .mapContainerChild-three {
            width: calc(100% - 49.99% - 1px);
            height: 95%;
            float: right;
            position: relative;
        }

        /*注意,   如果想让map达到百分之100的宽高, 则map的左右父div需要保证百分之100宽高*/
        .map {
            height: 100%;
        }

        .button-group {
            position: absolute;
            top: 10px;
            z-index: 9999;
        }
    </style>
</head>
<body>

<div class="map">
    <div class="mapContainer">
        <div class="button-group">
            <input type="button" value="二维" onClick='changeType(1) '/>
            <input type="button" value="三维" onClick='changeType(2) '/>
            <input type="button" value="二/三维" onClick='changeType() '/>
        </div>
        <!--注意:这里的样式名称要配合方法使用,尽量不要修改,可以添加额外样式!-->
        <div id="mapContainer" class="mapContainerChild-mapContainer-two mapContainerChild-two">
        </div>
        <div id="mapContainer2" class="mapContainerChild-mapContainer-three mapContainerChild-three">
        </div>
    </div>
</div>
<script type="text/javascript" src="https://www.openlayers.vip/apidoc/resources/jquery-3.6.0.min.js"></script>

<script src="./staticForMap/js/config.js"></script>
<script src="./staticForMap/js/lssec.cesium.js"></script>
</body>
</html>
<script type="text/javascript">

	// 二维对象、三维对象
    let ol2d, ol3d;

    function initMap() {

		// 自定义初始化二三维
        const GLMap = new LSSEC.GLMap('mapContainer', 'mapContainer2');

        ol2d = GLMap.ol2d;
        ol3d = GLMap.ol3d;

        const wkt = "POLYGON((112.38882259396966 40.668378110616445,117.91494564084466 42.942548032491445,118.53018001584466 38.954510923116445,117.06899837521966 36.098065610616445,113.21279720334466 37.603192563741445,112.38882259396966 40.668378110616445))";
		
		// 二维添加多边形,自动同步至三维
        ol2d.addFeature(wkt);

		// 输出查看 viewer 对象
		console.log(ol3d.getViewer());
		// 三维通过 viewer 添加点
        ol3d.addPoint([116.27798275021966, 39.899335141866445]);
    }

    initMap();

    function changeType(flag) {

        if (flag == '1') {
            $('.mapContainerChild-mapContainer-two').removeClass('mapContainerChild-two').addClass('mapContainerFull');
            $('.mapContainerChild-mapContainer-three').removeClass('mapContainerFull').addClass('mapContainerChild-three');
            ol2d.updateSize();
        } else if (flag == '2') {
            $('.mapContainerChild-mapContainer-two').removeClass('mapContainerFull').addClass('mapContainerChild-two');
            $('.mapContainerChild-mapContainer-three').removeClass('mapContainerChild-three').addClass('mapContainerFull');
        } else {
            $('.mapContainerChild-mapContainer-two').removeClass('mapContainerFull').addClass('mapContainerChild-two');
            $('.mapContainerChild-mapContainer-three').removeClass('mapContainerFull').addClass('mapContainerChild-three');
        }
    }
</script>


在线示例

ol-cesium 暴露 viewer 对象以及其他功能示例

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/915626.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

恭喜发财!

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>恭喜发财</title><link rel"stylesheet" href"css/style.css"> </head><body><section class"co…

leetcode1094. 拼车(差分数组-java)

差分数组 leetcode 1094 拼车差分数组代码演示&#xff1a; 前缀和数组 leetcode 1094 拼车 难度 - 中等 原题链接 - 拼车 车上最初有 capacity 个空座位。车 只能 向一个方向行驶&#xff08;也就是说&#xff0c;不允许掉头或改变方向&#xff09; 给定整数 capacity 和一个数…

解决方案:fatal error: openssl/bio.h: 没有那个文件或目录

出现报错如下&#xff1a; 出现该错误的原因有两个&#xff1a; 没有安装openssl或者libssl-dev库Libssl-dev版本过高&#xff0c;需要降级 一. 没有安装openssl或者libssl-dev库 使用指令安装openssl&#xff1a; 我的是已经安装完成了&#xff0c;所以再把libssl-dev的库也…

进程调度和进程切换——《王道考研》

一、王道书咋说 二、chatgpt咋说 进程调度和进程切换是多道程序操作系统中两个关键的概念&#xff0c;它们在处理多个进程时起着不同的作用。 2.1进程调度是指&#xff1a; 操作系统根据一定的调度算法&#xff0c;从就绪态的进程队列中选择一个进程来占用CPU资源&#xff0…

dfs之单词搜索

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那些水平相邻或垂直相…

江西抚州新能源汽车3d扫描零部件逆向抄数测量改装-CASAIM中科广电

汽车改装除了在外观方面越来越受到消费者的青睐&#xff0c;在性能和实用性提升上面的需求也是日趋增多&#xff0c;能快速有效地对客户指定汽车零部件进行一个改装&#xff0c;是每一个汽车改装企业和工程师的追求&#xff0c;也是未来消费者个性化差异化的要求。下面CASAIM中…

汉字占用两字节原因

经常可以看到这么一句话: 英文及符号占用一个字节,汉字占用两个字节. 大家大都强行记忆,并没有关注原因. 今天就能看看到底是什么原因导致的呢? 我们先看大家都见过的一张图 其中字符char占位一个字节或者两个字节. 当占位一个字节时,最大值为2^7-1,十进制为127,二进制为0111…

一文速学-LightGBM模型算法原理以及实现+Python项目实战

LighGBM 前言 LighGBM作为GBDT算法的衍生模型&#xff0c;在其他论文研究以及数学建模比赛中十分常见。如果不熟悉GBDT算法的可以去看看我的上一篇文章&#xff0c;过多关于GBDT的细节不再过多描述。主要将讲述一下LighGBM较于GBDT算法的改进以及独特算法细节优化&#xff0c…

yolov8后处理——DFL卷积如何卷

以 512*288 输入为例&#xff0c;网络输出大小 1*64*3024&#xff0c;其中 1 为 batch size&#xff0c;64为超参数reg_max16 和 bbox 个数 4 的乘积&#xff0c;302416*932*1864*36&#xff08;其中512/3216,288/329&#xff09; 首先 DFL 卷积是和 0-15 卷积&#xff0c;下面…

Ros noetic Move_base 监听Move状态 实战使用教程

前言: 承接上一篇文章,在上一文中我们了解到move_base有几种监听的状态,我一文章中我将开源全部监听代码,本文将从0开始建立监听包,并覆上全部的工程代码,和仿真实操结果。 本文,还将解决当临时障碍物与机身相交时,机器人回人为自己被“卡住”,局部规划器规划的速度为…

商业大厦烟感监控,效果出乎意料!

烟感监控是现代安全技术中至关重要的一环&#xff0c;其在预防火灾、保护生命和财产方面发挥着关键作用。通过使用先进的烟雾探测器和智能报警系统&#xff0c;烟感监控能够及早发现烟雾和火源&#xff0c;并在火灾爆发前提供必要的警示和警报。 通过其精密的传感技术和联动装置…

新品如何传播,小红书种草策略分析!

种草是小红书品宣与传播的核心&#xff0c;也是平台的巨大优势。品牌想要在小红书进行快速传播&#xff0c;制定一份可落地实施的种草策略是必不可少的。今天将通过一篇文章&#xff0c;给大家分享一下新品如何传播&#xff0c;小红书种草策略分析&#xff01; 一、如何进行小红…

6、Spring_Junit与JdbcTemplate整合

Spring 整合 1.Spring 整合 Junit 1.1新建项目结构 1.2导入依赖 导入 junit 与 Spring 依赖 <!-- 添加 spring 依赖--> <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version…

pdf格式怎么编辑?了解这种编辑方法就可以了

pdf格式怎么编辑&#xff1f;PDF作为一种通用的文档格式&#xff0c;以其跨平台、保真排版等优势在各个领域得到广泛应用。然而&#xff0c;对于许多人来说&#xff0c;PDF文件一直以来都被视为“静态”文件&#xff0c;不易编辑。但现在&#xff0c;有很多编辑器可以帮助我们进…

qt5 TLS initialization failed error

首先打印openssl支持信息 qDebug() << QSslSocket::supportsSsl() << "\n"; qDebug() << QSslSocket::sslLibraryBuildVersionString(); //上述代码打印下面的结果&#xff1a; false "OpenSSL 1.1.1g 21 Apr 2020"更新对应openssl证…

【从零学习python 】74. UDP网络程序:端口问题与绑定信息详解

文章目录 udp网络程序-端口问题UDP绑定信息总结 进阶案例 udp网络程序-端口问题 在运行 UDP 网络程序时&#xff0c;会遇到端口号会变化的情况。 每次重新运行网络程序后&#xff0c;可以观察到运行中的“网络调试助手”显示的数字是不同的。这是因为该数字标识了网络程序的…

35309-53-6,cyclo(Asp-Asp),氨基酸中间体,环(-天冬氨酰-天冬氨酰),

中文名&#xff1a;CYCLO(-天冬氨酸-ASP) 2,5-哌嗪二乙酸&#xff0c;3,6-二氧基-&#xff08;2S-顺式&#xff09; 环(-天冬氨酰-天冬氨酰) 英文名&#xff1a;cyclo(Asp-Asp)&#xff0c; [(2S)-(3,6-dioxo-piperazine-2r,5c-diyl)-di-acetic acid Cyclo(L-Aspartyl-L-A…

iPhone如何录屏?详细教程大揭秘(最新)

“iphone怎么录屏呀&#xff0c;有人知道吗&#xff1f;用了很久的iphone12了&#xff0c;却不知道录屏功能在哪里&#xff0c;现在需要用来录教程&#xff0c;找也找不到&#xff0c;有人知道iphone录屏在哪里吗&#xff1f;很急&#xff01;” iphone作为一款备受欢迎的智能…

MySQL 主从配置

环境 centos6.7 虚拟机两台 主&#xff1a;192.168.23.160 从&#xff1a;192.168.23.163 准备 在两台机器上分别安装mysql5.6.23&#xff0c;安装完成后利用临时密码登录mysql数据修改root的密码&#xff1b;将my.cnf配置文件放至/etc/my.cnf&#xff0c;重启mysql服务进…

多旋翼飞控底层算法开发系列实验 | 多旋翼动力系统设计实验2

多旋翼飞控底层算法开发系列实验 | 多旋翼动力系统设计实验2 01/多旋翼动力系统简介 多旋翼无人机的动力系统通常包括螺旋桨、电机、电调以及电池。动力系统是多旋翼最重要的组成部分&#xff0c;它决定了多旋翼的主要性能&#xff0c;如悬停时间、载重能力、飞行速度和飞行距…