CusVideo.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. import React, { Component } from "react";
  2. import {
  3. Platform,
  4. Text,
  5. View,
  6. ImageBackground,
  7. Button,
  8. Image,
  9. TouchableOpacity,
  10. StyleSheet
  11. } from "react-native";
  12. import { createStackNavigator, createAppContainer } from "react-navigation";
  13. import Video from "react-native-video";
  14. import SeekBar from "../components/SeekBar";
  15. const instructions = Platform.select({
  16. ios: "Press Cmd+R to reload,\n" + "Cmd+D or shake for dev menu",
  17. android:
  18. "Double tap R on your keyboard to reload,\n" +
  19. "Shake or press menu button for dev menu"
  20. });
  21. type Props = {};
  22. export default class CusVideo extends React.Component {
  23. state = {
  24. rate: 1,
  25. volume: 1,
  26. muted: false,
  27. resizeMode: "stretch",
  28. duration: 0.0,
  29. currentTime: 0.0,
  30. paused: false,
  31. wheel: false,
  32. player_status_icon: require("../images/video/start.png")
  33. };
  34. render() {
  35. return (
  36. <View style={this.props.style}>
  37. <Video
  38. style={{ flex: 1 }}
  39. source={{
  40. uri: this.props.uri
  41. }}
  42. ref={ref => {
  43. this.player = ref;
  44. }}
  45. // poster={this.props.poster}
  46. resizeMode={this.state.resizeMode}
  47. // posterResizeMode={this.state.resizeMode}
  48. onBuffer={this.onBuffer}
  49. rate={this.state.rate} //播放速率
  50. paused={this.state.paused} //暂停
  51. volume={this.state.volume} //调节音量
  52. muted={this.state.muted} //控制音频是否静音
  53. resizeMode={this.state.resizeMode} //缩放模式
  54. onLoadStart={this.loadStart} // 当视频开始加载时的回调函数
  55. onLoad={this.onLoad} //加载媒体并准备播放时调用的回调函数。
  56. onProgress={this.onProgress} //视频播放过程中每个间隔进度单位调用的回调函数
  57. onEnd={this.onEnd} //视频播放结束时的回调函数
  58. onAudioBecomingNoisy={this.onAudioBecomingNoisy} //音频变得嘈杂时的回调 - 应暂停视频
  59. onAudioFocusChanged={this.onAudioFocusChanged} //音频焦点丢失时的回调 - 如果焦点丢失则暂停
  60. repeat={this.state.wheel} //确定在到达结尾时是否重复播放视频。
  61. onError={this.onError} // 当视频不能加载,或出错后的回调函数
  62. playInBackground={false} // 当app转到后台运行的时候,播放是否暂停
  63. playWhenInactive={true} // [iOS] Video continues to play when control or notification center are shown. 仅适用于IOS
  64. />
  65. <View style={[styles.player_controller]}>
  66. <View
  67. style={{
  68. flex: 1,
  69. alignItems: "center"
  70. }}
  71. >
  72. {/* 暂停播放按钮 */}
  73. <TouchableOpacity
  74. //点击事件放在这个组件里才管用
  75. style={{
  76. justifyContent: "center",
  77. width: "100%",
  78. height: "100%"
  79. }}
  80. onPress={() => this.play()}
  81. >
  82. <Image
  83. style={[styles.player_pause_icon]}
  84. source={this.state.player_status_icon}
  85. />
  86. </TouchableOpacity>
  87. </View>
  88. <View style={{ flex: 2 }}>
  89. {/* //左侧当前播放时长 */}
  90. <Text style={[styles.player_time]}>
  91. {formatTime(this.state.currentTime)}
  92. </Text>
  93. </View>
  94. <View
  95. style={{
  96. flex: 9,
  97. overflow: "hidden"
  98. }}
  99. >
  100. {/* //中间进度条 */}
  101. <SeekBar
  102. style={{ flex: 1 }}
  103. ref={view => (this.seekbar = view)}
  104. //必须带此方法,作为滑动之后抬起的回调
  105. touchUpCallBack={this.touch_up_callback.bind(this)}
  106. />
  107. </View>
  108. <View style={{ flex: 2 }}>
  109. {/* //右侧总时长 */}
  110. <Text style={[styles.player_time]}>
  111. {formatTime(this.state.duration)}
  112. </Text>
  113. </View>
  114. <View
  115. style={{
  116. flex: 1,
  117. alignItems: "center"
  118. }}
  119. >
  120. <TouchableOpacity
  121. style={{
  122. justifyContent: "center",
  123. width: "100%",
  124. height: "100%"
  125. }}
  126. onPress={() => this.presentFullscreenPlayer()}
  127. >
  128. {/* //放大按钮 */}
  129. <Image
  130. style={[styles.fullscreen_icon]}
  131. source={require("../images/video/fullscreen.png")}
  132. />
  133. </TouchableOpacity>
  134. </View>
  135. </View>
  136. </View>
  137. );
  138. }
  139. loadStart() {
  140. // alert("loadStart");
  141. }
  142. onBuffer({ isBuffering }: { isBuffering: boolean }) {
  143. //true为正在加载,false为没有加载,此处给loading提示
  144. console.log("isBuffering:" + isBuffering);
  145. }
  146. onLoad = data => {
  147. //获取的是秒数
  148. this.setState({ duration: data.duration });
  149. this.seekbar.setMax(data.duration);
  150. };
  151. onProgress = data => {
  152. this.setState({
  153. currentTime: data.currentTime
  154. });
  155. this.seekbar.setProgress(this.state.currentTime);
  156. };
  157. onError() {
  158. alert("播放器异常");
  159. }
  160. onEnd() {
  161. alert("播放结束");
  162. }
  163. play() {
  164. if (this.state.paused) {
  165. this.start();
  166. } else {
  167. this.pause();
  168. }
  169. }
  170. pause() {
  171. this.setState({
  172. paused: true,
  173. player_status_icon: require("../images/video/start.png")
  174. });
  175. this.player_icon_index = 1;
  176. }
  177. start() {
  178. this.setState({
  179. paused: false,
  180. player_status_icon: require("../images/video/pause.png")
  181. });
  182. this.player_icon_index = 0;
  183. }
  184. showToast(params) {
  185. // ToastExample.message(params);
  186. ToastExample.show(params, ToastExample.SHORT);
  187. }
  188. seekTo(progress) {
  189. this.player.seek(progress);
  190. }
  191. presentFullscreenPlayer() {
  192. // alert("点击调用全屏");
  193. this.props.videofullScreenPlayer();
  194. console.log("currentTime:" + this.state.currentTime);
  195. setTimeout(() => {
  196. this.seekbar.setProgress(this.state.currentTime);
  197. }, 10);
  198. }
  199. touch_up_callback(progress) {
  200. //抬起之后,获取算出来的progress
  201. this.setState({
  202. currentTime: progress
  203. });
  204. this.seekTo(progress);
  205. }
  206. refreshVideo() {
  207. this.setState({
  208. duration: 0,
  209. currentTime: 0
  210. });
  211. }
  212. }
  213. const styles = StyleSheet.create({
  214. player_controller: {
  215. flexDirection: "row",
  216. position: "absolute",
  217. width: "100%",
  218. height: 50,
  219. alignItems: "center",
  220. justifyContent: "center",
  221. bottom: 0
  222. },
  223. player_pause_icon: {
  224. width: "80%",
  225. resizeMode: "center",
  226. height: "40%",
  227. justifyContent: "center",
  228. alignItems: "center",
  229. left: 5
  230. },
  231. fullscreen_icon: {
  232. width: "80%",
  233. resizeMode: "center",
  234. height: "30%",
  235. justifyContent: "center",
  236. alignItems: "center"
  237. },
  238. player_time: {
  239. fontSize: 18,
  240. color: "white",
  241. alignItems: "center",
  242. justifyContent: "center",
  243. textAlignVertical: "center",
  244. textAlign: "center"
  245. }
  246. });
  247. /**
  248. * 将秒转换为 分:秒
  249. * s int 秒数
  250. */
  251. function formatTime(s) {
  252. //计算分钟
  253. //算法:将秒数除以60,然后下舍入,既得到分钟数
  254. var h;
  255. h = Math.floor(s / 60);
  256. //计算秒
  257. //算法:取得秒%60的余数,既得到秒数
  258. s = Math.round(s % 60);
  259. //将变量转换为字符串
  260. h += "";
  261. s += "";
  262. //如果只有一位数,前面增加一个0
  263. h = h.length == 1 ? "0" + h : h;
  264. s = s.length == 1 ? "0" + s : s;
  265. return h + ":" + s;
  266. }