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 对象以及其他功能示例