react-native-rn-videoplayer
Version:
A customisable React Native video player for Android and IOS
1,171 lines (1,027 loc) • 61.9 kB
JavaScript
//修复播放不同分辨率视频,不会重新测量分辨率的问题https://github.com/react-native-community/react-native-video/pull/2053
import React from 'react';
import {
Text,
StyleSheet,
View,
TouchableOpacity,
Dimensions,
StatusBar,
Animated,
NativeModules,
Alert,
Easing,
PanResponder,
Platform
} from 'react-native';
import {
Loading,
TipsPaused,
Brightness,
Volume,
BottomSpeed,
Speed,
Header,
SpeedTipTime,
Lock,
AnFastSvg
} from './view/index';
import {
SvgVideoNextBtn,
SvgVideoSetting,
SvgVideoStop,
SvgVideoPlay,
SvgVideoAllBox,
SvgVideoSmallBox,
SvgVideoBack,
SvgVideoScang,
SvgVideoFastSpeed
} from './component/svg';
import SystemSetting from 'react-native-system-setting';
import LinearGradient from 'react-native-linear-gradient';
import Video from 'react-native-video';
import { formatSeconds } from './utils/formatSeconds';
import Orientation from 'react-native-orientation-locker';
import { getMaxdata } from './utils/getMaxdata';
const { height, width } = Dimensions.get('screen');
class VideoPlayer extends React.Component {
static defaultProps = {
autoPlay: true,
resizeMode:"contain",
posterResizeMode:"cover",
showSmallCont: true,
speedColor: "#e54602",
dotColor: "#e54602",
dotBorderColor: "rgba(255,255,255,0.3)",
bottomSpeedColor: "#e54602",
cachColor: "#ffffff",
allSpeedColor: "rgba(0,0,0,0.4)"
}
constructor(props) {
super(props)
this.noVipSecond = this.props.noVipSecond || 5//没有vip可观看的分钟数
this.url = this.props.url
this.spinValue = new Animated.Value(0)
this.adminBrightness = ''
this.soundData = 0//音量
this.soundDataY = 0
this.speedData = 0//滑动进度
this.speedDataX = 0
this.BrightnessData = 0//亮度
this.BrightnessY = 0
this.nowTime = "00:00"
this.nowCurrentTime = 0//当前播放秒数
this.defSpeed = 1
this.speedTouchScale = 5//长按快进快退的宽度 跟屏幕宽度的比例
this.speedFastValue = 3 //长按视频右边的快进速率
this.speedSlowValue = 3
this.dotX = new Animated.Value(0),
this.bufferX = new Animated.Value(0),
this.soundAnima = new Animated.Value(0),//音量
this.playDotX = null,//控件没被隐藏时的进度动画
this.playhideContsDotX = null,//控件被隐藏时,最下面的进度动画
this.playBufferX = null,
this.recordHandeY = [],//记录滑动y值
this.recordHandeX = [],//记录滑动x值
this.state = {
videoRate: this.defSpeed,//播放速率
duration: 0.0,
onload: false,//视频加载状态
admRePlay: false,//重置视频进度状态
opacity: new Animated.Value(1),
paused: true,
width: width,
smallP: true,//当前是否是小屏
statusBarH: 44,
isEnd: false,//是否播放完了
showVolume: false,
showBrightness: false,
videoStarTimeWidth: 0,//现在的播放时间的宽度
videoEndTimeWidth: 0,//总时长的宽度
height: width * 210 / 375,
LinearGradientHeight: 60,//控件阴影高度
topContsTop: 0,//上部分控件的top定位值
bottomContsBottom: 0,//下部分控件的bottom定位值
showOpenVip: false,//是否显示开通vip提示
currentTime: 0.0,
showLoading: false,//是否显示正在加载
showConts: true,
showDrTime: false,//拖动进度条时显示的时间进度
showChangeList: false,//控制是否显示全屏选集
showLockCont: false//锁的显示状态
}
this.animatedonBuffer = this.animatedonBuffer.bind(this)
}
componentWillUnmount() {
Orientation.lockToPortrait();
Platform.OS === "android"
? NativeModules.HideBottomNa.show()
: NativeModules.RNIndicator.alwaysVisible();
// Orientation.removeOrientationListener(this._orientationDidChange);
//离开该页面 还原屏幕亮度
if (this.adminBrightness) {
Platform.OS === "android" ?
NativeModules.AppBrightness.setAppBrightness(this.adminBrightness) :
SystemSetting.setBrightnessForce(this.adminBrightness).then((success) => {
!success && Alert.alert('没有权限', '您无权限改变屏幕亮度', [
{ 'text': '好的', style: 'cancel' },
{ 'text': '打开设置', onPress: () => SystemSetting.grantWriteSettingPermission() }
])
});
}
}
_orientationDidChange = (orientation) => {
// if (orientation === 'LANDSCAPE') {
// // 横屏
// this.setAll()
// } else {
// this.setSmall()
// // do something with portrait layout
// }
}
//全屏
changeAllBox = () => {
this.setAll()
Platform.OS === "android"
? NativeModules.HideBottomNa.hide()
: NativeModules.RNIndicator.autoHidden();
Orientation.lockToLandscape()
this.props.onWindowChange && this.props.onWindowChange("full")
}
//小屏
changeSmallBox = () => {
this.setSmall()
Orientation.lockToPortrait()
this.props.onWindowChange && this.props.onWindowChange("small")
Platform.OS === "android"
? NativeModules.HideBottomNa.show()
: NativeModules.RNIndicator.alwaysVisible();
}
setAll = () => {
this.playhideContsDotX = this.dotX.interpolate({
inputRange: [0, this.state.duration],
outputRange: [0, height],
extrapolate: 'clamp'
})
this.props.navigation && this.props.navigation.setParams({ enableGestures: false });
this.dotspeed && this.dotspeed.setdotStart(false)
this.setState({
width: height + 0,//StatusBar.currentHeight
height: width,
statusBarH: 0,
smallP: false,
showConts: false,
showLockCont: false,
LinearGradientHeight: 100,
topContsTop: 30,
bottomContsBottom: this.props.continuous ? 30 : 0,
}, () => {
StatusBar.setHidden(true)
// 更新播放进度
this.playDotX = this.dotX.interpolate({
inputRange: [0, this.state.duration],
outputRange: [0, height + 0 - 200],//StatusBar.currentHeight
extrapolate: 'clamp'
})
// 更新缓存进度
this.playBufferX = this.bufferX.interpolate({
inputRange: [0, this.state.duration],
outputRange: [0, height + 0 - 200],//StatusBar.currentHeight
extrapolate: 'clamp'
})
})
}
setSmall = () => {
//更新控件隐藏后的进度条
this.playhideContsDotX = this.dotX.interpolate({
inputRange: [0, this.state.duration],
outputRange: [0, width],
extrapolate: 'clamp'
})
this.props.navigation && this.props.navigation.setParams({ enableGestures: true });
this.dotspeed && this.dotspeed.setdotStart(false)
this.setState({
width: width,
height: width * 210 / 375,
statusBarH: 0,//
smallP: true,
showConts: false,
showLockCont: false,
LinearGradientHeight: 60,
topContsTop: 0,
bottomContsBottom: 0,
}, () => {
StatusBar.setHidden(false)
// 更新播放进度
this.playDotX = this.dotX.interpolate({
inputRange: [0, this.state.duration],
outputRange: [0, width - 200],
extrapolate: 'clamp'
})
// 更新缓存进度
this.playBufferX = this.bufferX.interpolate({
inputRange: [0, this.state.duration],
outputRange: [0, this.state.width - 200],
extrapolate: 'clamp'
})
}
)
}
componentDidMount() {
this.spin()
if (this.props.autoPlay) {
this.setState({
paused: false
})
}
// Orientation.lockToLandscape();
// Orientation.addOrientationListener(this._orientationDidChange);//监听屏幕方向
}
//控制loading加载器的显示隐藏
animatedonBuffer(event) {
this.props.onBuffer && this.props.onBuffer(event)
this.setState({
showLoading: Platform.OS === "android" ? (event.isBuffering ? true : false) : (!this.state.paused && true)
})
}
//播放进度 包含进度条 以及当前播放时间
animatedDot = (e) => {
this.props.onProgress && this.props.onProgress(e)
if (!this.ismoveDot) {
this.nowCurrentTime = e.currentTime
}
this.nowTime = formatSeconds(e.currentTime)
!this.ismoveDot && this.dotspeed && this.dotspeed.setSpeed(e)
if (!this.state.showOpenVip && this.props.VIPCONTS) {
e.currentTime >= this.noVipSecond
&&
this.setState({ showOpenVip: true, paused: true, showConts: false }, () => {
!this.state.smallP && this.changeSmallBox();
})
}
this.state.showLoading && Platform.OS === "ios" && this.setState({ showLoading: false })
Animated.timing(
// timing方法使动画值随时间变化
this.dotX, // 要变化的动画值
{
toValue: e.currentTime, // 最终的动画值
duration: 0,
useNativeDriver: false
},
).start(); // 开始执行动画
Animated.timing(
// timing方法使动画值随时间变化
this.bufferX, // 要变化的动画值
{
toValue: e.playableDuration, // 最终的动画值
duration: 0,
useNativeDriver: false
},
).start(); // 开始执行动画
}
speedLongTouch = (evt) => {
var speedStartX = evt.nativeEvent.pageX
var speedTouchWidth = this.state.width / 4
if ( speedStartX >= this.state.width - speedTouchWidth) {
this.setState({
videoRate: this.speedFastValue,
speedTouch:true
}, () => {
this.rightSpeedRef.setNativeProps({
style: {
opacity: 1
}
})
})
}
if(speedStartX <= speedTouchWidth ){
this.isSolTouch=true
this.setState({
speedTouch:true
})
this.nowCurrentTime&&this.player.seek(this.nowCurrentTime-5)
this.sloSpeedTime=setInterval(()=>{
this.nowCurrentTime&&this.player.seek(this.nowCurrentTime-5)
},500)
this.leftSpeedRef.setNativeProps({
style: {
opacity: 1
}
})
}
}
speedLongTouchOut = (evt) => {
this.setState({
speedTouch:false
})
var speedStartX = evt.nativeEvent.pageX
var speedTouchWidth = this.state.width / 4
if (speedStartX <= speedTouchWidth) {
this.sloSpeedTime&&clearInterval(this.sloSpeedTime)
this.isSolTouch=false
this.leftSpeedRef.setNativeProps({
style: {
opacity: 0
}
})
}
if (speedStartX >= this.state.width - speedTouchWidth) {
this.setState({
videoRate: this.defSpeed
}, () => {
this.rightSpeedRef.setNativeProps({
style: {
opacity: 0
}
})
})
}
}
componentWillMount() {
//控件逐渐透明动画
this.hide = Animated.timing(
// timing方法使动画值随时间变化
this.state.opacity, // 要变化的动画值
{
toValue: 0, // 最终的动画值
duration: 300,
delay: 5000,
useNativeDriver: false
},
)
//控件显示动画
this.AnimatedOp = Animated.timing(
// timing方法使动画值随时间变化
this.state.opacity, // 要变化的动画值
{
toValue: 1, // 最终的动画值
duration: 300,
useNativeDriver: false
},
)
//控件隐藏动画
this.fastHide = Animated.timing(
// timing方法使动画值随时间变化
this.state.opacity, // 要变化的动画值
{
toValue: 0, // 最终的动画值
duration: 300,
useNativeDriver: false
},
)
//直接隐藏
this.toofastHide = Animated.timing(
// timing方法使动画值随时间变化
this.state.opacity, // 要变化的动画值
{
toValue: 0, // 最终的动画值
duration: 0,
useNativeDriver: false
},
)
// 上下滑动 调节音量 以及屏幕亮度
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,//锁定控件时 禁用手势
onStartShouldSetPanResponderCapture: (evt, gestureState) => false,
onMoveShouldSetPanResponder: (evt, gestureState) => {
if(this.state.speedTouch){
return false
}
return Math.abs(gestureState.dx) > 2 || Math.abs(gestureState.dy) > 2
},
onMoveShouldSetPanResponderCapture: (evt, gestureState) => {
if(this.state.speedTouch){
return false
}
return Math.abs(gestureState.dx) > 2 || Math.abs(gestureState.dy) > 2
},
onPanResponderGrant: (evt, gestureState) => {
clearTimeout(this.TimeHideConts)//拖动时禁止隐藏控件
//初始化 记录滑动的xy值
this.recordHandeY = []; this.recordHandeX = [];
// 开始手势操作。给用户一些视觉反馈,让他们知道发生了什么事情!
this.startX = evt.nativeEvent.pageX;
this.startY = evt.nativeEvent.pageY;
//显示控件
this.showLockAndCont()
// console.log("startY", this.startY)
//获取当前音量
SystemSetting.getVolume().then((volume) => {
this.volume = volume
}).catch((err) => {
console.log('Current err is ' + err);
})
//获取当前屏幕亮度
SystemSetting.getBrightness().then((brightness) => {
this.adminBrightness = brightness
//安卓不是直接修改系统亮度,这里获取到的是系统亮度,所以安卓需要处理
if (this.brightnessData) {
this.brightness = Platform.OS === "android" ? this.brightnessData : brightness
} else {
this.brightness = brightness
}
});
},
onPanResponderMove: (evt, gestureState) => {
if (this.recordHandeY.length < 10) {
this.recordHandeY.push(evt.nativeEvent.pageY)
this.recordHandeX.push(evt.nativeEvent.pageX)
}
// console.log("locationY", evt.nativeEvent.pageY)
this.moveYData = this.startY - evt.nativeEvent.pageY
if (this.LockRef && this.LockRef.state.lock||this.speedTouch) return//锁定控件时 禁用手势
// console.log("moveYData",)
this.moveXData = evt.nativeEvent.pageX - this.startX
this.soundDataY = (this.startY + 30 - gestureState.moveY) / (this.state.height)
this.BrightnessY = (this.startY + 30 - gestureState.moveY) / (this.state.height)
this.speedDataX = (gestureState.moveX - this.startX)
if (this.recordHandeY.length === 10) {
if (Math.abs(this.recordHandeY[9] - this.recordHandeY[0]) > Math.abs(this.recordHandeX[9] - this.recordHandeX[0])) {
//console.log("上下滑动")
if (Math.abs(this.moveYData) > 5) {
if (Math.abs(this.soundDataY) <= 1 && this.startX > this.state.width / 2) {
// 改变当前系统音量
if (this.soundDataY) {
this.soundData = this.volume + this.soundDataY
if (!this.state.showVolume) {
this.setState({ showVolume: true })
}
if (this.hideVolumeTime) {
clearTimeout(this.hideVolumeTime)
}
// console.log("音量", this.soundData)
SystemSetting.setVolume(this.soundData);
if (this.soundData >= 1) {
this.VolumeRef && this.VolumeRef.setsoundWidth(100)
}
if (this.soundData >= 0 && this.soundData <= 1) {
this.VolumeRef && this.VolumeRef.setsoundWidth(this.soundData / 1 * 100)
}
if (this.soundData < 0 && this.soundData <= 1 && this.state.soundWidth != 0) {
this.VolumeRef && this.VolumeRef.setsoundWidth(0)
}
}
}
if (this.volume >= 1 && this.startX < this.state.width / 2 && this.soundData >= 0.96) {
this.setState({
soundWidth: 100
})
}
if (Math.abs(this.BrightnessY) <= 1 && this.startX < this.state.width / 2) {
//console.log("屏幕左边上下滑动调节亮度")
if (this.BrightnessY) {
if (!this.state.showBrightness) {
this.setState({ showBrightness: true })
}
if (this.hideBrightnessTime) {
clearTimeout(this.hideBrightnessTime)
}
this.brightnessData = this.brightness + this.BrightnessY
if (this.brightnessData >= 1) {
this.BrightnessRef && this.BrightnessRef.setBrightnessWidthFun(100)
}
if (this.brightnessData >= 0 && this.brightnessData <= 1) {
Platform.OS === "android" ?
NativeModules.AppBrightness.setAppBrightness(this.brightnessData)
:
SystemSetting.setBrightnessForce(this.brightnessData).then((success) => {
!success && Alert.alert('没有权限', '您无权限改变屏幕亮度', [
{ 'text': '好的', style: 'cancel' },
{ 'text': '打开设置', onPress: () => SystemSetting.grantWriteSettingPermission() }
])
});
this.BrightnessRef && this.BrightnessRef.setBrightnessWidthFun(this.brightnessData / 1 * 100)
}
if (this.brightnessData < 0 && this.brightnessData <= 1 && this.state.brightnessWidth != 0) {
this.BrightnessRef && this.BrightnessRef.setBrightnessWidthFun(0)
}
}
}
}
} else {
//"左右滑动调节播放进度"
if (this.state.onload && Math.abs(this.moveXData) > 0) {
const { duration, width } = this.state
!this.ismoveDot && this.dotspeed && this.dotspeed.setNativeProps({
style: { borderColor: "rgba(255,255,255,0.5)" }
})
/**调节进度开始**/
!this.ismoveDot && (this.ismoveDot = true);
this.dotspeed && this.dotspeed.setdotStart(true)
/**调节进度结束**/
this.changeSpeedTip({ opacity: 1, display: null, width: null })
clearTimeout(this.TimeHideConts)//拖动进度条时禁止隐藏控件
this.realMarginLeft = this.speedDataX / 2; //2为快进退的手势速度 必须大于0
if (this.realMarginLeft >= width - 200) {
this.realMarginLeft = width - 200
}
this.speedtime = duration > 60 * 30 ? (this.realMarginLeft) : (this.realMarginLeft) / (width) * duration//快进的时长 单位s
this.speedalltime = getMaxdata(this.nowCurrentTime + this.speedtime, duration)
this.SpeedTipTimeRef && this.SpeedTipTimeRef.setgoSpeedTime(formatSeconds(
this.speedalltime
))
this.dotspeedWidth = (width - 200) / duration * (this.speedalltime)
this.reasut = this.dotspeedWidth
this.dotspeed && this.dotspeed.setdotWidth(this.reasut)
}
}
}
},
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
this.speedLongTouchOut(evt)
// this.props.navigation.setParams({ enableGestures: true });
if (this.LockRef && this.LockRef.state.lock) return false//锁定控件时 禁用手势
this.activateAutoHide()//激活自动隐藏
this.dotspeed && this.dotspeed.setNativeProps({
style: { borderColor: "rgba(255,255,255,0)" }
})
let speedB = '';
speedB = this.speedalltime
if (speedB) {
speedB >= this.state.duration ?
this.player.seek(speedB - 2)
:
this.player.seek(speedB);
this.speedalltime = '';
}
this.changeSpeedTip({ opacity: 0, display: "none", width: 0 })
this.ismoveDot = false
// this.activateAutoHide()//激活自动隐藏
//调节完音量后隐藏音量显示器
if (this.state.showVolume) {
this.hideVolumeTime = setTimeout(() => { this.setState({ showVolume: false }) }, 800)
}
//调节完亮度后隐藏亮度显示器
if (this.state.showBrightness) {
this.hideBrightnessTime = setTimeout(() => { this.setState({ showBrightness: false }) }, 800)
}
if (Math.abs(this.moveXData) > 5) {
this.changeSpeedTip({ opacity: 0, display: "none", width: 0 })
}
if (this.brightnessData >= 1) {
this.brightnessData = 1
}
if (this.brightnessData <= 0) {
this.brightnessData = 0
}
},
onPanResponderTerminate: (evt, gestureState) => {
this.speedLongTouchOut(evt)
this.activateAutoHide()//激活自动隐藏
this.dotspeed && this.dotspeed.setNativeProps({
style: { borderColor: "rgba(255,255,255,0)" }
})
this.changeSpeedTip({ opacity: 0, display: "none", width: 0 })
this.ismoveDot = false
return true;
},
onShouldBlockNativeResponder: (evt, gestureState) => {
return false;
},
});
// 左右拖动进度条
this._panSpeeDot = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
onPanResponderGrant: (evt, gestureState) => {
// this.props.navigation.setParams({ enableGestures: false });
if (this.state.showOpenVip || !this.state.onload) return//需要权限 或者视频还不可以播放时停止不允许滑动进度条
this.dotspeed.setNativeProps({
style: { borderColor: this.props.dotBorderColor }
})
this.changeSpeedTip({ opacity: 1, display: null, width: null })
clearTimeout(this.TimeHideConts)//拖动进度条时禁止隐藏控件
this.ismoveDot = true
// 开始手势操作。给用户一些视觉反馈,让他们知道发生了什么事情!
this.touchX = evt.nativeEvent.locationX;
this.dotspeed.setdotStart(true)
// this.setState({ dotWidth: evt.nativeEvent.pageX - 100, })
this.dotspeed.setdotWidth(evt.nativeEvent.pageX - 100)
// this.playDotX=null
// gestureState.{x,y} 现在会被设置为0
},
onPanResponderMove: (evt, gestureState) => {
if (this.state.showOpenVip || !this.state.onload) return//需要权限 或者视频还不可以播放时停止不允许滑动进度条
this.realMarginLeft = gestureState.moveX - this.touchX - 85;
if (this.realMarginLeft >= this.state.width - 200) {
this.realMarginLeft = this.state.width - 200
}
// console.log("realMarginLeft",this.realMarginLeft)
// console.log("当前",)
if (this.realMarginLeft > 0) {
// this.setState({
// // dotWidth: this.realMarginLeft,
// //想要拖动快进的时间
// goSpeedTime: formatSeconds((this.realMarginLeft) / (this.state.width - 200) * this.state.duration)
// })
this.SpeedTipTimeRef && this.SpeedTipTimeRef.setgoSpeedTime(formatSeconds((this.realMarginLeft) / (this.state.width - 200) * this.state.duration))
this.dotspeed.setdotWidth(evt.nativeEvent.pageX - 100 >= this.state.width - 200 ? this.state.width - 200 : evt.nativeEvent.pageX - 100)
}
},
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
// this.props.navigation.setParams({ enableGestures: true });
if (this.state.showOpenVip) return//需要权限时停止不允许滑动进度条
this.dotspeed.setNativeProps({
style: { borderColor: "rgba(255,255,255,0)" }
})
this.activateAutoHide()//手指离开后激活自动隐藏
let speedB = (this.dotspeed.state.dotWidth) / (this.state.width - 200)
if (speedB >= 1) {
this.player.seek(this.state.duration * speedB - 2)
} else {
this.player.seek(this.state.duration * speedB)
}
this.changeSpeedTip({ opacity: 0, display: "none", width: 0 })
this.ismoveDot = false
},
onPanResponderTerminate: (evt, gestureState) => {
this.changeSpeedTip({ opacity: 0, display: "none", width: 0 })
this.dotspeed.setNativeProps({
style: { borderColor: "rgba(255,255,255,0)" }
})
this.ismoveDot = false//判断是否触摸按住进度条上的点
this.activateAutoHide()//激活自动隐藏
return true;
},
onShouldBlockNativeResponder: (evt, gestureState) => {
return false;
},
});
}
changeSpeedTip = (e) => {
this.SpeedTipTimeRef && this.SpeedTipTimeRef.refs.gotimeSpeed.setNativeProps({ style: e })
}
//快速隐藏控件
fastHideConts = () => {
this.fastHide.start(() => { this.setState({ showConts: false, showLockCont: false }) })
}
//激活自动隐藏
activateAutoHide = () => {
this.TimeHideConts = setTimeout(this.fastHideConts, 5000);
}
//重置播放
rePlay = (autoPlay = true, admRePlay = true) => {
this.adminPaused = true;
//admRePlay//重置当前播放时间
const GSTATE = { admRePlay: admRePlay, showChangeList: false }
if (this.state.isEnd) {
this.player.seek(0)
setTimeout(() => {
autoPlay
?
this.setState({ paused: true, isEnd: false, showConts: true, ...GSTATE }, () => { this.setState({ paused: false }) })
:
this.setState({ isEnd: false, showConts: true, ...GSTATE });
}, 300)
} else {
if (!this.state.paused) {
this.setState({ paused: true, ...GSTATE }, () => { autoPlay && this.setState({ paused: false }) });
}
}
if (this.state.paused && !this.state.isEnd) {
this.setState({ paused: autoPlay ? false : true, ...GSTATE });
}
}
//暴露方法 设置播放暂停
setPaused = (e) => {
this.adminPaused = true
if (e) {
this.setState({
paused: true
})
} else {
this.setState({
paused: false
})
}
}
//重新加载 暴露方法
reLoad = () => {
const { paused } = this.state
if (!paused) { this.setState({ paused: true }) }
this.player.seek(0)
setTimeout(() => {
this.setState({ paused: false, showConts: true, showLoading: true });
})
}
showLockAndCont = () => {
const GSHOWSTATE = { showLockCont: true, showConts: true, showChangeList: false }
const animaFun = () => {
this.hide.stop(); this.AnimatedOp.stop(); this.fastHide && this.fastHide.stop();
}
if (this.LockRef && !this.LockRef.state.lock) {
this.AnimatedOp.start(() => { this.setState({ ...GSHOWSTATE }); animaFun() }); // 开始执行动画
} else {
!this.LockRef
?
this.AnimatedOp.start(() => { this.setState({ ...GSHOWSTATE }); animaFun() }) // 开始执行动画
:
this.AnimatedOp.start(() => { this.setState({ showLockCont: true, showChangeList: false }); animaFun() }); // 开始执行动画
}
}
//显示控件
showConts = () => {
try {
clearTimeout(this.TimeHideConts)
//当提示要vip 暂停播放时 禁止双击暂停播放
if (!this.state.showOpenVip) {
if (this.lastBackPressed && this.lastBackPressed + 300 >= Date.now()) {
// clearTimeout(this.Timeout)
if (this.LockRef && this.LockRef.state.lock) return//锁定控件时 禁用手势
this.adminPaused = true
this.state.paused ? this.rePlay(true, false) : this.setState({ paused: true, })
this.state.opacity.setValue(1)
return
} else {
this.lastBackPressed = Date.now();
}
}
// this.Timeout = setTimeout(() => {
if (this.state.showConts || this.state.showLockCont) {//立即消失
this.hide.stop()
this.fastHideConts()
} else {
this.hide.stop();
//点击视频显示控件
this.showLockAndCont()
}
// }, 300)
this.activateAutoHide()//激活控件自动隐藏
} catch (error) {
}
}
onLoad = (data) => {
this.props.onLoad && this.props.onLoad(data)
//视频总长度
this.setState({ duration: data.duration, allTime: formatSeconds(data.duration), showChangeList: false, admRePlay: false, onload: true });
//进度条动画
this.playDotX = this.dotX.interpolate({
inputRange: [0, data.duration],
outputRange: [0, this.state.width - 200],
extrapolate: 'clamp'
})
//隐藏控件时,最下面的进度动画
this.playhideContsDotX = this.dotX.interpolate({
inputRange: [0, data.duration],
outputRange: [0, this.state.width],
extrapolate: 'clamp'
})
this.playBufferX = this.bufferX.interpolate({
inputRange: [0, data.duration],
outputRange: [0, this.state.width - 200],
extrapolate: 'clamp'
})
this.toofastHide.start(() => { this.setState({ showConts: false }) })
}
//播放完重制播放进度等状态
reVideo = () => {
!this.props.repeat && this.setState({ showConts: true, opacity: 1, paused: true, isEnd: true }, () => {
// this.player.seek(0)
// this.refs.speed.setNativeProps({
// style: {
// width: 0
// }
// })
})
if (!this.state.paused) {
this.props.onEnd && this.props.onEnd()
}
}
//旋转方法
spin = () => {
this.spinValue.setValue(0)
Animated.timing(this.spinValue, {
toValue: 1, // 最终值 为1,这里表示最大旋转 360度
duration: 2000,
easing: Easing.linear,
useNativeDriver: true
}).start(() => this.spin())
}
videoError = (e) => {
this.props.onError && this.props.onError(e)
this.setState({ showLoading: false, paused: true })
this.onError = true
}
changeWindows = (e) => {
if (e) {
this.changeAllBox()
} else {
this.changeSmallBox()
}
}
btnPasuedfun = () => {
!this.state.showOpenVip && (this.adminPaused = true, this.setState({ paused: true }))
}
//视频地址改变的回调
onchangeUrl = () => {
this.setState({
onload: false
})
}
render() {
const spin = this.spinValue.interpolate({
inputRange: [0, 1],//输入值
outputRange: ["0deg", "360deg"] //输出值
})
var propsObj = { ...this.props }
delete (propsObj["paused"])
if (this.url && this.url != this.props.url) {
this.onchangeUrl()
}
this.url = this.props.url
const { videoRate, smallP, allTime,speedTouch, LinearGradientHeight, showOpenVip, topContsTop, bottomContsBottom } = this.state
const stateHeight = this.state.height
const stateWidth = this.state.width
const preShowSmallCont = smallP ? (this.props.showSmallCont ? true : false) : true
const speedLoToWidth = stateWidth / this.speedTouchScale
return (
<>
{this.props.statusBar ? (smallP && this.props.statusBar()) : <Header width={stateWidth} />}
<View ref={ref => this.videoBox = ref} style={{ backgroundColor: "#000", position: 'relative' }}>
<View style={{}}>
<View {...this._panResponder.panHandlers} style={{ height: stateHeight, width: stateWidth, }}
activeOpacity={1}
>
<TouchableOpacity
activeOpacity={1}
onPress={this.showConts}
onLongPress={this.speedLongTouch}
onPressOut={this.speedLongTouchOut}
style={{ overflow: "hidden" }}
>
<Video
key={this.url}
rate={videoRate}
source={{ uri: this.props.url }}
ref={(ref) => { this.player = ref }}
continuous={this.props.continuous ? true : false}//是否是连续剧,用来全屏展示选集,下一集按钮 重新加载Video标签,防止出现上个视频和下个视频分辨率不切换的问题
{...propsObj}
repeat={this.props.repeat ? this.props.repeat : false}
onSeek={(e) => {
this.props.onSeek && this.props.onSeek(e)
this.setState({ isEnd: false })
}}
// posterResizeMode={"cover"}//封面大小
playWhenInactive={true}//确定当通知或控制中心在视频前面时,媒体是否应继续播放。
paused={this.adminPaused ? this.state.paused : (this.props.autoPlay ? false : true)}//暂停
onLoad={this.onLoad}
onEnd={this.reVideo}
// resizeMode={this.props.resizeMode}
onReadyForDisplay={(e) => {
this.props.onReadyForDisplay && this.props.onReadyForDisplay(e)
}}
controls={false}
onProgress={this.animatedDot}
onBuffer={(e) => this.animatedonBuffer(e)}
onError={this.videoError}
width={this.props.width ? this.props.width : stateWidth}
style={{ height: stateHeight, backgroundColor: "#000000" }} />
<View style={{ position: 'absolute', left: 0, right: 0, bottom: 0, top: 0, flexDirection: "row", justifyContent: 'space-between', }}>
<View ref={(e) => this.leftSpeedRef = e} style={{ opacity: 0, width: stateHeight * 2, backgroundColor: "rgba(0,0,0,0.5)", borderRadius: stateHeight * 2, right: stateHeight * 2 - speedLoToWidth, height: stateHeight * 2, top: -stateHeight / 2 }}></View>
<View ref={(e) => this.rightSpeedRef = e} style={{ opacity: 0, width: stateHeight * 2, backgroundColor: "rgba(0,0,0,0.5)", borderRadius: stateHeight * 2, right: stateHeight * 2 - stateWidth + speedLoToWidth, height: stateHeight * 2, top: -stateHeight / 2 }}></View>
{
speedTouch &&
<View
style={{ position: "absolute", top: topContsTop + 20, width: stateWidth, alignItems: "center" }}
>
<View
style={{ justifyContent: 'center', flexDirection: 'row', backgroundColor: "rgba(0,0,0,0.6)", paddingVertical: 4, paddingHorizontal: 8, borderRadius: 4 }}
>
<AnFastSvg
isSolTouch={this.isSolTouch}
videoRate={videoRate}
solText={this.props.solText}
fastText={this.props.fastText}
/>
</View>
</View>
}
</View>
</TouchableOpacity>
</View>
{this.state.showConts ?
<Animated.View
style={{ position: "absolute", left: 0, right: 0, top: 0, opacity: this.state.opacity, height: 30 }}
>
{/* 阴影 */}
<LinearGradient colors={['rgba(0,0,0,0.4)', 'rgba(0,0,0,0.1)', 'rgba(0,0,0,0)']} style={{ height: LinearGradientHeight, width: stateWidth }}></LinearGradient>
{/* 返回键 */}
{preShowSmallCont && <TouchableOpacity
style={{ position: "absolute", top: topContsTop, left: smallP ? 5 : this.props.continuous ? 45 : 5, padding: 10, zIndex: 999, flexDirection: 'row' }}
//如果是全屏 点击返回键是切换到小屏 反之返回上个页面
onPress={() => {
if (this.state.smallP) {
this.props.onSmallBack && this.props.onSmallBack()
// this.props.navigation.goBack()
} else { this.changeSmallBox() }
}}
>
<SvgVideoBack height="20" width="20" />
<Text
style={{ color: "#fff", fontSize: 15, paddingLeft: 10, maxWidth: smallP ? width / 3 : height / 3, ...this.props.backVideoNameStyle }}
numberOfLines={1}
>
{this.props.backVideoName ? this.props.backVideoName : ''}
</Text>
</TouchableOpacity>}
{/* 收藏|更多 */}
<View style={{ position: "absolute", top: topContsTop, right: smallP ? 5 : this.props.continuous ? 45 : 5, flexWrap: "nowrap", flexDirection: "row", zIndex: 10, }}>
<TouchableOpacity style={{ padding: 8 }}
onPress={this.props.onStore && this.props.onStore}
>
{this.props.storeComponent ? this.props.storeComponent() : <SvgVideoScang height="20" width="20" />}
</TouchableOpacity>
<TouchableOpacity style={{ padding: 8, marginLeft: 1, }}
onPress={this.props.onMoreFun && this.props.onMoreFun()}
>
{this.props.moreSetting ? this.props.moreSetting() : <SvgVideoSetting height="20" width="20" />}
</TouchableOpacity>
</View>
</Animated.View >
:
null}
{showOpenVip && this.props.VIPCONTS
&&
<ShouldPermissionTitle openViptipBOTTOM={bottomContsBottom + 40} />}
{//控件隐藏时候,最下面显示的进度
this.state.showConts ? null :
<BottomSpeed
bottomSpeedColor={this.props.bottomSpeedColor}
playhideContsDotX={this.playhideContsDotX}
admRePlay={this.state.admRePlay}
{...this.state}
/>
}
{this.props.lockControl &&
<Lock
ref={(ref) => this.LockRef = ref}
showContsfun={(e) => { this.setState({ showConts: e }) }}
{...this.state}
/>
}
{
this.state.showConts &&
<LinearGradient
colors={['rgba(0,0,0,0)', 'rgba(0,0,0,0.1)', 'rgba(0,0,0,0.4)']}
style={{ height: LinearGradientHeight, width: stateWidth, position: "absolute", bottom: this.state.smallP ? 0 : -bottomContsBottom }}
></LinearGradient>
}
{
this.state.showConts ?
<Animated.View
style={{ width: stateWidth, bottom: bottomContsBottom, opacity: this.state.opacity, zIndex: 99999, position: "absolute", }}>
<View style={{ flexDirection: "row", flexWrap: "nowrap" }}>
{/* 播放暂停 */}
{
!this.props.continuous ? (this.state.paused
?
<TouchableOpacity activeOpacity={1} style={s.touchs} onPress={() => {
if (!showOpenVip) {
this.rePlay(true, false)
}
}}>
<SvgVideoPlay height="20" width="20" />
</TouchableOpacity>
:
<TouchableOpacity activeOpacity={1} style={s.touchs} onPress={this.btnPasuedfun}>
<SvgVideoStop height="20" width="20" />
</TouchableOpacity>
)
:
smallP && (this.state.paused
?
<TouchableOpacity activeOpacity={1} style={s.touchs} onPress={() => {
if (!showOpenVip) {
this.rePlay(true, false)
}
}}>
<SvgVideoPlay height="20" width="20" />
</TouchableOpacity>
:
<TouchableOpacity
activeOpacity={1}
style={s.touchs}
onPress={this.btnPasuedfun}
>
<SvgVideoStop height="20" width="20" />
</TouchableOpacity>
)
}
{/* 进度条 缓存条*/}
<Speed
{...this.state}
color={this.props.speedColor}
cachColor={this.props.cachColor}
dotColor={this.props.dotColor}
dotBorderColor={this.props.dotBorderColor}
allSpeedColor={this.props.allSpeedColor}
admRePlay={this.state.admRePlay}
nowTime={this.nowTime}
panHandlers={this._panSpeeDot.panHandlers}
allTime={allTime}
ref={child => this.dotspeed = child}
pl