Cesium學習筆記(四): 相機(camera)

相機可以控制我們在場景中的視野,默認的,相機操作是這樣的:

  • 左鍵單擊並拖動 - 移動整個地圖
  • 右鍵單擊並拖動 - 放大和縮小相機。
  • 中輪滾動 - 也可以放大和縮小相機。
  • 中間點擊並拖動 - 圍繞地球表面的點旋轉相機。

我們可以自己給相機設置位置

var point = Cesium.Cartesian3.fromDegrees(-117.16, 32.71, 15000.0);
camera.setView({
    destination : point,
    orientation: {
        heading : Cesium.Math.toRadians(0.0), //默認值
        pitch : Cesium.Math.toRadians(-90.0), // 默認值
        roll : 0.0 //默認值
    }
});

這裏寫圖片描述

可以看出來,我們加載的是一個點,這個視野也是從這個點看去的視野,我們也可以加載一個矩形,也就是整個視野區域

//他需要西,南,東,北四個度數來構成
var rectangle = Cesium.Rectangle.fromDegrees(0.0, 20.0, 10.0, 30.0);
camera.setView({
    destination : point,
    orientation: {
        heading : Cesium.Math.toRadians(0.0), //默認值
        pitch : Cesium.Math.toRadians(-90.0), // 默認值
        roll : 0.0 //默認值
    }
});

這裏寫圖片描述

你現在所看到的區域就是我們加載的這個矩形了

現在,我們來嘗試自己覆寫鏡頭移動。

首先肯定是先把原有的給禁止掉

var viewer = new Cesium.Viewer("cesiumContainer");
var scene = viewer.scene;
var canvas = viewer.canvas;
canvas.setAttribute('tabindex', '0'); // 需要把焦點放在畫布上
canvas.onclick = function() {
    canvas.focus();
};
//這個橢球形就是地球了
var ellipsoid = viewer.scene.globe.ellipsoid;

// 禁止默認的事件
scene.screenSpaceCameraController.enableRotate = false;
scene.screenSpaceCameraController.enableTranslate = false;
scene.screenSpaceCameraController.enableZoom = false;
scene.screenSpaceCameraController.enableTilt = false;
scene.screenSpaceCameraController.enableLook = false;

然後再創建我們用來記錄鼠標位置和鍵盤點擊情況的變量

//存儲鼠標位置的變量
var startMousePosition;
var mousePosition;

var flags = {
    //記錄是否在查看地圖,也就是記錄是否點擊了鼠標或鍵盤
    looking : false,
    //記錄鍵盤的前後上下左右
    moveForward : false,
    moveBackward : false,
    moveUp : false,
    moveDown : false,
    moveLeft : false,
    moveRight : false
};

繼續爲鍵盤的wasdqe幾個鍵設置相機移動效果

//判斷鍵盤的輸入
function getFlagForKeyCode(keyCode) {
    switch (keyCode) {
    case 'W'.charCodeAt(0):
        return 'moveUp';
    case 'S'.charCodeAt(0):
        return 'moveDown';
    case 'Q'.charCodeAt(0):
        return 'moveForward';
    case 'E'.charCodeAt(0):
        return 'moveBackward';
    case 'D'.charCodeAt(0):
        return 'moveRight';
    case 'A'.charCodeAt(0):
        return 'moveLeft';
    default:
        return undefined;
    }
}
//獲得鍵盤keydown事件
document.addEventListener('keydown', function(e) {
    var flagName = getFlagForKeyCode(e.keyCode);
    if (typeof flagName !== 'undefined') {
        flags[flagName] = true;
    }
}, false);
//獲得鍵盤keyup事件
document.addEventListener('keyup', function(e) {
    var flagName = getFlagForKeyCode(e.keyCode);
    if (typeof flagName !== 'undefined') {
        flags[flagName] = false;
    }
}, false);

別忘了,還有鼠標

