原文链接及内容

效果如下视频所示:

示例代码如下:

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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
<template>
<CesiumMap @viewerCreated="viewerCreated" />
<el-select
class="select"
v-model="styleVal"
placeholder="空"
@change="handleStyleChange">
<el-option
v-for="item in styles"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select>
</template>

<script setup>
/**
* 示例介绍:在场景中添加图片或标记形式的广告牌(Billboards)
*/

//#region --------------------- 定义变量----------------
let viewer, scene;

const styleVal = ref("Add billboard");

/**
* @type {Array} 样式列表
*/
const styles = [
{ value: "Add billboard", label: "添加广告牌" },
{
value: "Set billboard properties at creation",
label: "在创建广告牌时设置其属性",
},
{ value: "Change billboard properties", label: "更改广告牌属性" },
{ value: "Size billboard in meters", label: "广告牌尺寸(以米为单位)" },
{ value: "Add multiple billboards", label: "添加多个广告牌" },
{ value: "Scale by viewer distance", label: "根据viewer距离缩放" },
{ value: "Fade by viewer distance", label: "根据viewer距离淡出" },
{ value: "Offset by viewer distance", label: "根据viewer距离偏移" },
{ value: "Add marker billboards", label: "添加标记广告牌" },
{
value: "Disable the depth test when clamped to ground",
label: "当贴地时禁用深度测试",
},
];
//#endregion

function viewerCreated(v) {
viewer = v;
scene = viewer.scene;
handleStyleChange(styleVal.value);
}

//#region --------------------- 方法区域----------------

function handleStyleChange(value) {
reset();
switch (value) {
case "Add billboard":
addBillboard();
break;
case "Set billboard properties at creation":
setBillboardProperties();
break;
case "Change billboard properties":
changeBillboardProperties();
break;
case "Size billboard in meters":
sizeBillboardInMeters();
break;
case "Add multiple billboards":
addMultipleBillboards();
break;
case "Scale by viewer distance":
scaleByDistance();
break;
case "Fade by viewer distance":
fadeByDistance();
break;
case "Offset by viewer distance":
offsetByDistance();
break;
case "Add marker billboards":
addMarkerBillboards();
break;
case "Disable the depth test when clamped to ground":
disableDepthTest();
break;
default:
break;
}
}

function addBillboard() {
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(104.355, 28.705),
billboard: {
image: "../images/Cesium_Logo_overlay.png",
},
});
}

function setBillboardProperties() {
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(104.355, 28.705),
billboard: {
image: "../images/Cesium_Logo_overlay.png", // default: undefined
show: true, // default
pixelOffset: new Cesium.Cartesian2(0, -50), // default: (0, 0)
eyeOffset: new Cesium.Cartesian3(0.0, 0.0, 0.0), // default
horizontalOrigin: Cesium.HorizontalOrigin.CENTER, // default
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // default: CENTER
scale: 2.0, // default: 1.0
color: Cesium.Color.LIME, // default: WHITE
rotation: Cesium.Math.PI_OVER_FOUR, // default: 0.0,这里是逆时针旋转45度
alignedAxis: Cesium.Cartesian3.ZERO, // default
width: 100, // default: undefined,宽度,单位为pixel
height: 25, // default: undefined,高度,单位为pixel
},
});
}

function changeBillboardProperties() {
const entity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(104.355, 28.705, 300000.0),
billboard: {
image: "../images/Cesium_Logo_overlay.png",
},
});

const billboard = entity.billboard;
billboard.scale = 3.0;
billboard.color = Cesium.Color.WHITE.withAlpha(0.25);
}

function sizeBillboardInMeters() {
const entity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(104.355, 28.705),
billboard: {
image: "../images/Cesium_Logo_overlay.png",
sizeInMeters: true,
},
});

viewer.zoomTo(entity);
}

function addMultipleBillboards() {
const logoUrl = "../images/Cesium_Logo_overlay.png";
const facilityUrl = "../images/facility.gif";

viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(104.355, 28.705),
billboard: {
image: logoUrl,
},
});
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(99.5, 35.14),
billboard: {
image: facilityUrl,
},
});
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(109.12, 25.46),
billboard: {
image: facilityUrl,
},
});
}

function scaleByDistance() {
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(104.355, 28.705),
billboard: {
image: "../images/facility.gif",
scaleByDistance: new Cesium.NearFarScalar(1.5e2, 2.0, 1.5e7, 0.5),
},
});
}

function fadeByDistance() {
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(104.355, 28.705),
billboard: {
image: "../images/Cesium_Logo_overlay.png",
//Cesium.NearFarScalar(near, nearValue, far, farValue)
translucencyByDistance: new Cesium.NearFarScalar(1.5e2, 2.0, 1.5e7, 0.5),
},
});
}

