uni-app render获取video DOM异常

发布于 1周前 作者 bupafengyu 来自 Uni-App

uni-app render获取video DOM异常

开发环境 版本号 项目创建方式
Windows 22H2 HBuilderX

产品分类:uniapp/App

PC开发环境操作系统:Windows

HBuilderX类型:正式

HBuilderX版本号:3.98

手机系统:Android

手机系统版本号:Android 11

手机厂商:vivo

手机机型:IQOO NEO 855竞速版

页面类型:vue

vue版本:vue2

打包方式:云端

项目创建方式:HBuilderX

示例代码:

<template>  
    <div class="face">  
        <div class="face-meiti">  
            <view style="font-size: 40rpx;font-weight: 600;text-align: center;" @click="test.init">  
                开始检测  
            </view>  
            <div class="tip">{{tip}}</div>  
            <video ref="video" id="video" objectFit="cover" class="video" :controls="false"  
                :show-center-play-btn="false" :autoplay="true" :loop="true"></video>  
            <canvas ref="canvas" :style="canvasStyle" canvas-id="myCanvas" id="myCanvas" class="myCanvas"></canvas>  
            <view  
                style="display: flex;justify-content: space-between;align-items: center;position: fixed;bottom: 0;left: 0;right:0;">  
                <template v-if="src && src.length > 0">  
                    <template v-for="(item, index) in src">  
                        <image style="width: 100%;" :key="index" :src="item.src" mode="widthFix"></image>  
                    </template>  
                </template>  
            </view>  
        </div>  
    </div>  
</template>  

<script lang="renderjs" module="test">  
import '@/static/tracking/tracking-min.js';  
import '@/static/tracking/data/face-min.js';  

export default {  
    data() {  
        return {  
            tip: '请正对摄像头',  
            mediaStreamTrack: null,  
            video: null, // 播放器实例  
            trackerTask: null, //tracking实例  
            uploadLock: true, // 上传锁  
            faceflag: false, //是否进行拍照  
            src: [],  
            canvasStyle: {}  
        }  
    },  
    mounted() {  
        this.init()  
    },  
    methods: {  
        init(options) {  
            const _this = this;  
            console.log("document.querySelector('.video')", document.querySelector('.video').children[0].children.length);   
            if (document.querySelector('.video') && document.querySelector('.video').children[0] !== null && document  
                .querySelector('.video').children[0].children[0] !== null && document.querySelector('.myCanvas') &&  
                document.querySelector('.myCanvas').children[0] !== null) {  
                this.video = this.mediaStreamTrack = document.querySelector('.video').children[0].children[0];  
                this.getUserMedia = navigator.mediaDevices.getUserMedia = navigator.mediaDevices.getUserMedia ||  
                    navigator.webkitGetUserMedia ||  
                    navigator.mozGetUserMedia || navigator.msGetUserMedia;  

                navigator.mediaDevices.getUserMedia({  
                    'video': true  
                }, function(stream) {  
                    _this.video.srcObject = stream  
                }, function(err) {  
                    _this.tip = '摄像头调用失败'  
                })  

                _this.initTracker(options)    
            }  
        },  
        initTracker(options) {  
            const _this = this;  
            let tracker = new window.tracking.ObjectTracker('face');  
            tracker.setInitialScale(4);  
            tracker.setStepSize(2);  
            tracker.setEdgesDensity(0.1);  

            this.trackerTask = window.tracking.track(this.video, tracker, {  
                camera: true  
            });  
            tracker.on('track', function(event) {  
                if (event.data.length == 0) {  
                    if (!_this.faceflag) {  
                        _this.tip = '未检测到人脸'  
                    }  
                } else if (event.data.length > 0) {  
                    _this.tip = '识别成功,正在拍照,请勿乱动~';  
                    let canvas = document.querySelector('.myCanvas').children[0];  
                    const context = canvas.getContext('2d', {  
                        willReadFrequently: true  
                    });  
                    event.data.forEach(function(rect) {  
                        if (!_this.faceflag) {  
                            _this.faceflag = true;  
                            context.drawImage(_this.video, 0, 0, '390', '390');  
                            const base64Img = canvas.toDataURL('image/jpeg');  

                            if (_this.src.length < 3) {  
                                _this.src.push({  
                                    src: base64Img  
                                })  
                                setTimeout(function() {  
                                    _this.faceflag = false  
                                }, 500)  
                            } else {  
                                uni.showToast({  
                                    title: '检测认证已完成'  
                                })  
                            }  
                        }  
                    });  
                }  
            })  
        }  
    }  
}  
</script>  

