zoukankan      html  css  js  c++  java
  • react中使用canvas播放视频

    最近做个移动端视频需求,要求隐藏播放控件,并且可以自动播放而且隐藏播放控件(不太人性化),最后要有个定制的结束遮罩层用来人机交互。尝试直接用video标签做,但是各种坑啊,video永远是在页面的最顶层,所以播放控件的自定义化就凉凉了,怎么办呢?受以前做的一个利用canvas做视频直播的项目启发,尝试下canvas做视频播放,于是我抱着试一试的心态去查阅了相关资料,尼玛,还真的可以,而且原理很简单!

    首先要解决在react中操作canvas的问题,众所周知,react和vue都是生成的虚拟dom,直接通过dom的API操作canvas是不现实的。npm上的一些库也是繁琐的像XX。。。我写了一个方法,在react的componentDidMount中利用react的ref把canvas直接传给这个方法,拿到了页面上的canvas,只要这个页面不卸载,我就可以为所欲为啦!直接上代码:

    import React, { Component } from 'react';
    import './App.css';
    import {draw} from './canvas'
    class App extends Component {
    
      componentDidMount() {
        if (this.canvas) {
            draw(this.canvas)
        }
      }
    
      render() {
    
        return <div style={{ '100%',height: 'auto'}} id={'scrollBox'}>
          <canvas width='1280' height='720' ref={node => this.canvas = node} style={{ '100%',height: 'auto'}}></canvas>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
          <p>我是测试我是测试</p>
        </div>;
      }
    }
    
    export default App;
    

       通过ref函数把canvas赋值给this.canvas,在componentDidMount钩子中传给canvas脚本文件绘制(注意,由状态动态生成的canvas可能拿不到这个dom,建议放到componentDidUpdate钩子中,不熟悉react生命周期的同学自行查阅官方文档),于是这个时候,我拿出了我的终极大杀器——canvas.js.好了,不吹牛皮,其实它就是一个非常简单的脚本,看看它的代码:

    export const draw = (canvas) => {
        if (canvas) {
            //获取canvas上下文
            let ctx = canvas.getContext('2d');
    
            //创建video标签,并且设置相关属性
            let video = document.createElement('video');
    
            video.preload = true;
            video.autoplay = true;
            video.src='https://pic.ibaotu.com/00/92/91/90f888piCjkw.mp4';
            //document.body.appendChild(video);
    
            //监听video的play事件,一旦开始,就把video逐帧绘制到canvas上
            video.addEventListener('play',() => {
                let play = () => {
                    ctx.drawImage(video,0,0);
                    requestAnimationFrame(play);
                };
    
                play();
            },false)
    
            //暂停/播放视频
            canvas.addEventListener('click',() => {
                if (!video.paused) {
                    video.pause();
                } else {
                    video.play();
                }
            },false);
        }
    }
    

      大概的思路就是我首先在内存中创建一个video标签并设置好相关属性,之后监听video的play事件,一旦开始播放,我就会通过requestAnimationFrame把video逐帧绘制到canvas上。由于真的有个video在播放视频,所以你会听到声音,但是,我并没有把它放到页面上,所以你看到的不是视频,而是一个没有声音的canvas!嘿嘿嘿O.o

      视频这样子处理,虽然依旧不能跨过谷歌和苹果爸爸对视频自动播放的限制,但是可以像操作普通div节点一样操作视频了,尤其是定制视频交互控件的样式,基本都可以满足产品的各种无厘头需求啦!最后献上我的页面

    注意是有声音的‘视频’哦!

  • 相关阅读:
    (模板)高斯消元法模板
    poj1797(dijstra变形,求最小边的最大值)
    poj2253(floyd变形)
    (模板)poj2387(dijkstra+优先队列优化模板题)
    poj1915(双向bfs)
    poj3977(折半枚举+二分查找)
    uva11624 Fire! (bfs预处理)
    codeforces#1152C. Neko does Maths(最小公倍数)
    codeforces#1154F. Shovels Shop (dp)
    codeforces#1136E. Nastya Hasn't Written a Legend(二分+线段树)
  • 原文地址:https://www.cnblogs.com/zhangbob/p/10039440.html
Copyright © 2011-2022 走看看