123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622 |
- import React, { Component } from "react";
- import {
- Platform,
- Text,
- View,
- ImageBackground,
- Button,
- Image,
- TouchableOpacity,
- PanResponder,
- StyleSheet
- } from "react-native";
- import { createStackNavigator, createAppContainer } from "react-navigation";
- import Video from "react-native-video";
- import SeekBar from "../components/SeekBar";
- const instructions = Platform.select({
- ios: "Press Cmd+R to reload,\n" + "Cmd+D or shake for dev menu",
- android:
- "Double tap R on your keyboard to reload,\n" +
- "Shake or press menu button for dev menu"
- });
- type Props = {};
- export default class CusVideo extends React.Component {
- constructor(props) {
- super(props);
- this.pressStatus = false;
- this.progress = 0;
- this.time_hideController;
- }
- config = {
- changeX: 0,
- changeY: 0,
- xDiff: 0,
- yDiff: 0
- };
- state = {
- player_status_icon: require("../images/video/start.png"),
- rate: 1,
- volume: 1,
- muted: false,
- resizeMode: "stretch",
- duration: 0.0,
- currentTime: 0.0,
- paused: true,
- onBuffer: true,
- wheel: false,
- isFull: false,
- needback: this.props.needback,
- show_controller: true,
- show_loading: true,
- loading_arr: [
- require("../images/video/loading1.png"),
- require("../images/video/loading2.png"),
- require("../images/video/loading3.png"),
- require("../images/video/loading4.png"),
- require("../images/video/loading5.png"),
- require("../images/video/loading6.png"),
- require("../images/video/loading7.png"),
- require("../images/video/loading8.png"),
- require("../images/video/loading9.png"),
- require("../images/video/loading10.png"),
- require("../images/video/loading11.png"),
- require("../images/video/loading12.png"),
- require("../images/video/loading13.png"),
- require("../images/video/loading14.png"),
- require("../images/video/loading15.png"),
- require("../images/video/loading16.png"),
- require("../images/video/loading17.png"),
- require("../images/video/loading18.png"),
- require("../images/video/loading19.png"),
- require("../images/video/loading20.png")
- ]
- };
- render() {
- if (!this.props.show) {
- return null;
- }
- return (
- <View style={[this.props.style, { overflow: "hidden" }]}>
- <Video
- {...this.videotouch.panHandlers}
- style={{ flex: 1 }}
- source={{
- uri: this.props.uri
- }}
- ref={ref => {
- this.player = ref;
- }}
- // poster={this.props.poster}
- resizeMode={[this.state.resizeMode]}
- // posterResizeMode={this.state.resizeMode}
- onBuffer={this.onBuffer.bind(this)}
- rate={this.state.rate} //播放速率
- paused={this.state.paused} //暂停
- volume={this.state.volume} //调节音量
- muted={this.state.muted} //控制音频是否静音
- resizeMode={this.state.resizeMode} //缩放模式
- onLoadStart={this.loadStart} // 当视频开始加载时的回调函数
- onLoad={this.onLoad} //加载媒体并准备播放时调用的回调函数。
- onProgress={this.onProgress} //视频播放过程中每个间隔进度单位调用的回调函数
- onAudioBecomingNoisy={this.onAudioBecomingNoisy} //音频变得嘈杂时的回调 - 应暂停视频
- onAudioFocusChanged={this.onAudioFocusChanged} //音频焦点丢失时的回调 - 如果焦点丢失则暂停
- repeat={this.state.wheel} //确定在到达结尾时是否重复播放视频。
- onError={this.onError.bind(this)} // 当视频不能加载,或出错后的回调函数
- onEnd={this.onEnd.bind(this)} //视频播放结束时的回调函数
- playInBackground={false} // 当app转到后台运行的时候,播放是否暂停
- playWhenInactive={true} // [iOS] Video continues to play when control or notification center are shown. 仅适用于IOS
- />
- <View
- style={{
- position: "absolute",
- width: "100%",
- height: "100%",
- alignItems: "center",
- justifyContent: "center"
- }}
- >
- <Loading
- loading_arr={this.state.loading_arr}
- show={this.state.show_loading}
- />
- </View>
- <TopController
- ref={view => (this.topcontroller = view)}
- needback={this.state.needback}
- videoback={this.videoBackClick.bind(this)}
- />
- <BottomController
- ref={view => (this.bottomcontroller = view)}
- show={this.state.show_controller}
- touch_up_callback={this.touch_up_callback.bind(this)}
- full_click={this.presentFullscreenPlayer.bind(this)}
- play_click={this.play.bind(this)}
- duration={this.state.duration}
- currentTime={this.state.currentTime}
- player_status_icon={this.state.player_status_icon}
- />
- </View>
- );
- }
- componentWillMount() {
- this.videotouch = PanResponder.create({
- onStartShouldSetPanResponder: (evt, gestureState) => true,
- onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
- onMoveShouldSetPanResponder: (evt, gestureState) => true,
- onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
- onPanResponderGrant: (evt, gestureState) => {
- this.pressStatus = true;
- this.config.changeY = evt.nativeEvent.pageY;
- this.config.changeX = evt.nativeEvent.pageX;
- if (this.state.show_controller) {
- this.hideController();
- } else {
- this.showController();
- }
- },
- onPanResponderStart: (evt, gestureState) => {
- this.pressStatus = true;
- },
- onPanResponderMove: (evt, gestureState) => {
- this.config.yDiff = evt.nativeEvent.pageY - this.config.changeY;
- this.config.xDiff = evt.nativeEvent.pageX - this.config.changeX;
- this.config.changeY = evt.nativeEvent.pageY;
- this.config.changeX = evt.nativeEvent.pageX;
- },
- onPanResponderEnd: (evt, gestureState) => {
- this.pressStatus = true;
- },
- onPanResponderTerminationRequest: (evt, gestureState) => true,
- onPanResponderRelease: (evt, gestureState) => {
- if (this.pressStatus) {
- this.props.onPress && this.props.onPress();
- }
- },
- onPanResponderTerminate: (evt, gestureState) => {
- // 另一个组件已经成为了新的响应者,所以当前手势将被取消。
- },
- onShouldBlockNativeResponder: (evt, gestureState) => {
- // 返回一个布尔值,决定当前组件是否应该阻止原生组件成为JS响应者
- // 默认返回true。目前暂时只支持android。
- //基于业务交互场景,如果这里使用js事件处理,会导致容器不能左右滑动。所以设置成false.
- return false;
- }
- });
- }
- componentWillUnmount() {
- clearTimeout(this.time_hideController);
- }
- loadStart() {
- // alert("loadStart");
- }
- onBuffer({ isBuffering }: { isBuffering: boolean }) {
- //true为正在加载,false为没有加载,此处给loading提示
- this.setState({
- onBuffer: isBuffering,
- show_loading: isBuffering
- });
- }
- isPlaying() {
- if (this.state.onBuffer == false && this.state.paused == false) {
- return true;
- }
- return false;
- }
- onLoad = data => {
- //获取的是秒数
- this.setState({ duration: data.duration });
- // this.bottomcontroller.setMax(data.duration);
- };
- onProgress = data => {
- this.setState({
- currentTime: data.currentTime
- });
- if (this.state.show_controller && this.props.show) {
- this.bottomcontroller.setProgress(this.state.currentTime);
- this.bottomcontroller.setMax(this.state.duration);
- }
- };
- onError() {
- if (this.props.onEnd == undefined) {
- } else {
- this.props.onError();
- }
- }
- onEnd() {
- if (this.props.onEnd == undefined) {
- } else {
- this.props.onEnd();
- }
- }
- play() {
- //controller的play点击无法换图...
- if (this.state.paused) {
- this.start();
- } else {
- this.pause();
- }
- }
- pause() {
- this.setState({
- paused: true,
- player_status_icon: require("../images/video/start.png")
- });
- this.player_icon_index = 1;
- }
- start() {
- this.setState({
- paused: false,
- player_status_icon: require("../images/video/pause.png")
- });
- this.player_icon_index = 0;
- if (this.state.show_controller) {
- this.time_hideController = setTimeout(() => {
- this.setState({
- show_controller: false
- // needback: false
- });
- this.bottomcontroller.setBottom(-50);
- this.topcontroller.setTop(-50);
- }, 5000);
- }
- }
- seekTo(progress) {
- this.player.seek(progress);
- }
- presentFullscreenPlayer() {
- if (this.state.isFull) {
- this.setState({
- isFull: false,
- needback: this.props.needback
- });
- } else {
- this.setState({
- isFull: true,
- needback: true
- });
- }
- this.props.videofullScreenPlayer();
- this.bottomcontroller.setProgress(this.state.currentTime);
- }
- touch_up_callback(progress) {
- //抬起之后,获取算出来的progress
- this.setState({
- currentTime: progress
- });
- this.seekTo(progress);
- }
- refreshVideo() {
- this.setState({
- duration: 0,
- currentTime: 0
- });
- this.bottomcontroller.setProgress(0);
- }
- videoBackClick() {
- // if (this.props.needback != undefined && this.props.needback) {
- // }
- if (this.state.isFull) {
- //全屏状态下,变小屏
- this.presentFullscreenPlayer();
- } else {
- this.props.videoback();
- }
- }
- showController() {
- clearTimeout(this.time_hideController);
- this.setState({
- show_controller: true
- // needback: this.props.needback
- });
- this.bottomcontroller.setBottom(0);
- this.bottomcontroller.setProgress(this.state.currentTime);
- this.topcontroller.setTop(0);
- this.time_hideController = setTimeout(() => {
- this.setState({
- show_controller: false
- // needback: false
- });
- this.bottomcontroller.setBottom(-50);
- this.topcontroller.setTop(-50);
- }, 5000);
- }
- hideController() {
- this.setState({
- show_controller: false
- // needback: false
- });
- this.bottomcontroller.setBottom(-50);
- this.topcontroller.setTop(-50);
- }
- componentWillUnmount() {
- clearTimeout(this.time_hideController);
- }
- }
- /**
- * 将秒转换为 分:秒
- * s int 秒数
- */
- function formatTime(s) {
- //计算分钟
- //算法:将秒数除以60,然后下舍入,既得到分钟数
- var h;
- h = Math.floor(s / 60);
- //计算秒
- //算法:取得秒%60的余数,既得到秒数
- s = Math.round(s % 60);
- //将变量转换为字符串
- h += "";
- s += "";
- //如果只有一位数,前面增加一个0
- h = h.length == 1 ? "0" + h : h;
- s = s.length == 1 ? "0" + s : s;
- return h + ":" + s;
- }
- class TopController extends Component {
- state = {
- controller_top: 0
- };
- render() {
- if (this.props.needback == false) {
- return null;
- }
- return (
- <View
- style={[styles.player_controller, { top: this.state.controller_top }]}
- >
- <View
- style={{
- flex: 1,
- alignItems: "center"
- }}
- >
- <TouchableOpacity
- //点击事件放在这个组件里才管用
- style={{
- justifyContent: "center",
- width: "100%",
- height: "100%"
- }}
- onPress={() => this.props.videoback()}
- >
- <Image
- style={[styles.player_pause_icon]}
- source={require("../images/video/back.png")}
- />
- </TouchableOpacity>
- </View>
- <View style={{ flex: 2 }} />
- <View
- style={{
- flex: 9,
- overflow: "hidden"
- }}
- />
- <View style={{ flex: 2 }} />
- <View
- style={{
- flex: 1,
- alignItems: "center"
- }}
- />
- </View>
- );
- }
- setTop(top) {
- this.setState({
- controller_top: top
- });
- }
- }
- class Loading extends Component {
- constructor(props) {
- super(props);
- this.loading_index = 0;
- }
- state = {
- loading_img: this.props.loading_arr[0]
- };
- render() {
- if (this.props.show) {
- return (
- <Image
- source={this.state.loading_img}
- style={{ width: 100, height: 20 }}
- />
- );
- } else {
- return null;
- }
- }
- componentWillMount() {
- this.changeIndex();
- }
- componentWillUnmount() {
- clearTimeout(this.changeindex);
- }
- changeIndex() {
- this.changeindex = setTimeout(() => {
- if (this.loading_index > this.props.loading_arr.length - 2) {
- this.loading_index = 0;
- } else {
- this.loading_index = this.loading_index + 1;
- }
- this.setState({
- loading_img: this.props.loading_arr[this.loading_index]
- });
- this.changeIndex();
- }, 1);
- }
- }
- class BottomController extends Component {
- state = {
- controller_bottom: 0
- };
- render() {
- return (
- <View
- style={[
- styles.player_controller,
- { bottom: this.state.controller_bottom }
- ]}
- >
- <View
- style={{
- flex: 1,
- alignItems: "center"
- }}
- >
- {/* 暂停播放按钮 */}
- <TouchableOpacity
- //点击事件放在这个组件里才管用
- style={{
- justifyContent: "center",
- width: "100%",
- height: "100%"
- }}
- onPress={() => this.props.play_click()}
- >
- <Image
- style={[styles.player_pause_icon]}
- source={this.props.player_status_icon}
- />
- </TouchableOpacity>
- </View>
- <View style={{ flex: 2 }}>
- {/* //左侧当前播放时长 */}
- <Text style={[styles.player_time]}>
- {formatTime(this.props.currentTime)}
- </Text>
- </View>
- <View
- style={{
- flex: 9,
- overflow: "hidden"
- }}
- >
- {/* //中间进度条 */}
- <SeekBar
- style={{ flex: 1 }}
- ref={view => (this.seekbar = view)}
- //必须带此方法,作为滑动之后抬起的回调
- touchUpCallBack={this.props.touch_up_callback}
- />
- </View>
- <View style={{ flex: 2 }}>
- {/* //右侧总时长 */}
- <Text style={[styles.player_time]}>
- {formatTime(this.props.duration)}
- </Text>
- </View>
- <View
- style={{
- flex: 1,
- alignItems: "center"
- }}
- >
- <TouchableOpacity
- style={{
- justifyContent: "center",
- width: "100%",
- height: "100%"
- }}
- onPress={() => this.props.full_click()}
- >
- {/* //放大按钮 */}
- <Image
- style={[styles.fullscreen_icon]}
- source={require("../images/video/fullscreen.png")}
- />
- </TouchableOpacity>
- </View>
- </View>
- );
- }
- setMax(duration) {
- this.seekbar.setMax(duration);
- }
- getMax() {
- return this.seekbar.getMax();
- }
- setBottom(bottom) {
- this.setState({
- controller_bottom: bottom
- });
- }
- setProgress(currentTime) {
- this.seekbar.setProgress(currentTime);
- }
- }
- const styles = StyleSheet.create({
- player_controller: {
- flexDirection: "row",
- position: "absolute",
- width: "100%",
- height: 50,
- alignItems: "center",
- justifyContent: "center"
- },
- player_pause_icon: {
- width: "80%",
- resizeMode: "center",
- height: "40%",
- justifyContent: "center",
- alignItems: "center",
- left: 5
- },
- fullscreen_icon: {
- width: "80%",
- resizeMode: "center",
- height: "30%",
- justifyContent: "center",
- alignItems: "center"
- },
- player_time: {
- fontSize: 16,
- color: "white",
- alignItems: "center",
- justifyContent: "center",
- textAlignVertical: "center",
- textAlign: "center"
- }
- });
- /**
- 使用方法
- <CusVideo
- show={this.state.video_show} //是否显示
- uri={this.state.video_uri} //播放路径
- ref={view => (this.video = view)} //设置ID
- needback={false}
- videoback={() => alert("videoback")}
- videofullScreenPlayer={this.fullScreenPlayer.bind(this)}
- style={{
- left: this.state.x,
- top: this.state.y,
- width: this.state.video_width,
- height: this.state.video_height,
- overflow: "hidden",
- position: "absolute"
- }}
- />
- */
|