Cesium 视频投射

Cesium 视频投射

话不多说,直接上代码

javascript 复制代码
        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();
        // 暂停
        // video_dom.pause();

        // 清除
        // new video(viewer, {}).clearAll();
javascript 复制代码
// video.js
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,
                    // translucent : false
                }
            )
        })
        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)
相关推荐
Watermelo6178 分钟前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
m0_7482489410 分钟前
HTML5系列(11)-- Web 无障碍开发指南
前端·html·html5
m0_7482356121 分钟前
从零开始学前端之HTML(三)
前端·html
一个处女座的程序猿O(∩_∩)O2 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
hackeroink5 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者7 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-7 小时前
验证码机制
前端·后端
燃先生._.8 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖9 小时前
[react]searchParams转普通对象
开发语言·前端·javascript