React本地多个视频与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',
  },
});

我需要一些想法,我们要使用一个播放器参考,也有swiper组件具有 onindexchanged ,当我们移动到下一个视频时,它将触发,如何链接播放器的参考对于onIndexChanged,当我们刷新时,我们如何将其制作到当前的视频?

按照安德鲁的建议,我也使用了InportView组件,也确定了当前的滑动视图,但我仍然不确定如何为播放功能中使用的视频元素引用并暂停关注的视频。

使用的组件:

用于视频反应 - video

swiper:反应式swiper

更新了带有Expo的完整代码示例:Expo小吃

,请服用零食。我设法使它工作。

我将视频移到了自己的组件中,并传递了一些其他道具,其中的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

最新更新