Billboard 是 Cesium 中最常用的实体类型之一,用于在地球表面显示图标、图片或文本标签。以下是 Billboard 属性的完整详解和示例。
| 属性分类 | 属性名称 (Type) | 默认值 | 描述 | |
|---|---|---|---|---|
| 核心样式 | show (Property | boolean) | true | 是否显示该广告牌12。 |
image (Property | string) | 广告牌图像的 URI,或 Canvas 的 ID12。支持 Data URI、Blob URL 等。 | ||
color (Property | Color) | Color.WHITE | 与图像相乘的颜色1。可用于着色或设置透明度。 | |
scale (Property | number) | 1.0 | 应用于图像大小的统一缩放比例1。 | |
rotation (Property | number) | 0.0 | 旋转角度(弧度) ,逆时针方向12。 | |
alignedAxis (Property | Cartesian3) | Cartesian3.ZERO | 指定的旋转轴(单位向量)。默认为零向量,表示绕屏幕法线旋转12。 | |
| 尺寸控制 | width (Property | number) | 广告牌的宽度(像素) ,覆盖图像原始宽度12。 | |
height (Property | number) | 广告牌的高度(像素) ,覆盖图像原始高度12。 | ||
sizeInMeters (Property | boolean) | false | 广告牌大小是否以米为单位(而非像素)1。 | |
| 位置偏移 | pixelOffset (Property | Cartesian2) | Cartesian2.ZERO | 屏幕空间的像素偏移12。原点为广告牌初始位置,X向右为正,Y向下为正。 |
eyeOffset (Property | Cartesian3) | Cartesian3.ZERO | 眼睛坐标(视图空间)的偏移(米) 12。相对于广告牌附着点。 | |
| 对齐方式 | horizontalOrigin (Property | HorizontalOrigin) | HorizontalOrigin.CENTER | 水平对齐原点12。可选 LEFT, CENTER, RIGHT。 |
verticalOrigin (Property | VerticalOrigin) | VerticalOrigin.CENTER | 垂直对齐原点12。可选 TOP, CENTER, BOTTOM, BASELINE。 | |
| 高级效果 | scaleByDistance (Property | NearFarScalar) | 根据与相机的距离缩放广告牌12。 | |
translucencyByDistance (Property | NearFarScalar) | 根据与相机的距离改变广告牌透明度12。 | ||
pixelOffsetScaleByDistance (Property | NearFarScalar) | 根据与相机的距离缩放 pixelOffset1。 | ||
imageSubRegion (Property | BoundingRectangle) | 定义使用图像的特定区域(像素单位,从左下角开始)1。 | ||
| 显示控制 | distanceDisplayCondition (Property | DistanceDisplayCondition) | 指定广告牌可见的距离范围12。 | |
disableDepthTestDistance (Property | number) | 0.0 | 禁用深度测试的距离12。例如,设置为 Number.POSITIVE_INFINITY 可防止被地形或其他实体遮挡。 | |
heightReference (Property | HeightReference) | HeightReference.NONE | 高度参考1。可选 NONE(绝对高度), CLAMP_TO_GROUND(贴地), RELATIVE_TO_GROUND(相对地面高度)。 |
基本属性
1. 核心显示属性
const entity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(116.404, 39.915),
billboard: {
// 必需属性:图片URL或Canvas
image: 'path/to/icon.png',
// 尺寸控制
width: 50, // 宽度(像素)
height: 50, // 高度(像素)
scale: 1.0, // 整体缩放比例
scaleByDistance: new Cesium.NearFarScalar(1.5e2, 2.0, 1.5e7, 0.5),
// 颜色和透明度
color: Cesium.Color.WHITE,
eyeOffset: new Cesium.Cartesian3(0.0, 0.0, 0.0),
// 显示控制
show: true,
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10000),
// 对齐和位置
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
pixelOffset: new Cesium.Cartesian2(0, 0),
// 旋转
rotation: 0, // 弧度
alignedAxis: Cesium.Cartesian3.ZERO,
// 大小模式
sizeInMeters: false,
heightReference: Cesium.HeightReference.NONE,
// 透明度裁剪
translucencyByDistance: new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.2),
pixelOffsetScaleByDistance: new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.0),
// 禁用深度检测
disableDepthTestDistance: 0.0
}
});
详细属性说明
1. 图片相关属性
billboard: {
// 图片源(支持URL、Canvas、DataURL)
image: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGNpcmNsZSBjeD0iMTYiIGN5PSIxNiIgcj0iMTQiIGZpbGw9IiNGRjAwMDAiLz4KPC9zdmc+',
// 或者使用Canvas
image: createCustomCanvas(),
// 图片子区域(sprite sheet)
imageSubRegion: new Cesium.BoundingRectangle(0, 0, 32, 32)
}
function createCustomCanvas() {
const canvas = document.createElement('canvas');
canvas.width = 64;
canvas.height = 64;
const ctx = canvas.getContext('2d');
// 绘制自定义图形
ctx.fillStyle = '#ff0000';
ctx.beginPath();
ctx.arc(32, 32, 30, 0, Math.PI * 2);
ctx.fill();
return canvas;
}
2. 尺寸和缩放控制
billboard: {
image: 'icon.png',
// 固定尺寸
width: 40,
height: 40,
// 动态缩放(基于距离)
scaleByDistance: new Cesium.NearFarScalar(
100, // 近距离(米)
2.0, // 近距离缩放
5000, // 远距离(米)
0.5 // 远距离缩放
),
// 基于眼睛距离的透明度变化
translucencyByDistance: new Cesium.NearFarScalar(
100, // 近距离
1.0, // 完全不透明
5000, // 远距离
0.3 // 30%透明度
),
// 物理尺寸模式(true时width/height单位为米)
sizeInMeters: false
}
3. 位置和对齐
billboard: {
image: 'icon.png',
// 垂直对齐方式
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // TOP, CENTER, BOTTOM
// 水平对齐方式
horizontalOrigin: Cesium.HorizontalOrigin.CENTER, // LEFT, CENTER, RIGHT
// 像素偏移(屏幕坐标)
pixelOffset: new Cesium.Cartesian2(0, -20), // 向下偏移20像素
// 基于距离的像素偏移缩放
pixelOffsetScaleByDistance: new Cesium.NearFarScalar(
100, 1.0, // 近距离正常偏移
5000, 0.5 // 远距离偏移减半
),
// 眼睛偏移(世界坐标)
eyeOffset: new Cesium.Cartesian3(0, 0, 100), // 沿Z轴偏移100米
}
4. 旋转和方向
billboard: {
image: 'arrow.png',
// 旋转角度(弧度)
rotation: Cesium.Math.toRadians(45), // 旋转45度
// 对齐轴(3D旋转)
alignedAxis: Cesium.Cartesian3.UNIT_Z, // 围绕Z轴旋转
// 朝向相机(billboard始终面向相机)
// 默认就是朝向相机的,alignedAxis用于特殊旋转需求
}
5. 显示控制
billboard: {
image: 'icon.png',
// 显示/隐藏
show: true,
// 距离显示条件
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
100, // 最小距离(米)
5000 // 最大距离(米)
),
// 高度参考
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, // NONE, CLAMP_TO_GROUND, RELATIVE_TO_GROUND
// 禁用深度测试距离
disableDepthTestDistance: 1000.0 // 1000米内禁用深度测试
}
完整示例
1. 创建自定义标记
function createCustomBillboard(viewer, lon, lat, options = {}) {
const {
image = 'default-icon.png',
color = Cesium.Color.WHITE,
scale = 1.0,
label = '',
verticalOffset = 0
} = options;
return viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(lon, lat),
billboard: {
image: image,
width: 32,
height: 32,
scale: scale,
color: color,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, verticalOffset),
scaleByDistance: new Cesium.NearFarScalar(100, 1.5, 2000, 0.8)
},
label: {
text: label,
font: '14pt monospace',
pixelOffset: new Cesium.Cartesian2(0, -40),
fillColor: Cesium.Color.WHITE,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE
}
});
}
// 使用示例
const marker = createCustomBillboard(viewer, 116.404, 39.915, {
image: 'custom-marker.png',
color: Cesium.Color.RED.withAlpha(0.8),
scale: 1.2,
label: '北京',
verticalOffset: -20
});
2. 动态更新 Billboard
// 获取entity引用
const entity = viewer.entities.add({/*...*/});
// 动态更新属性
entity.billboard.image = 'new-icon.png';
entity.billboard.scale = 2.0;
entity.billboard.color = Cesium.Color.BLUE;
entity.billboard.show = false; // 隐藏
// 使用回调函数创建动态内容
entity.billboard.image = new Cesium.CallbackProperty(function(time, result) {
// 根据时间或其他条件返回不同的图片
const hour = new Date().getHours();
return hour < 12 ? 'day-icon.png' : 'night-icon.png';
}, false);
3. 性能优化示例
// 批量创建billboards
const positions = [
{ lon: 116.404, lat: 39.915, type: 'type1' },
{ lon: 121.473, lat: 31.230, type: 'type2' },
// ...更多位置
];
const billboards = positions.map(pos => {
return viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(pos.lon, pos.lat),
billboard: {
image: getIconForType(pos.type),
width: 24,
height: 24,
scaleByDistance: new Cesium.NearFarScalar(100, 1.0, 5000, 0.6),
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10000)
}
});
});
function getIconForType(type) {
const icons = {
type1: 'red-dot.png',
type2: 'blue-dot.png',
type3: 'green-dot.png'
};
return icons[type] || 'default.png';
}
常见问题解决方案
1. 图片跨域问题
billboard: {
image: new Cesium.Resource({
url: 'https://other-domain.com/icon.png',
headers: {
'Accept': 'image/*'
}
})
}
2. 图片加载失败处理
const billboard = entity.billboard;
billboard.image.addEventListener(Cesium.ImageryState.FAILED, function() {
console.error('图片加载失败');
billboard.image = 'fallback-icon.png';
});
3. 性能优化建议
// 对于大量billboard,使用相同的image可以共享纹理
const sharedImage = 'shared-icon.png';
positions.forEach(pos => {
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(pos.lon, pos.lat),
billboard: {
image: sharedImage, // 共享纹理
width: 16,
height: 16
}
});
});