<script>  
export default {  
    data() {  
        return {  
            tip: '请正对摄像头',  
            mediaStreamTrack: null,  
            video: null, // 播放器实例  
            trackerTask: null, //tracking实例  
            uploadLock: true, // 上传锁  
            faceflag: false, //是否进行拍照  
            src: [],  
            canvasStyle: {}  
        }  
    },  
    mounted() {  
        const _this = this;  
        uni.getSystemInfo({  
            success(res) {  
                _this.canvasStyle = {  
                    width: res.windowWidth + 'px',  
                    height: res.windowWidth + 'px',  
                }  
            }  
        })  

    },  
}  
</script>  
<style lang="scss">  
.face {  
    width: 100vw;  
    height: 100vh;  
    display: flex;  
    justify-content: center;  
    align-items: flex-start;  
    padding: 60rpx 0;  
    box-sizing: border-box;  

    .face-meiti {  
        position: relative;  

        .tip {  
            text-align: center;  
            font-size: 24rpx;  
            padding-bottom: 30rpx;  
        }  

        video {  
            display: block;  
            width: 360rpx;  
            height: 360rpx;  
            -webkit-border-radius: 180rpx;  
            -moz-border-radius: 180rpx;  
            border-radius: 180rpx;  
            object-fit: cover;  
            border: 2rpx solid #000;  
            box-sizing: border-box;  
            margin: 0 auto;  
        }  

        canvas {  
            position: fixed;  
            top: 0;  
            left: 100vw;  
        }  
    }  

    img {  
        width: 100%;  
        height: auto;  
    }  
}  
</style>

2 回复

在浏览器中运行时,document.querySelector(’.video’).children[0].children[0]可以正确获取到想要的DOM,document.querySelector(’.video’).children[0].children.length 是6,app端document.querySelector(’.video’).children[0].children.length 是0


uni-app 中,如果你尝试通过 renderref 获取 video 组件的 DOM 元素时遇到异常,可能是由于以下几个原因导致的。以下是一些常见的问题和解决方案:

1. video 组件未正确绑定 ref

确保你在 video 组件上正确绑定了 ref,并且在使用 this.$refs 获取时,ref 名称是正确的。

<template>
  <video ref="myVideo" src="your-video-url.mp4"></video>
</template>

<script>
export default {
  mounted() {
    const videoElement = this.$refs.myVideo;
    console.log(videoElement);
  }
}
</script>

2. video 组件未正确渲染

uni-app 中,video 组件可能在某些平台上(如小程序)并不是标准的 HTML5 video 元素,而是原生组件。因此,直接通过 ref 获取的 DOM 元素可能不是标准的 video 元素。

如果你需要操作 video 组件,建议使用 uni-app 提供的 API 来操作,而不是直接操作 DOM。

this.$refs.myVideo.play(); // 使用 uni-app 提供的 API

3. 平台差异

uni-app 支持多端编译,不同平台(如 H5、小程序、App)对 video 组件的实现方式可能不同。在 H5 平台上,video 组件是标准的 HTML5 video 元素,但在小程序或 App 上,video 组件可能是原生组件。

如果你需要跨平台兼容,建议使用 uni-app 提供的 API 来操作 video 组件,而不是直接操作 DOM。

4. 异步问题

如果你在 mounted 钩子中获取 video 元素时遇到问题,可能是因为 video 组件还未完全渲染。你可以尝试在 nextTick 中获取 video 元素。

this.$nextTick(() => {
  const videoElement = this.$refs.myVideo;
  console.log(videoElement);
});

5. 使用 uni.createVideoContext

如果你在小程序或 App 中需要操作 video 组件,可以使用 uni.createVideoContext 来创建 video 上下文,然后通过该上下文来操作 video 组件。

const videoContext = uni.createVideoContext('myVideo', this);
videoContext.play();

在模板中,你需要为 video 组件指定一个 id

<template>
  <video id="myVideo" src="your-video-url.mp4"></video>
</template>
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!