//監聽用戶的輸入
var handler = new Cesium.ScreenSpaceEventHandler(canvas);
//當鼠標左鍵按下時執行(拿到鼠標按下時的位置)
handler.setInputAction(function(movement) {
    flags.looking = true;
    mousePosition = startMousePosition = Cesium.Cartesian3.clone(movement.position);
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
//當鼠標移動時執行(拿到鼠標擡起時的位置)
handler.setInputAction(function(movement) {
    mousePosition = movement.endPosition;
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
//當鼠標左鍵擡起時執行
handler.setInputAction(function(position) {
    flags.looking = false;
}, Cesium.ScreenSpaceEventType.LEFT_UP);

最後根據我們接收的鼠標和鍵盤的輸入,來實現真正的相機移動

//更新相機
viewer.clock.onTick.addEventListener(function(clock) {
    var camera = viewer.camera;
    //當按下鼠標左鍵時
    if (flags.looking) {
        var width = canvas.clientWidth;
        var height = canvas.clientHeight;

        // 鼠標滑動的距離的xy/網頁可見區域的寬或者高
        var x = (mousePosition.x - startMousePosition.x) / width;
        var y = -(mousePosition.y - startMousePosition.y) / height;
        //這就是決定相機移動速度的參數
        var lookFactor = 0.05;
        //相機移動
        camera.lookRight(x * lookFactor);
        camera.lookUp(y * lookFactor);
    }

    // 鏡頭移動的速率基於鏡頭離地球的高度
    var cameraHeight = ellipsoid.cartesianToCartographic(camera.position).height;
    var moveRate = cameraHeight / 100.0;

    if (flags.moveForward) {
        camera.moveForward(moveRate);
    }
    if (flags.moveBackward) {
        camera.moveBackward(moveRate);
    }
    if (flags.moveUp) {
        camera.moveUp(moveRate);
    }
    if (flags.moveDown) {
        camera.moveDown(moveRate);
    }
    if (flags.moveLeft) {
        camera.moveLeft(moveRate);
    }
    if (flags.moveRight) {
        camera.moveRight(moveRate);
    }
});

這裏我們是把監聽事件加載clock的onTick上的,這是一個以毫秒爲單位的回調,完全可以保證我們的鏡頭移動的流暢

完整代碼如下

//相機設置
var viewer = new Cesium.Viewer("cesiumContainer");
var scene = viewer.scene;
var canvas = viewer.canvas;
canvas.setAttribute('tabindex', '0'); // 需要把焦點放在畫布上
canvas.onclick = function() {
    canvas.focus();
};
//這個橢球形就是地球了
var ellipsoid = viewer.scene.globe.ellipsoid;

// 禁止默認的事件
scene.screenSpaceCameraController.enableRotate = false;
scene.screenSpaceCameraController.enableTranslate = false;
scene.screenSpaceCameraController.enableZoom = false;
scene.screenSpaceCameraController.enableTilt = false;
scene.screenSpaceCameraController.enableLook = false;

//存儲鼠標位置的變量
var startMousePosition;
var mousePosition;

var flags = {
    //記錄是否在查看地圖,也就是記錄是否點擊了鼠標或鍵盤
    looking : false,
    //記錄鍵盤的前後上下左右
    moveForward : false,
    moveBackward : false,
    moveUp : false,
    moveDown : false,
    moveLeft : false,
    moveRight : false
};

//監聽用戶的輸入
var handler = new Cesium.ScreenSpaceEventHandler(canvas);
//當鼠標左鍵按下時執行(拿到鼠標按下時的位置)
handler.setInputAction(function(movement) {
    flags.looking = true;
    mousePosition = startMousePosition = Cesium.Cartesian3.clone(movement.position);
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
//當鼠標移動時執行(拿到鼠標擡起時的位置)
handler.setInputAction(function(movement) {
    mousePosition = movement.endPosition;
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
//當鼠標左鍵擡起時執行
handler.setInputAction(function(position) {
    flags.looking = false;
}, Cesium.ScreenSpaceEventType.LEFT_UP);

//判斷鍵盤的輸入
function getFlagForKeyCode(keyCode) {
    switch (keyCode) {
    case 'W'.charCodeAt(0):
        return 'moveUp';
    case 'S'.charCodeAt(0):
        return 'moveDown';
    case 'Q'.charCodeAt(0):
        return 'moveForward';
    case 'E'.charCodeAt(0):
        return 'moveBackward';
    case 'D'.charCodeAt(0):
        return 'moveRight';
    case 'A'.charCodeAt(0):
        return 'moveLeft';
    default:
        return undefined;
    }
}
//獲得鍵盤keydown事件
document.addEventListener('keydown', function(e) {
    var flagName = getFlagForKeyCode(e.keyCode);
    if (typeof flagName !== 'undefined') {
        flags[flagName] = true;
    }
}, false);
//獲得鍵盤keyup事件
document.addEventListener('keyup', function(e) {
    var flagName = getFlagForKeyCode(e.keyCode);
    if (typeof flagName !== 'undefined') {
        flags[flagName] = false;
    }
}, false);

//更新相機
viewer.clock.onTick.addEventListener(function(clock) {
    console.log("dida");
    var camera = viewer.camera;
    //當按下鼠標左鍵時
    if (flags.looking) {
        var width = canvas.clientWidth;
        var height = canvas.clientHeight;

        // 鼠標滑動的距離的x或y/網頁可見區域的寬或者高
        var x = (mousePosition.x - startMousePosition.x) / width;
        var y = -(mousePosition.y - startMousePosition.y) / height;
        //這就是決定相機移動速度的參數
        var lookFactor = 0.05;
        //相機移動
        camera.lookRight(x * lookFactor);
        camera.lookUp(y * lookFactor);
    }

    // 鏡頭移動的速度基於鏡頭離地球的高度
    var cameraHeight = ellipsoid.cartesianToCartographic(camera.position).height;
    var moveRate = cameraHeight / 100.0;

    if (flags.moveForward) {
        camera.moveForward(moveRate);
    }
    if (flags.moveBackward) {
        camera.moveBackward(moveRate);
    }
    if (flags.moveUp) {
        camera.moveUp(moveRate);
    }
    if (flags.moveDown) {
        camera.moveDown(moveRate);
    }
    if (flags.moveLeft) {
        camera.moveLeft(moveRate);
    }
    if (flags.moveRight) {
        camera.moveRight(moveRate);
    }
});

參考資料:官網教程官方API

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章