原文链接及内容

界面代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<style>
@import url(../templates/bucket.css);
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
<table class="infoPanel">
<tbody>
<tr>
<td>首先需要点击加载Cesium地球的主窗口</td>
</tr>
<tr>
<td>w键/s键 - 移动剪贴画 向北/向南</td>
</tr>
<tr>
<td>a键/d键 - 移动剪贴画 向西/向东</td>
</tr>
</tbody>
</table>
</div>

为了能够具体的演示示例如何实现的,我们分布展示效果:

  1. 首先,这里将Natural Earth II数据集作为底图层,并禁用底图层选择器:

内置的数据位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const viewer = new Cesium.Viewer("cesiumContainer", {
geocoder: false,
sceneModePicker: false,
homeButton: false,
navigationHelpButton: false,
navigationInstructionsInitiallyVisible: false,
fullscreenButton: false,
selectionIndicator: false,
skyBox: false,
timeline: false,
animation: false,
shouldAnimate: true,
//这里将Natural Earth II数据集作为底图层,并禁用底图层选择器。
baseLayerPicker: false,
baseLayer: Cesium.ImageryLayer.fromProviderAsync(
Cesium.TileMapServiceImageryProvider.fromUrl(
Cesium.buildModuleUrl("Assets/Textures/NaturalEarthII")
)
),
});
viewer.cesiumWidget.creditContainer.style.display = "none";

效果如下:

  1. 然后将焦点聚焦到渲染Cesium地球的画布上:
1
2
3
4
5
6
7
const canvas = viewer.canvas;
canvas.setAttribute("tabindex", "0"); // 需要将焦点聚焦到画布上
canvas.onclick = function () {
canvas.focus();
};

const scene = viewer.scene;
  1. 在上述影像图层中增加一个矩形切口:
1
2
3
4
5
6
7
8
9
10
11
12
13
const scene = viewer.scene;

const defaultImageryLayerCutout = Cesium.Rectangle.fromDegrees(
-90,
20,
-70,
40
);

const layers = viewer.imageryLayers;
const imageryBaseLayer = layers.get(0);

imageryBaseLayer.cutoutRectangle = defaultImageryLayerCutout;

效果如下:

影像图层增加一个矩形切口

  1. 然后再嵌入一个cesium logo图片:
1
2
3
4
5
6
7
8
9
10
// 在最底层的裁剪区域内嵌入 SingleTileImageryProvider
const logo = Cesium.ImageryLayer.fromProviderAsync(
Cesium.SingleTileImageryProvider.fromUrl(
"../images/Cesium_Logo_overlay.png",
{
rectangle: defaultImageryLayerCutout,
}
)
);
layers.add(logo);

效果如下:

  1. 然后再在以上图层上再添加一个“Earth at Night”图层,它在Ceisium Ion中的assetId为3812。然后在该图层增加一个比上述矩形大一圈的矩形切口。
1
2
3
4
5
6
7
8
9
10
/**
* 添加Earth at Night示例中(使用)的图层和"移动"剪切效果,
* 示例详见:https://gisnotes.github.io/posts/53e0a3f4/
*/
const earthAtNight = Cesium.ImageryLayer.fromProviderAsync(
Cesium.IonImageryProvider.fromAssetId(3812)
);
earthAtNight.cutoutRectangle = Cesium.Rectangle.fromDegrees(-100, 10, -60, 50);
earthAtNight.alpha = 0.9;
layers.add(earthAtNight);

效果如下:

  1. 最后,我们在clock.onTick增加一个监听器,实时监听键盘上的W、S、A、D四个按键,然后实时移动earthAtNight图层的矩形切口。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// "traveling" code
const flags = {
moveEast: false,
moveWest: false,
moveNorth: false,
moveSouth: false,
};

function getFlagForKeyCode(code) {
switch (code) {
case "KeyW":
return "moveNorth";
case "KeyS":
return "moveSouth";
case "KeyD":
return "moveEast";
case "KeyA":
return "moveWest";
default:
return undefined;
}
}

document.addEventListener(
"keydown",
function (e) {
const flagName = getFlagForKeyCode(e.code);
if (typeof flagName !== "undefined") {
flags[flagName] = true;
}
},
false
);

document.addEventListener(
"keyup",
function (e) {
const flagName = getFlagForKeyCode(e.code);
if (typeof flagName !== "undefined") {
flags[flagName] = false;
}
},
false
);

const moveIncrement = 0.05;
viewer.clock.onTick.addEventListener(function (clock) {
const travelingRectangle = earthAtNight.cutoutRectangle;
if (
flags.moveNorth &&
travelingRectangle.north + moveIncrement < Cesium.Math.PI_OVER_TWO
) {
travelingRectangle.north += moveIncrement;
travelingRectangle.south += moveIncrement;
}
if (
flags.moveSouth &&
travelingRectangle.south - moveIncrement > -Cesium.Math.PI_OVER_TWO
) {
travelingRectangle.north -= moveIncrement;
travelingRectangle.south -= moveIncrement;
}
if (flags.moveEast) {
travelingRectangle.east += moveIncrement;
travelingRectangle.west += moveIncrement;
}
if (flags.moveWest) {
travelingRectangle.east -= moveIncrement;
travelingRectangle.west -= moveIncrement;
}
travelingRectangle.east = wrapLongitude(travelingRectangle.east);
travelingRectangle.west = wrapLongitude(travelingRectangle.west);
});

function wrapLongitude(value) {
if (value < -Cesium.Math.PI) {
return value + Cesium.Math.TWO_PI;
}
if (value > Cesium.Math.PI) {
return value - Cesium.Math.TWO_PI;
}
return value;
}

效果如下: