1. 程式人生 > >react中使用canvas播放視頻

react中使用canvas播放視頻

const tlist dup 生命 一個 lse 使用 直播 let

最近做個移動端視頻需求,要求隱藏播放控件,並且可以自動播放而且隱藏播放控件(不太人性化),最後要有個定制的結束遮罩層用來人機交互。嘗試直接用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={{width: ‘100%‘,height: ‘auto‘}} id={‘scrollBox‘}>
      <canvas width=‘1280‘ height=‘720‘ ref={node => this.canvas = node} style={{width: ‘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節點一樣操作視頻了,尤其是定制視頻交互控件的樣式,基本都可以滿足產品的各種無厘頭需求啦!最後獻上我的頁面

技術分享圖片

註意是有聲音的‘視頻’哦!

react中使用canvas播放視頻