【问题标题】:Swap video components in React with no delay在 React 中无延迟地交换视频组件
【发布时间】:2020-05-24 13:16:42
【问题描述】:

我有一个显示video 元素的应用。

我希望用户能够点击一个按钮并观看另一个视频。然而,在更改 src 属性时,在渲染下一个 mp4 时会出现轻微的白色闪烁。

为了解决这个问题,我认为我需要加载一个,预加载另一个并在准备好时更改它们。

我不确定如何在 React 中执行此操作。

import React, { Component } from 'react';

import './App.css'

import one from './one.mp4';
import two from './two.mp4';
import three from './three.mp4';
import four from './four.mp4';

class App extends Component {

  playlist = [one, two, three, four]

  shuffle = (array) => array.sort(() => Math.random() - 0.5);

  getRandomVideo = () => this.shuffle(this.playlist)[Math.floor(Math.random() * this.playlist.length)] 

  state = { 
    playerOne: {
      isVisible: true,
      inputSrc: this.getRandomVideo()
    },
    playerTwo: {
      isVisible: false,
      inputSrc: this.getRandomVideo()
    } 
  }

  onTap = () => this.setState(prevState => ({ 
    playerOne: {
      isVisible: !prevState.playerOne.isVisible,
      inputSrc: this.getRandomVideo()
    },
    playerTwo: {
      isVisible: !prevState.playerTwo.isVisible,
      inputSrc: this.getRandomVideo()
    } 
  }));

  render() {
    const { playerOne, playerTwo } = this.state
    return (
      <div>
        <div className="outer">
          <button onClick={this.onTap}>Toggle</button>
          {playerOne.isVisible &&  <VideoPlayer src={playerOne.inputSrc} /> }
          {playerTwo.isVisible && <VideoPlayer src={playerTwo.inputSrc} /> }
        </div>
      </div>
    )
  }
}

export default App

const VideoPlayer = ({ src }) => {
  return (
    <video key={src} preload autoPlay loop muted><source src={src} type='video/mp4' /></video>
  )
}

【问题讨论】:

    标签: javascript html reactjs html5-video


    【解决方案1】:

    您可以在video 元素中设置background 属性,并使用一些svg 动画来处理闪烁。

    示例

    const { useState, useEffect } = React;
    
    const getVideos = () => Promise.resolve([
    {id: 1,
    src: "https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4"},
    {
    id: 2,
    src: "https://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"}
    ])
    
    const App = () => {
      const [{videos, video}, setData] = useState({
        videos: [],
        video: {
          id: -1,
          src: null
        }
      });
    
      useEffect(() => {
        let isUnmounted = false;
        
        getVideos().then(videos => {
          if(isUnmounted) {
            return;
          }
        
          setData(data => ({
            ...data,
            videos,
            video: videos[0]
          }))
        })
        
        return () => {
          isUnmounted = true;
        }
      
      }, [])
      
      const onNextVideo = () => {
        setData(data => ({
          ...data,
          video: data.videos.find(pr => pr.id !== video.id)
        }))
      }
    
      return <div>
        <video preload="true" autoPlay loop muted key={video.id}>
          <source
            src={video.src}
            type="video/mp4"/>
          </video>
          <div>
            <button onClick={onNextVideo}>Next Video</button>
          </div>
      </div>
    }
    
    ReactDOM.render(
        <App />,
        document.getElementById('root')
      );
    video {
        width: 300px;
        height: 200px;
        object-fit: cover;
        background-size: contain;
        background-position: center;
        background-repeat: no-repeat;
        background-color: black;
        background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0NSIgaGVpZ2h0PSI0NSIgdmlld0JveD0iMCAwIDQ1IDQ1IiBzdHJva2U9IiNmZmYiPgo8cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJibGFjayIvPgogICAgPGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxIDEpIiBzdHJva2Utd2lkdGg9IjIiPgogICAgICAgIDxjaXJjbGUgY3g9IjIyIiBjeT0iMjIiIHI9IjExLjA2NTYiIHN0cm9rZS1vcGFjaXR5PSIwIj4KICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iciIgYmVnaW49IjEuNXMiIGR1cj0iM3MiIHZhbHVlcz0iNjsyMiIgY2FsY01vZGU9ImxpbmVhciIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiLz4KICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0ic3Ryb2tlLW9wYWNpdHkiIGJlZ2luPSIxLjVzIiBkdXI9IjNzIiB2YWx1ZXM9IjE7MCIgY2FsY01vZGU9ImxpbmVhciIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiLz4KICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0ic3Ryb2tlLXdpZHRoIiBiZWdpbj0iMS41cyIgZHVyPSIzcyIgdmFsdWVzPSIyOzAiIGNhbGNNb2RlPSJsaW5lYXIiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIi8+CiAgICAgICAgPC9jaXJjbGU+CiAgICAgICAgPGNpcmNsZSBjeD0iMjIiIGN5PSIyMiIgcj0iMTkuMDY1NiIgc3Ryb2tlLW9wYWNpdHk9IjAiPgogICAgICAgICAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJyIiBiZWdpbj0iM3MiIGR1cj0iM3MiIHZhbHVlcz0iNjsyMiIgY2FsY01vZGU9ImxpbmVhciIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiLz4KICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0ic3Ryb2tlLW9wYWNpdHkiIGJlZ2luPSIzcyIgZHVyPSIzcyIgdmFsdWVzPSIxOzAiIGNhbGNNb2RlPSJsaW5lYXIiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIi8+CiAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9InN0cm9rZS13aWR0aCIgYmVnaW49IjNzIiBkdXI9IjNzIiB2YWx1ZXM9IjI7MCIgY2FsY01vZGU9ImxpbmVhciIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiLz4KICAgICAgICA8L2NpcmNsZT4KICAgICAgICA8Y2lyY2xlIGN4PSIyMiIgY3k9IjIyIiByPSIzLjc5OTE4Ij4KICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iciIgYmVnaW49IjBzIiBkdXI9IjEuNXMiIHZhbHVlcz0iNjsxOzI7Mzs0OzU7NiIgY2FsY01vZGU9ImxpbmVhciIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiLz4KICAgICAgICA8L2NpcmNsZT4KICAgIDwvZz4KPC9zdmc+");
        }
    <script src="https://unpkg.com/react/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    
    <div id="root"></div>

    【讨论】:

      猜你喜欢
      • 2018-08-18
      • 2019-09-17
      • 1970-01-01
      • 1970-01-01
      • 2013-05-20
      • 2021-07-11
      • 2015-08-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多