Cesium指南-自定義原生js組件

Cesium中可操作的模塊都是由Widget組成的,比如地圖上的首頁按鈕,點擊按鈕后地圖將恢復到地球狀態(tài),看似一個很簡單的功能,代碼卻不少,這是由于使用了組件化的思想,將一些功能抽成組件的方式方便添加和刪除。下面就使用原生的javascript來實現(xiàn)一個放大縮小地圖的組件,后面再介紹使用用vue來實現(xiàn)其它的組件。主要包括ZoomInOut .js,ZoomInOut .css,ZoomInOutViewModel.js三個文件效果圖如下所示:

WX20210418-190206@2x.png

1.創(chuàng)建ViewModel文件

自定義組件采用的是MVVM的思想,主要借助于knockout這個js庫來實現(xiàn)ViewModel,因此在創(chuàng)建自定義組件的時候需要創(chuàng)建一個ViewModel的文件,該文件主要用于定義屬性、創(chuàng)建事件的實現(xiàn)。

1.1 定義屬性

使用Object.defineProperties重寫getset方法。如下所示:

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;
}

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容