PlayerGesture.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import React, { useState, useEffect } from 'react';
  2. import {
  3. View,
  4. Text,
  5. StyleSheet,
  6. Dimensions,
  7. PanResponder,
  8. ScrollView,
  9. Image,
  10. Platform,
  11. StatusBar
  12. } from 'react-native';
  13. import { Slider, Icon } from 'react-native-elements';
  14. import Animated, { Easing } from 'react-native-reanimated';
  15. import { State, PanGestureHandler } from 'react-native-gesture-handler';
  16. import { getStatusBarHeight } from '../utils/StatusBarHeight';
  17. import C from 'rn-class';
  18. import PlayerControls from '../components/PlayerControls';
  19. import PlayerContents from '../components/PlayerContents';
  20. const { width, height } = Dimensions.get('window');
  21. const statusBarHeight = getStatusBarHeight();
  22. const minHeight = height*0.1;
  23. const midBound = height - height/2.5;
  24. const upperBound = midBound + minHeight;
  25. const {
  26. Value,
  27. event,
  28. Extrapolate,
  29. Clock,
  30. cond,
  31. eq,
  32. set,
  33. add,
  34. sub,
  35. multiply,
  36. lessThan,
  37. clockRunning,
  38. startClock,
  39. spring,
  40. stopClock,
  41. interpolate,
  42. timing,
  43. neq
  44. } = Animated;
  45. const shadow = {
  46. alignItems: 'center',
  47. shadowColor: 'black',
  48. shadowOffset: { width: 0, height: 0 },
  49. shadowOpacity: 0.18,
  50. shadowRadius: 2
  51. };
  52. const shadow2 = {
  53. alignItems: 'center',
  54. shadowColor: '#000',
  55. shadowOffset: {
  56. width: 0,
  57. height: 7
  58. },
  59. shadowOpacity: 0.41,
  60. shadowRadius: 9.11
  61. //elevation: 14
  62. };
  63. function runSpring(clock, value, dest) {
  64. const state = {
  65. finished: new Value(0),
  66. velocity: new Value(0),
  67. position: new Value(0),
  68. time: new Value(0)
  69. };
  70. const config = {
  71. damping: 20,
  72. mass: 1,
  73. stiffness: 100,
  74. overshootClamping: false,
  75. restSpeedThreshold: 1,
  76. restDisplacementThreshold: 0.5,
  77. toValue: new Value(0)
  78. };
  79. return [
  80. cond(clockRunning(clock), 0, [
  81. set(state.finished, 0),
  82. set(state.velocity, 0),
  83. set(state.position, value),
  84. set(config.toValue, dest),
  85. startClock(clock)
  86. ]),
  87. spring(clock, state, config),
  88. cond(state.finished, stopClock(clock)),
  89. state.position
  90. ];
  91. }
  92. const Player = props => {
  93. const translationY = new Value(0);
  94. const velocityY = new Value(0);
  95. const offsetY = new Value(0);
  96. const offsetY2 = new Value(0);
  97. const gestureState = new Value(State.UNDETERMINED);
  98. const onGestureEvent = event(
  99. [
  100. {
  101. nativeEvent: {
  102. translationY,
  103. velocityY,
  104. state: gestureState
  105. }
  106. }
  107. ],
  108. { useNativeDriver: true }
  109. );
  110. const clockY = new Clock();
  111. const finalTranslateY = add(translationY, multiply(0.2, velocityY));
  112. const snapPoint = cond(
  113. lessThan(finalTranslateY, sub(offsetY, height / 4)),
  114. 0,
  115. upperBound
  116. );
  117. const ty = cond(
  118. eq(gestureState, State.END),
  119. [
  120. set(
  121. translationY,
  122. runSpring(clockY, add(offsetY, translationY), snapPoint)
  123. ),
  124. set(offsetY, translationY),
  125. translationY
  126. ],
  127. [
  128. cond(eq(gestureState, State.BEGAN), stopClock(clockY)),
  129. add(offsetY, translationY)
  130. ]
  131. );
  132. const translateY = add(ty, offsetY2);
  133. const opacity = interpolate(translateY, {
  134. inputRange: [0, midBound - 100],
  135. outputRange: [1, 0],
  136. extrapolate: Extrapolate.CLAMP
  137. });
  138. const statusBarOpacity = interpolate(translateY, {
  139. inputRange: [0, statusBarHeight],
  140. outputRange: [1, 0],
  141. extrapolateLeft: Extrapolate.CLAMP
  142. });
  143. const playContainerWidth = interpolate(translateY, {
  144. inputRange: [0, midBound],
  145. outputRange: [width, width - 16],
  146. extrapolate: Extrapolate.CLAMP
  147. });
  148. const playerContainerHeight = interpolate(translateY, {
  149. inputRange: [0, midBound],
  150. outputRange: [height, 0],
  151. extrapolate: Extrapolate.CLAMP
  152. });
  153. const videoWidth = interpolate(translateY, {
  154. inputRange: [0, midBound, upperBound],
  155. outputRange: [width, width - 16, width / 4],
  156. extrapolate: Extrapolate.CLAMP
  157. });
  158. const videoHeight = interpolate(translateY, {
  159. inputRange: [0, midBound, upperBound],
  160. outputRange: [width / 1.78, minHeight * 1.3, minHeight],
  161. extrapolate: Extrapolate.CLAMP
  162. });
  163. const playerControlOpaciy = interpolate(translateY, {
  164. inputRange: [midBound, upperBound],
  165. outputRange: [0, 1],
  166. extrapolate: Extrapolate.CLAMP
  167. });
  168. const playerBoderRadius = interpolate(translateY, {
  169. inputRange: [midBound, upperBound],
  170. outputRange: [0, 15],
  171. extrapolate: Extrapolate.CLAMP
  172. });
  173. const mainPlayerContainerHeight = interpolate(translateY, {
  174. inputRange: [0, midBound, upperBound],
  175. outputRange: [height, minHeight * 1.3, minHeight],
  176. extrapolate: Extrapolate.CLAMP
  177. });
  178. useEffect(() => {
  179. return () => {};
  180. }, []);
  181. const slideUp = () => {};
  182. return (
  183. <PanGestureHandler
  184. onHandlerStateChange={onGestureEvent}
  185. activeOffsetY={[-10, 10]}
  186. {...{ onGestureEvent }}
  187. >
  188. <Animated.View
  189. style={{
  190. ...StyleSheet.absoluteFillObject,
  191. zIndex: 10,
  192. marginTop: statusBarHeight,
  193. transform: [{ translateY }],
  194. alignItems: 'center',
  195. height: mainPlayerContainerHeight,
  196. }}
  197. >
  198. <Animated.View
  199. style={{
  200. padding: 5,
  201. backgroundColor: 'white',
  202. width: playContainerWidth,
  203. borderRadius: playerBoderRadius
  204. }}
  205. >
  206. <Animated.View
  207. style={[
  208. Platform.OS === 'android'
  209. ? { borderColor: '#eee' }
  210. : { borderColor: 'white' },
  211. {
  212. ...StyleSheet.absoluteFillObject,
  213. borderWidth: 1,
  214. borderRadius: 15,
  215. opacity: playerControlOpaciy,
  216. backgroundColor: 'white'
  217. },
  218. shadow2
  219. ]}
  220. >
  221. <PlayerControls
  222. {...props}
  223. title={props.Pages.subtitle}
  224. slideup={slideUp}
  225. closePlayer={props.closePlayer}
  226. />
  227. </Animated.View>
  228. <Animated.View style={{ width: videoWidth, height: videoHeight }}>
  229. <Image
  230. resizeMode="contain"
  231. style={{ flex: 1, width: null, height: null }}
  232. source={props.Pages.img}
  233. />
  234. </Animated.View>
  235. </Animated.View>
  236. <Animated.View
  237. style={{
  238. backgroundColor: 'white',
  239. width: playContainerWidth,
  240. height: playerContainerHeight
  241. }}
  242. >
  243. <Animated.View style={{ opacity }}>
  244. <PlayerContents {...props} />
  245. </Animated.View>
  246. </Animated.View>
  247. </Animated.View>
  248. </PanGestureHandler>
  249. );
  250. };
  251. export default Player;