Appearance
VideoMaterialProperty 视频贴面材质
将视频画面实时贴到多边形表面的材质,基于 Cesium 原生
'Image'材质类型封装。视频帧由渲染层逐帧copyFrom驱动,无需注册自定义 GLSL;贴面方向(stRotation)由 polygon 图形属性承载,与材质解耦。
能力定位
VideoMaterialProperty 适合:
- 视频融合展示:监控视频 / 实时流贴到地表多边形,模拟大屏视频融合;
- 动态纹理面:把 canvas 流(
captureStream)、摄像头或视频文件作为多边形表面; - 视频贴面旋转:配合
polygon.stRotation旋转贴面方向,对齐实际地理朝向。
与 WaterMaterialProperty(GLSL 程序化水面)不同,本材质消费 Cesium 原生 'Image' fabric(HTMLVideoElement 分支),无需宿主注册任何自定义材质。
构造函数
ts
constructor(options: VideoMaterialPropertyOptions)ts
interface VideoMaterialPropertyOptions {
videoElement?: HTMLVideoElement; // 已有视频元素(优先),与 videoUrl 二选一
videoUrl?: string; // 视频地址,内部创建 <video> 加载;与 videoElement 二选一
repeat?: Cartesian2 | Property; // 纹理平铺,默认 (1,1)
color?: Color | Property; // 叠加颜色,默认 (1,1,1,1) 原色
}| 参数 | 类型 | 描述 |
|---|---|---|
videoElement | HTMLVideoElement | 复用已创建的视频元素(videoUrl 与 videoElement 必须提供其一,且只能其一) |
videoUrl | string | 视频地址,内部创建 <video> 并设置 autoplay / muted / loop / crossOrigin='anonymous' |
repeat | Cartesian2 | Property | 纹理平铺次数,默认 (1, 1) |
color | Color | Property | 与视频画面叠加的颜色,默认 (1, 1, 1, 1) |
repeat / color 支持 CallbackProperty 动态驱动。
材质属性接口
VideoMaterialProperty 实现 Cesium MaterialProperty 契约,可直接赋给实体材质:
ts
getType(time): string // 返回 'Image'(Cesium 原生类型,无需注册)
getValue(time, result?): object // 返回 { image, repeat, color } uniforms
isConstant: boolean // repeat/color 均为常量时为 true(视频帧恒为动态)
definitionChanged: Event // 属性赋值时触发
equals(other): boolean // 比较视频源 + repeat/color 属性视频帧动态性:
isConstant只反映repeat/color是否常量。视频画面本身每帧变化, 由 Cesium 渲染层在HTMLVideoElement.readyState >= 2时逐帧texture.copyFrom驱动, 因此材质永远"动态",但不影响isConstant语义(纹理内容不参与常量判定)。
基础示例(videoUrl)
ts
import { VideoMaterialProperty } from '@nexa/gis-cesium'
import { Cartesian3, CallbackProperty, Math as CesiumMath } from 'cesium'
const material = new VideoMaterialProperty({
videoUrl: '/static/videos/camera.mp4',
})
const entity = viewer.entities.add({
polygon: {
hierarchy: Cartesian3.fromDegreesArray([
114.225, 30.605,
114.248, 30.605,
114.248, 30.618,
114.225, 30.618,
]),
perPositionHeight: true,
material,
},
})
// 贴面旋转:stRotation 是 polygon 属性(弧度),与材质解耦
entity.polygon.stRotation = new CallbackProperty(
() => CesiumMath.toRadians(180),
false
)进阶示例(videoElement + canvas 实时流)
零资产演示:用 canvas.captureStream(30) 程序化生成动态"监控画面",贴到地表多边形。
ts
import { VideoMaterialProperty } from '@nexa/gis-cesium'
import { Cartesian3 } from 'cesium'
// 1. 程序化画面(零外部资产)
const canvas = document.createElement('canvas')
canvas.width = 320
canvas.height = 180
const ctx = canvas.getContext('2d')
function drawFrame () {
ctx.fillStyle = 'hsl(210, 80%, 45%)'
ctx.fillRect(0, 0, 320, 180)
ctx.fillStyle = 'rgba(255, 220, 120, 0.9)'
ctx.beginPath()
ctx.arc(120, 80, 14, 0, Math.PI * 2)
ctx.fill()
}
drawFrame()
const timer = setInterval(drawFrame, 1000 / 30)
// 2. canvas 流 → video 元素 → 材质
const video = document.createElement('video')
video.muted = true
video.loop = true
video.srcObject = canvas.captureStream(30)
video.play()
const material = new VideoMaterialProperty({ videoElement: video })
// 3. 贴到地表多边形
viewer.entities.add({
polygon: {
hierarchy: Cartesian3.fromDegreesArray([
114.225, 30.605,
114.248, 30.605,
114.248, 30.618,
114.225, 30.618,
]),
perPositionHeight: true,
material,
},
})实现与性能说明
- 原生 Image 材质:
getType()返回'Image',直接消费 Cesium 内置'Image'fabric 的HTMLVideoElement分支,无需registerAll注册 GLSL; - 帧驱动:视频纹理由 Cesium 渲染层逐帧
Texture.copyFrom更新,readyState >= 2后才开始采样(不足时材质保持上一帧/空纹理); videoUrl内部创建:自动设置autoplay / muted / loop / crossOrigin='anonymous', 避免跨域纹理污染(SecurityError);- stRotation 解耦:贴面旋转是 polygon 图形属性而非材质 uniform,材质保持纯净 (
image / repeat / color三件套),旋转由调用方经entity.polygon.stRotation设置; - 资源所有权:材质本身无生命周期;
videoUrl创建的视频元素与实体由创建方负责清理。
清理责任
- 复用外部
videoElement时,材质不暂停/移除该元素,所有权在调用方; videoUrl内部创建的视频元素随材质一起由调用方管理(暂停、srcObject = null);- 引用材质的实体由创建方移除:
ts
viewer.entities.remove(entity)与原生 Cesium API 的组合方式
- 可直接赋给
entity.polygon.material/entity.ellipsoid.material等实体材质; - 等价于
entity.polygon.material = new Cesium.ImageMaterialProperty({ image: videoEl }), 但统一了getValue / equals / definitionChanged契约,可与其他MaterialProperty一样参与属性生命周期管理; - 与
perPositionHeight结合可贴合真实地形高程的视频面。
Cesium 版本限制
- 需要 Cesium
'Image'fabric 的HTMLVideoElement分支(readyState >= 2采样); - 已验证目标版本:Cesium 1.133.1。