Cesium 视频投射

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();
        // 暂停
        // video_dom.pause();

        // 清除
        // new video(viewer, {}).clearAll();
// 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)

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BJ-Giser

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值