Cesium
中可操作的模塊都是由Widget
組成的,比如地圖上的首頁
按鈕腮郊,點擊按鈕后地圖將恢復(fù)到地球狀態(tài)摹蘑,看似一個很簡單的功能,代碼卻不少轧飞,這是由于使用了組件化的思想衅鹿,將一些功能抽成組件的方式方便添加和刪除。下面就使用原生的javascript
來實現(xiàn)一個放大縮小地圖的組件过咬,后面再介紹使用用vue
來實現(xiàn)其它的組件大渤。主要包括ZoomInOut .js
,ZoomInOut .css
,ZoomInOutViewModel.js
三個文件效果圖如下所示:
1.創(chuàng)建ViewModel文件
自定義組件采用的是MVVM
的思想,主要借助于knockout
這個js
庫來實現(xiàn)ViewModel
泵三,因此在創(chuàng)建自定義組件的時候需要創(chuàng)建一個ViewModel
的文件,該文件主要用于定義屬性衔掸、創(chuàng)建事件的實現(xiàn)烫幕。
1.1 定義屬性
使用Object.defineProperties
重寫get
和set
方法敞映。如下所示:
Object.defineProperties(ZoomInOutViewModel.prototype, {
scene: {
get: function () {
return this._scene;
},
},
zoomIn: {
get: function () {
return this._zoomIn;
},
},
zoomOut: {
get: function () {
return this._zoomOut;
},
},
});
1.2 創(chuàng)建事件
使用createCommand
進行創(chuàng)建事件,
this._zoomIn = createCommand(function () {
});
//ZoomInOutViewModel.js
import defined from "../../Core/defined.js";
import DeveloperError from "../../Core/DeveloperError.js";
import knockout from "../../ThirdParty/knockout.js";
import createCommand from "../createCommand.js";
function ZoomInOutViewModel(scene) {
if (!defined(scene)) {
throw new DeveloperError("scene is required.");
}
this._scene = scene;
var that = this;
this._zoomOut = createCommand(function () {
// 獲取當前鏡頭位置的笛卡爾坐標
let cameraPos = that._scene.camera.position;
// 獲取當前坐標系標準
let ellipsoid = that._scene.globe.ellipsoid;
// 根據(jù)坐標系標準诗芜,將笛卡爾坐標轉(zhuǎn)換為地理坐標
let cartographic = ellipsoid.cartesianToCartographic(cameraPos);
// 獲取鏡頭的高度
let height = cartographic.height;
that._scene.camera.zoomOut(height * 1.2);
});
this._zoomIn = createCommand(function () {
// 獲取當前鏡頭位置的笛卡爾坐標
let cameraPos = that._scene.camera.position;
// 獲取當前坐標系標準
let ellipsoid = that._scene.globe.ellipsoid;
// 根據(jù)坐標系標準,將笛卡爾坐標轉(zhuǎn)換為地理坐標
let cartographic = ellipsoid.cartesianToCartographic(cameraPos);
// 獲取鏡頭的高度
let height = cartographic.height;
that._scene.camera.zoomIn(height/3);
});
this.zoomInTooltip = "放大";
this.zoomOutTooltip = "縮小";
knockout.track(this, ["zoomInTooltip"]);
knockout.track(this, ["zoomOutTooltip"]);
}
Object.defineProperties(ZoomInOutViewModel.prototype, {
scene: {
get: function () {
return this._scene;
},
},
zoomIn: {
get: function () {
return this._zoomIn;
},
},
zoomOut: {
get: function () {
return this._zoomOut;
},
},
});
export default ZoomInOutViewModel;
2.創(chuàng)建元素
創(chuàng)建元素跟平時我們使用js
創(chuàng)建元素的方式是一樣的,主要不同點在于事件的綁定不一樣栓霜,這里綁定事件是直接在setAttribute
中使用click
進行事件綁定翠桦,click
指定的函數(shù)名為ViewModel
中創(chuàng)建的事件函數(shù),如下所示:
var zoomOut = document.createElement("button");
zoomOut.style.marginTop = '5px';
zoomOut.style.fontWeight = 'bold';
zoomOut.type = "button";
zoomOut.className = "cesium-button cesium-toolbar-button cesium-home-button";
zoomOut.setAttribute(
"data-bind",
"\
attr: { title: zoomOutTooltip },\
click: zoomOut"
);
zoomOut.innerText = "-";
element.appendChild(zoomOut);
3.綁定元素
創(chuàng)建好ViewModel
后胳蛮,需要將ViewModel
與元素進行綁定销凑,采用knockout
中的applyBindings
進行元素的綁定,如下所示:
knockout.applyBindings(viewModel, element);
4.添加元素到地圖上
創(chuàng)建好元素并綁定后仅炊,需要將其顯示在地圖上斗幼,首先找到Viewer.js
文件,在/Cesium/Source/Widgets/Viewer/Viewer.js
目錄下抚垄,然后將ZoomInOut.js
引入進行再進行實例化蜕窿,將新的元素添加到viewerContainer
上谋逻,如下所示:
import ZoomInOut from "../ZoomInOut/ZoomInOut.js";
//ZoomInOut
var zoomInOutContainer = document.createElement("div");
zoomInOutContainer.className = "cesium-viewer-zoomInOutContainer";
viewerContainer.appendChild(zoomInOutContainer);
var zoomInOut = new ZoomInOut(zoomInOutContainer,scene);
//ZoomInOut.js
import defined from "../../Core/defined.js";
import destroyObject from "../../Core/destroyObject.js";
import DeveloperError from "../../Core/DeveloperError.js";
import knockout from "../../ThirdParty/knockout.js";
import getElement from "../getElement.js";
import ZoomInOutViewModel from "./ZoomInOutViewModel.js";
/**
* 放大縮小組件
* @param container
* @param scene
* @constructor
*/
function ZoomInOut(container, scene) {
if (!defined(container)) {
throw new DeveloperError("container is required.");
}
container = getElement(container);
var viewModel = new ZoomInOutViewModel(scene);
var element = document.createElement("div");
var zoomIn = document.createElement("button");
zoomIn.type = "button";
zoomIn.className = "cesium-button cesium-toolbar-button cesium-home-button";
zoomIn.setAttribute(
"data-bind",
"\
attr: { title: zoomInTooltip },\
click: zoomIn"
);
zoomIn.innerText = "+";
element.appendChild(zoomIn);
var zoomOut = document.createElement("button");
zoomOut.style.marginTop = '5px';
zoomOut.style.fontWeight = 'bold';
zoomOut.type = "button";
zoomOut.className = "cesium-button cesium-toolbar-button cesium-home-button";
zoomOut.setAttribute(
"data-bind",
"\
attr: { title: zoomOutTooltip },\
click: zoomOut"
);
zoomOut.innerText = "-";
element.appendChild(zoomOut);
container.appendChild(element);
knockout.applyBindings(viewModel, element);
this._container = container;
this._viewModel = viewModel;
this._element = element;
}
Object.defineProperties(ZoomInOut.prototype, {
container: {
get: function () {
return this._container;
},
},
viewModel: {
get: function () {
return this._viewModel;
},
},
});
/**
* 判斷是否銷毀組件,由于能調(diào)用該方法桐经,所以一定是沒銷毀的毁兆,因此直接返回false
* @returns {boolean}
*/
ZoomInOut.prototype.isDestroyed = function () {
return false;
};
/**
* 銷毀組件
*/
ZoomInOut.prototype.destroy = function () {
knockout.cleanNode(this._element);
this._container.removeChild(this._element);
return destroyObject(this);
};
export default ZoomInOut;
5.引入樣式文件
如果有創(chuàng)建css
文件,需要引入到項目中阴挣,首先找到widgets.css
文件气堕,目錄在/Cesium/Source/Widgets/widgets.css
,然后使用@import url(./ZoomInOut/ZoomInOut.css);
引入樣式文件畔咧。
.cesium-viewer-zoomInOutContainer{
display: block;
width: 30px;
height: 100px;
margin: 0;
border-radius: 0;
position: absolute;
right:12px;
top: 40px;
}