使用 Swiper 组件播放暂停问题对原生多视频做出反应

Jot*_*nan 0 reactjs react-native

我在swiper中有多个视频可以一个一个地显示视频,但是所有视频都是同时加载和播放的,而且音频很乱,我希望当前视频只能一次播放。

import * as React from 'react';
import { Text, View, StyleSheet,Image, Dimensions } from 'react-native';
import { Constants } from 'expo';
import { Video } from 'expo';
import Swiper from './Swiper';
import InViewPort from './InViewport';
const screenWidth = Dimensions.get('window').width ;
const screenHeight = Dimensions.get('window').height;

export default class App extends React.Component {
  constructor(props) {
    super(props);
    // Your source data
    this.state = {
      images: {},
      muted : false,
      paused: true,
    };
    this.player = Array();
    this.onChangeImage = this.onChangeImage.bind(this);
  }

   videoError(err){
     console.warn(err);
   }

   pauseVideo = () => {
     var curr = this.state.currentIndex;
     console.warn(curr);
     if(this.player[curr]) {
       this.setState({paused: true });
     }
   }

   playVideo = () => {
     var curr = this.state.currentIndex;
     console.warn(curr);
     if(this.player[curr]) {
     this.setState({paused: false});
     }
   }

   handlePlaying = (isVisible) => {
     isVisible ? this.playVideo() : this.pauseVideo();
   }


  onChangeImage (index) {
     this.setState({ currentIndex: index});
   }


  render() {
   let items = Array.apply(null, Array(15)).map((v, i) => {
      return {
        id: i,
        caption: i + 1,
        source: { uri: 'http://placehold.it/200x200?text=' + (i + 1) },
        dimension: '{ width: 150, height: 150 }',
      };
    });
      return(
        <View style={styles.DefaultView}>
          <Swiper
          showsPagination={false}
          onIndexChanged={this.onChangeImage}
          index={0}
          >
           {items.map((item, key) => {
             if(key==1 || key ==5){
               return (
                 <InViewPort onChange={this.handlePlaying} key={key}>
                  <Video onError={this.videoError}
                   muted={this.state.muted}
                   paused={this.state.paused}
                   source={{uri: 'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4' }}
                   style={styles.backgroundVideo}
                   ref={(ref) => {
                      this.player[key] = ref;
                    }}
                    controls={true}
                   />
                  </InViewPort>
               )
             }else{
               return(
                 <Image
                   resizeMode='contain'
                   style={{width:screenWidth, height: screenHeight}}
                   source={item.source}
                   key={key}
               />
              )
             }
           })}
         </Swiper>
         </View>
      )
  }
}

const styles = StyleSheet.create({
    scrollView: {
        flex: 1,
        flexDirection: 'row',
    },
    DefaultView: {
        flex: 1,
        backgroundColor: '#000',
        width: screenWidth,
        justifyContent:'center',
        alignItems:'center'
    },
    iconContainer: {
      flexDirection: "row",
      justifyContent: "space-evenly",
      width: 150,
    },
    backgroundVideo: {
      position: 'absolute',
      top: 0,
      left: 0,
      bottom: 0,
      right: 0,
      width: screenWidth,
      height: 300,
      marginTop:'50%',
      position:'absolute',
  },
});
Run Code Online (Sandbox Code Playgroud)

我需要对此有所了解,我们有一个要使用的播放器引用,还有 swiper 组件具有onIndexChanged,当我们移动到下一个视频时会触发它,我们如何将播放器的引用链接到onIndexChanged以及何时滑动我们如何制作它当前视频只能播放?

根据安德鲁的建议,我也使用了 InPortView 组件来确定滑动的当前视图,但我仍然不确定如何参考要在播放和暂停相关视频的功能中使用的视频元素。

使用的组件:

对于视频react-native-video

对于 Swiper :react-native-swiper

使用 Expo 示例更新完整代码:Expo Snack

And*_*rew 5

所以带上你的零食。我设法让它工作。

我将 Video 移到它自己的组件中,并向它传递了一些额外的 props,index数组中的 和currentIndex显示。

export default class App extends React.Component {
  constructor(props) {
    super(props);
    // Your source data
    this.state = {
      images: {},
      muted : false,
      paused: true,
      currentIndex: 0
    };
  }

  onChangeImage = (index) => {
     console.log('currentIndex ', index)
     this.setState({ currentIndex: index});
   }

  render() {
   let items = Array.apply(null, Array(15)).map((v, i) => {
      return {
        id: i,
        caption: i + 1,
        source: { uri: 'http://placehold.it/200x200?text=' + (i + 1) },
        dimension: '{ width: 150, height: 150 }',
      };
    });
      return(
        <View style={styles.DefaultView}>
          <Swiper
          showsPagination={false}
          onIndexChanged={this.onChangeImage}
          index={0}
          >
           {items.map((item, key) => {
             if(key==1 || key ==5){
               return (
                 <VideoPlayer key={key} index={key} currentIndex={this.state.currentIndex}/>
               )
             }else{
               return(
                 <Image
                   resizeMode='contain'
                   style={{width:screenWidth, height: screenHeight}}
                   source={item.source}
                   key={key}
               />
              )
             }
           })}
          </Swiper>
         </View>
      )
  }
}
Run Code Online (Sandbox Code Playgroud)

视频组件用于react-native-inviewport帮助处理它是否在视口中。然而,它不能很好地发挥作用,react-native-swiper但有可能让它工作。

export default class VideoPlayer extends React.Component {

  pauseVideo = () => {
    if(this.video) {
      this.video.pauseAsync();
    }
  }

  playVideo = () => {
    if(this.video) {
      this.video.playAsync();
    }
  }

  handlePlaying = (isVisible) => {
    this.props.index === this.props.currentIndex ?  this.playVideo() : this.pauseVideo();
  }

  render() {
      return (
        <View style={styles.container}>
          <InViewPort onChange={this.handlePlaying}>
            <Video
              ref={ref => {this.video = ref}}
              source={{ uri: 'http://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4' }}
              rate={1.0}
              volume={1.0}
              isMuted={false}
              resizeMode="cover"
              shouldPlay
              style={{ width: WIDTH, height: 300 }}
            />
          </InViewPort>
        </View>
      )
  }  
}
Run Code Online (Sandbox Code Playgroud)

当我InViewPort单独使用该组件时,它似乎认为位置 6 的视频在视口中并且会播放它。因此,我使用的InviewPort是执行检查以将index视频与currentIndex是否匹配播放视频进行比较,否则将暂停。我想这可以更新以用于componentDidUpdate处理道具的变化。但是,当组件安装时需要执行额外的检查,以便它不播放视频。

这是我的小吃,它起作用了。https://snack.expo.io/@andypandy/swiper-video