function offsetByDistance() {
Promise.all([
Cesium.Resource.fetchImage("../images/Cesium_Logo_overlay.png"),
Cesium.Resource.fetchImage("../images/facility.gif"),
]).then(function (images) {
// 当viewer放大接近设施广告牌时,将 CesiumLogo 广告牌的 pixelOffset 增加至该高度
const facilityHeight = images[1].height;

// 并置(合并)广告牌,随着viewer靠近而分开
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(104.355, 28.705),
billboard: {
image: images[1],
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
},
});
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(104.355, 28.705),
billboard: {
image: images[0],
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0.0, -facilityHeight),
pixelOffsetScaleByDistance: new Cesium.NearFarScalar(
1.0e3,
1.0,
1.5e6,
0.0
),
translucencyByDistance: new Cesium.NearFarScalar(
1.0e3,
1.0,
1.5e6,
0.1
),
},
});
});
}

function addMarkerBillboards() {
// 基于图集中的上述图像添加多个广告牌。
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(104.355, 28.705),
billboard: {
image: "../images/whiteShapes.png",
imageSubRegion: new Cesium.BoundingRectangle(49, 43, 18, 18),
color: Cesium.Color.LIME,
},
});
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(108.0, 39.0),
billboard: {
image: "../images/whiteShapes.png",
imageSubRegion: new Cesium.BoundingRectangle(61, 23, 18, 18),
color: new Cesium.Color(0, 0.5, 1.0, 1.0),
},
});
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(100.0, 41.0),
billboard: {
image: "../images/whiteShapes.png",
imageSubRegion: new Cesium.BoundingRectangle(67, 80, 14, 14),
color: new Cesium.Color(0.5, 0.9, 1.0, 1.0),
},
});
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(93.0, 37.0),
billboard: {
image: "../images/whiteShapes.png",
imageSubRegion: new Cesium.BoundingRectangle(27, 103, 22, 22),
color: Cesium.Color.RED,
},
});
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(107.0, 35.0),
billboard: {
image: "../images/whiteShapes.png",
imageSubRegion: new Cesium.BoundingRectangle(105, 105, 18, 18),
color: Cesium.Color.YELLOW,
},
});
}

async function disableDepthTest() {
viewer.scene.globe.depthTestAgainstTerrain = true;

try {
const worldTerrainProvider = await Cesium.createWorldTerrainAsync();

// 若在此期间已选择其他选项,则提前返回
if (!viewer.scene.globe.depthTestAgainstTerrain) {
return;
}

viewer.terrainProvider = worldTerrainProvider;
} catch (error) {
window.alert(`Failed to load terrain. ${error}`);
}

viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-122.1958, 46.1915),
billboard: {
image: "../images/facility.gif",
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
/**
* 属性值设置为:Number.POSITIVE_INFINITY,即无限大,也就是不使用深度测试的意思。
*/
disableDepthTestDistance: Number.POSITIVE_INFINITY,
},
});
viewer.scene.camera.setView({
destination: new Cesium.Cartesian3(
-2357576.243142461,
-3744417.5604860787,
4581807.855903771
),
orientation: new Cesium.HeadingPitchRoll(
5.9920811504170475,
-0.6032820429886212,
6.28201303164098
),
});
}

async function reset() {
viewer.camera.flyHome(0);
viewer.entities.removeAll();
viewer.scene.terrainProvider = new Cesium.EllipsoidTerrainProvider();
viewer.scene.globe.depthTestAgainstTerrain = false;
}
//#endregion
</script>

<style lang="scss" scoped>
.select {
position: absolute;
top: 20px;
right: 20px;
width: 240px;
}
</style>

BillboardGraphics属性

  1. pixelOffset: 获取或设置指定在屏幕空间中从该billboard原点偏移的像素偏移属性。屏幕空间原点是画布的左上角; x 从左到右增加, y 从上到下增加。具体看官方文档的解释,官方用图示解释的,清晰易懂。

pixelOffset属性

  1. eyeOffset: 获取或设置 Cartesian3 属性,指定billboard在眼睛坐标中的偏移量。

eyeOffset属性

  1. horizontalOrigin:获取或设置指定HorizontalOrigin的 Property,而它的属性如下图所示:

HorizontalOrigin属性

  1. VerticalOrigin: 具体如下图所示:

VerticalOrigin属性

  1. scale: 缩放比例,具体如下图所示:

scale属性

  1. alignedAxis: 获取或设置Cartesian3属性,指定固定框架中的单位矢量旋转轴。设置为Cartesian3.ZERO(该值也是默认值)时,旋转从屏幕顶部开始。而rotation属性则和该属性有关,rotation属性(默认值为0)表示:获取或设置指定图像从alignedAxis逆时针旋转的数值属性。

  2. sizeInMeters: 获取或设置布尔属性,指定此广告牌的大小是否以米为单位

  3. translucencyByDistance: 根据与摄像机的距离指定公告板的半透明性。

  4. translucencyByDistance: 根据与摄像机的距离指定公告板的半透明性。

  5. imageSubRegion: 获取或设置指定 BoundingRectangle。定义要用于公告板的图像的子区域,而不是整个图像,以从左下角开始的像素为单位。具体如下图所示:

类似“雪碧图”(Sprite)技术,可复用单张图片中的多个图标。

  1. heightReference: 设置HeightReference属性,如下图所示;

HeightReference属性

  1. disableDepthTestDistance: 具体看下图官方对该属性的介绍。

disableDepthTestDistance属性