使用Swiper组件播放暂停问题来响应本地多个视频

时间:2019-02-23 17:00:55

标签: reactjs react-native

我在雨刷器中有多个视频,一个视频一个接一个地显示,但是所有视频都同时加载并播放,并且音频混乱,我希望当前的视频只能一次播放。

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',
  },
});

我需要一些想法,我们有一个播放器参考要使用,滑动组件也有 onIndexChanged ,当我们移到下一个视频时,它将触发,如何链接播放器的参考到onIndexChanged,然后滑动时如何将其设为当前只能播放的视频?

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

使用的组件:

对于视频react-native-video

对于刷卡机:react-native-swiper

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

1 个答案:

答案 0 :(得分:1)

所以带上你的零食。我设法使它起作用。

我将视频移到了自己的组件中,并传递了一些额外的道具,即数组中的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>
      )
  }
}

视频组件使用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>
      )
  }  
}

当我单独使用InViewPort组件时,似乎认为位置6的视频在视口中并且可以播放。因此,我使用InviewPort进行检查是将视频的indexcurrentIndex进行比较,如果它们匹配,则播放视频,否则会暂停。我想可以将其更新为使用componentDidUpdate处理道具的更改。但是,在安装组件时将需要执行其他检查,以使其不播放视频。

这是我的零食,可以正常工作。 https://snack.expo.io/@andypandy/swiper-video