UNPKG

@td-design/react-native-picker

Version:

基于 @td-design/react-native 的 picker 组件

128 lines (126 loc) 4.28 kB
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } import React from 'react'; import { StyleSheet, View } from 'react-native'; import { PanGestureHandler } from 'react-native-gesture-handler'; import Animated, { Easing, Extrapolate, interpolate, runOnJS, useAnimatedGestureHandler, useAnimatedStyle, useDerivedValue, useSharedValue, withTiming } from 'react-native-reanimated'; export default function WheelPicker(_ref) { let { itemHeight = 40, data, visibleRest = 5, textStyle, contentContainerStyle, indicatorBgColor = 'rgba(0, 0, 0, 0.3)', value, onChange, ...props } = _ref; const initialIndex = value ? data.findIndex(item => item.value === value) : 0; const translateY = useSharedValue(-itemHeight * initialIndex); const snapPoints = new Array(data.length).fill(0).map((_, index) => -itemHeight * index); const timingConfig = { duration: 1000, easing: Easing.bezier(0.35, 1, 0.35, 1) }; const wrapper = index => { onChange === null || onChange === void 0 ? void 0 : onChange(data[index], index); }; const onGestureEvent = useAnimatedGestureHandler({ onStart(_, ctx) { ctx.y = translateY.value; }, onActive(event, ctx) { translateY.value = ctx.y + event.translationY; }, onEnd(event) { const snapPointsY = snapPoint(translateY.value, event.velocityY, snapPoints); const index = Math.abs(snapPointsY / itemHeight); translateY.value = withTiming(snapPointsY, timingConfig); runOnJS(wrapper)(index); } }); const animatedStyle = useAnimatedStyle(() => ({ transform: [{ translateY: translateY.value }] })); return /*#__PURE__*/React.createElement(View, _extends({}, props, { style: styles.container }), /*#__PURE__*/React.createElement(PanGestureHandler, { onGestureEvent: onGestureEvent }, /*#__PURE__*/React.createElement(Animated.View, { style: [animatedStyle, contentContainerStyle, { height: itemHeight * visibleRest, paddingTop: (itemHeight * visibleRest - itemHeight) / 2 }] }, data.map((data, index) => /*#__PURE__*/React.createElement(PickerItem, { key: index, translateY: translateY, index: index, itemHeight: itemHeight, visibleRest: visibleRest, data: data, textStyle: textStyle })))), /*#__PURE__*/React.createElement(View, { style: { width: '100%', height: itemHeight, backgroundColor: indicatorBgColor, opacity: 0.2, position: 'absolute' }, pointerEvents: "none" })); } function PickerItem(_ref2) { let { translateY, index, data, itemHeight, visibleRest, textStyle } = _ref2; const y = useDerivedValue(() => interpolate(translateY.value / -itemHeight, [index - visibleRest / 2, index, index + visibleRest / 2], [-1, 0, 1], Extrapolate.CLAMP)); const textAnimation = useAnimatedStyle(() => ({ opacity: 1 / (1 + Math.abs(y.value)), transform: [{ scale: 1 - Math.abs(y.value) * 0.35 }, { perspective: 500 }, { rotateX: `${y.value * 65}deg` }] })); return /*#__PURE__*/React.createElement(Animated.View, { style: [styles.item, { height: itemHeight }] }, /*#__PURE__*/React.createElement(Animated.Text, { style: [textAnimation, textStyle] }, data.label)); } const styles = StyleSheet.create({ container: { flex: 1, overflow: 'hidden', justifyContent: 'center', position: 'relative' }, item: { justifyContent: 'center', alignItems: 'center' } }); /** * @summary Select a point where the animation should snap to given the value of the gesture and it's velocity. * @worklet */ const snapPoint = (value, velocity, points) => { 'worklet'; const point = value + 0.2 * velocity; const deltas = points.map(p => Math.abs(point - p)); const minDelta = Math.min.apply(null, deltas); return points.find(p => Math.abs(point - p) === minDelta) || points[0]; }; //# sourceMappingURL=index.js.map