Cesium 视频投射
话不多说,直接上代码
var options = {
horizontalViewAngle: 60,
verticalViewAngle: 40,
video: "video_dom",
viewPosition: Cesium.Cartesian3.fromDegrees(85.788705, 45.161394, 900),
viewPositionEnd: Cesium.Cartesian3.fromDegrees(85.788705, 45.167394, 500),
};
v = new video(viewer, options);
v.drawVideo();
video_dom.play();
var videos = [];
var video_dom;
var getCurrentMousePosition = function (scene, position, noPickEntity) {
var cartesian;
var pickedObject = scene.pick(position);
if (scene.pickPositionSupported && Cesium.defined(pickedObject)) {
var entity = pickedObject.id;
if (noPickEntity == null || (noPickEntity && entity !== noPickEntity)) {
var cartesian = scene.pickPosition(position);
if (Cesium.defined(cartesian)) {
var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
var height = cartographic.height;
if (height >= 0) return cartesian;
if (!Cesium.defined(pickedObject.id) && height >= -500)
return cartesian;
}
}
}
if (scene.mode === Cesium.SceneMode.SCENE3D) {
var pickRay = scene.camera.getPickRay(position);
cartesian = scene.globe.pick(pickRay, scene);
} else {
cartesian = scene.camera.pickEllipsoid(position, scene.globe.ellipsoid);
}
return cartesian;
}
class video {
constructor(viewer, config) {
this.viewer = viewer;
this.config = config;
}
creat() {
var viewer = this.viewer;
var config = this.config;
var videoElement = config.videoElement;
var positions = config.positions;
var clampToGround = config.clampToGround;
if (clampToGround) {
viewer.entities.add({
nam: "video",
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray(positions),
material: videoElement
}
});
} else {
viewer.entities.add({
nam: "video",
polygon: {
hierarchy: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights(positions)
},
material: videoElement,
perPositionHeight: true,
outline: true
}
});
}
}
clearAll() {
var dd = viewer.entities._entities._array;
for (let index = 0; index < dd.length; index++) {
if (dd[index]._nam = "video") {
viewer.entities.remove(dd[index])
index--;
}
}
videos.forEach((v) => {
v.destroy();
})
}
change(object) {
var _this = this;
for (const key in object) {
const element = object[key];
_this.lightCamera.frustum[key] = element;
_this.clear()
_this.drawFrustumOutline();
}
}
drawVideo() {
let _self = this;
var options = this.config;
this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.horizontalViewAngle = options.horizontalViewAngle || 60.0;
this.verticalViewAngle = options.verticalViewAngle || 40.0;
video_dom = document.getElementById(options.video);
this.options = options;
this.posArray = [];
this.state = "PREPARE";
if (options.viewPosition && options.viewPositionEnd) {
_self.viewPosition = options.viewPosition;
_self.viewPositionEnd = options.viewPositionEnd;
_self.viewDistance = Cesium.Cartesian3.distance(_self.viewPosition, _self.viewPositionEnd);
_self.viewHeading = getHeading(_self.viewPosition, _self.viewPositionEnd);
_self.viewPitch = getPitch(_self.viewPosition, _self.viewPositionEnd);
_self.createLightCamera();
} else {
this.action();
}
}
action() {
let _self = this;
_self.handler.setInputAction(function (movement) {
var cartesian = getCurrentMousePosition(_self.viewer.scene, movement.position);
if (!cartesian) {
return;
}
if (_self.posArray.length == 0) {
_self.posArray.push(cartesian);
_self.state = "OPERATING";
} else if (_self.posArray.length == 1) {
_self.viewPosition = _self.posArray[0];
_self.viewPositionEnd = cartesian;
_self.viewDistance = Cesium.Cartesian3.distance(_self.viewPosition, _self.viewPositionEnd);
_self.viewHeading = getHeading(_self.viewPosition, _self.viewPositionEnd);
_self.viewPitch = getPitch(_self.viewPosition, _self.viewPositionEnd);
_self.state = "END";
_self.handler.destroy();
_self.handler = null;
_self.createLightCamera();
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
createLightCamera() {
this.lightCamera = new Cesium.Camera(this.viewer.scene);
this.lightCamera.position = this.viewPosition;
this.lightCamera.frustum.near = this.viewDistance * 0.0001;
this.lightCamera.frustum.far = this.viewDistance;
const hr = Cesium.Math.toRadians(this.horizontalViewAngle);
const vr = Cesium.Math.toRadians(this.verticalViewAngle);
const aspectRatio =
(this.viewDistance * Math.tan(hr / 2) * 2) /
(this.viewDistance * Math.tan(vr / 2) * 2);
this.lightCamera.frustum.aspectRatio = aspectRatio;
if (hr > vr) {
this.lightCamera.frustum.fov = hr;
} else {
this.lightCamera.frustum.fov = vr;
}
this.lightCamera.setView({
destination: this.viewPosition,
orientation: {
heading: Cesium.Math.toRadians(this.viewHeading || 0),
pitch: Cesium.Math.toRadians(this.viewPitch || 0),
roll: 0
}
});
this.drawFrustumOutline();
}
drawFrustumOutline() {
const scratchRight = new Cesium.Cartesian3();
const scratchRotation = new Cesium.Matrix3();
const scratchOrientation = new Cesium.Quaternion();
const position = this.lightCamera.positionWC;
const direction = this.lightCamera.directionWC;
const up = this.lightCamera.upWC;
let right = this.lightCamera.rightWC;
right = Cesium.Cartesian3.negate(right, scratchRight);
let rotation = scratchRotation;
Cesium.Matrix3.setColumn(rotation, 0, right, rotation);
Cesium.Matrix3.setColumn(rotation, 1, up, rotation);
Cesium.Matrix3.setColumn(rotation, 2, direction, rotation);
let orientation = Cesium.Quaternion.fromRotationMatrix(rotation, scratchOrientation);
var newObj = _.cloneDeep(this.lightCamera.frustum);
newObj.near = newObj.far - 0.01;
var videoGeometryInstance1 = new Cesium.GeometryInstance({
geometry: new Cesium.FrustumGeometry({
frustum: newObj,
origin: this.viewPosition,
orientation: orientation
})
});
var p1s = new Cesium.Primitive({
geometryInstances: [videoGeometryInstance1],
appearance: createAppearance()
})
this.viewer.scene.primitives.add(
p1s
);
var videoGeometryInstance2 = new Cesium.GeometryInstance({
geometry: new Cesium.FrustumOutlineGeometry({
frustum: this.lightCamera.frustum,
origin: this.viewPosition,
orientation: orientation
}),
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.BLUE)
}
});
var p2s = new Cesium.Primitive({
geometryInstances: [videoGeometryInstance2],
appearance: new Cesium.PerInstanceColorAppearance(
{
flat: true,
}
)
})
this.viewer.scene.primitives.add(
p2s
);
this.FrustumGeometry = p1s;
this.FrustumOutlineGeometry = p2s;
videos.push(p1s)
videos.push(p2s)
}
clear() {
this.FrustumGeometry.destroy()
this.FrustumOutlineGeometry.destroy()
}
}
function getHeading(fromPosition, toPosition) {
let finalPosition = new Cesium.Cartesian3();
let matrix4 = Cesium.Transforms.eastNorthUpToFixedFrame(fromPosition);
Cesium.Matrix4.inverse(matrix4, matrix4);
Cesium.Matrix4.multiplyByPoint(matrix4, toPosition, finalPosition);
Cesium.Cartesian3.normalize(finalPosition, finalPosition);
return Cesium.Math.toDegrees(Math.atan2(finalPosition.x, finalPosition.y));
}
function getPitch(fromPosition, toPosition) {
let finalPosition = new Cesium.Cartesian3();
let matrix4 = Cesium.Transforms.eastNorthUpToFixedFrame(fromPosition);
Cesium.Matrix4.inverse(matrix4, matrix4);
Cesium.Matrix4.multiplyByPoint(matrix4, toPosition, finalPosition);
Cesium.Cartesian3.normalize(finalPosition, finalPosition);
return Cesium.Math.toDegrees(Math.asin(finalPosition.z));
}
html 部分
<script src="./video.js"></script>
<script src="./turf.min.js"></script>
<script src="./lodash.min.js"></script>
<video id="video_dom" preload="auto" autoPlay loop>
<source src="./video.mp4" type="video/mp4" />
</video>
``
### 效果图
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/b09f790a49e74d1d87479e31957aa468.png#pic_center)