@mpxjs/webpack-plugin 2.9.70-alpha.0 → 2.9.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +433 -0
- package/README.md +1 -1
- package/lib/config.js +0 -14
- package/lib/dependencies/ResolveDependency.js +0 -5
- package/lib/index.js +7 -38
- package/lib/json-compiler/helper.js +3 -3
- package/lib/loader.js +0 -53
- package/lib/parser.js +1 -1
- package/lib/platform/json/wx/index.js +21 -8
- package/lib/platform/style/wx/index.js +51 -54
- package/lib/platform/template/wx/component-config/button.js +2 -14
- package/lib/platform/template/wx/component-config/fix-component-name.js +15 -12
- package/lib/platform/template/wx/component-config/image.js +0 -4
- package/lib/platform/template/wx/component-config/index.js +1 -1
- package/lib/platform/template/wx/component-config/input.js +0 -4
- package/lib/platform/template/wx/component-config/movable-view.js +8 -1
- package/lib/platform/template/wx/component-config/picker-view.js +1 -5
- package/lib/platform/template/wx/component-config/rich-text.js +6 -2
- package/lib/platform/template/wx/component-config/scroll-view.js +1 -5
- package/lib/platform/template/wx/component-config/switch.js +0 -4
- package/lib/platform/template/wx/component-config/text.js +0 -4
- package/lib/platform/template/wx/component-config/textarea.js +0 -5
- package/lib/platform/template/wx/component-config/unsupported.js +1 -1
- package/lib/platform/template/wx/component-config/view.js +0 -4
- package/lib/platform/template/wx/index.js +1 -131
- package/lib/resolve-loader.js +1 -4
- package/lib/runtime/components/react/context.ts +8 -0
- package/lib/runtime/components/react/dist/context.js +2 -0
- package/lib/runtime/components/react/dist/getInnerListeners.js +39 -37
- package/lib/runtime/components/react/dist/mpx-button.jsx +16 -44
- package/lib/runtime/components/react/dist/mpx-canvas/html.js +2 -4
- package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +5 -1
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +93 -58
- package/lib/runtime/components/react/dist/mpx-navigator.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +10 -14
- package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +94 -81
- package/lib/runtime/components/react/dist/mpx-picker-view.jsx +19 -16
- package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +10 -11
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +11 -4
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +31 -8
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +435 -371
- package/lib/runtime/components/react/dist/mpx-view.jsx +18 -53
- package/lib/runtime/components/react/dist/pickerFaces.js +3 -8
- package/lib/runtime/components/react/dist/pickerVIewContext.js +5 -0
- package/lib/runtime/components/react/dist/{pickerViewOverlay.jsx → pickerViewIndicator.jsx} +6 -6
- package/lib/runtime/components/react/dist/pickerViewMask.jsx +2 -2
- package/lib/runtime/components/react/dist/useAnimationHooks.js +27 -10
- package/lib/runtime/components/react/dist/utils.jsx +162 -70
- package/lib/runtime/components/react/event.config.ts +25 -26
- package/lib/runtime/components/react/getInnerListeners.ts +236 -182
- package/lib/runtime/components/react/mpx-button.tsx +27 -69
- package/lib/runtime/components/react/mpx-canvas/html.ts +2 -4
- package/lib/runtime/components/react/mpx-canvas/index.tsx +44 -46
- package/lib/runtime/components/react/mpx-checkbox-group.tsx +15 -13
- package/lib/runtime/components/react/mpx-checkbox.tsx +20 -21
- package/lib/runtime/components/react/mpx-form.tsx +15 -20
- package/lib/runtime/components/react/mpx-icon.tsx +2 -2
- package/lib/runtime/components/react/mpx-image.tsx +87 -47
- package/lib/runtime/components/react/mpx-input.tsx +24 -32
- package/lib/runtime/components/react/mpx-label.tsx +12 -14
- package/lib/runtime/components/react/mpx-movable-area.tsx +10 -16
- package/lib/runtime/components/react/mpx-movable-view.tsx +133 -92
- package/lib/runtime/components/react/mpx-navigator.tsx +3 -9
- package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +76 -0
- package/lib/runtime/components/react/mpx-picker-view-column.tsx +206 -183
- package/lib/runtime/components/react/mpx-picker-view.tsx +49 -48
- package/lib/runtime/components/react/mpx-radio-group.tsx +13 -15
- package/lib/runtime/components/react/mpx-radio.tsx +19 -25
- package/lib/runtime/components/react/mpx-rich-text/html.ts +40 -0
- package/lib/runtime/components/react/mpx-rich-text/index.tsx +115 -0
- package/lib/runtime/components/react/mpx-root-portal.tsx +3 -5
- package/lib/runtime/components/react/mpx-scroll-view.tsx +53 -43
- package/lib/runtime/components/react/mpx-swiper-item.tsx +45 -11
- package/lib/runtime/components/react/mpx-swiper.tsx +742 -0
- package/lib/runtime/components/react/mpx-switch.tsx +19 -15
- package/lib/runtime/components/react/mpx-text.tsx +8 -16
- package/lib/runtime/components/react/mpx-textarea.tsx +11 -10
- package/lib/runtime/components/react/mpx-view.tsx +28 -77
- package/lib/runtime/components/react/mpx-web-view.tsx +94 -59
- package/lib/runtime/components/react/pickerFaces.ts +10 -7
- package/lib/runtime/components/react/pickerVIewContext.ts +27 -0
- package/lib/runtime/components/react/pickerViewIndicator.tsx +34 -0
- package/lib/runtime/components/react/pickerViewMask.tsx +30 -0
- package/lib/runtime/components/react/types/{getInnerListeners.ts → getInnerListeners.d.ts} +4 -5
- package/lib/runtime/components/react/types/global.d.ts +12 -1
- package/lib/runtime/components/react/useAnimationHooks.ts +60 -15
- package/lib/runtime/components/react/utils.tsx +175 -71
- package/lib/runtime/components/web/mpx-checkbox.vue +1 -1
- package/lib/runtime/components/web/mpx-picker-view-column.vue +9 -4
- package/lib/runtime/components/web/mpx-web-view.vue +34 -20
- package/lib/runtime/optionProcessor.js +0 -22
- package/lib/style-compiler/index.js +1 -1
- package/lib/style-compiler/plugins/scope-id.js +30 -2
- package/lib/template-compiler/compiler.js +91 -39
- package/lib/utils/env.js +1 -6
- package/lib/utils/pre-process-json.js +9 -5
- package/lib/wxss/loader.js +15 -2
- package/package.json +4 -7
- package/lib/dependencies/AddEntryDependency.js +0 -24
- package/lib/runtime/components/react/dist/types/common.js +0 -1
- package/lib/runtime/components/react/dist/types/getInnerListeners.js +0 -1
- package/lib/runtime/components/react/mpx-swiper/carouse.tsx +0 -527
- package/lib/runtime/components/react/mpx-swiper/index.tsx +0 -80
- package/lib/runtime/components/react/mpx-swiper/type.ts +0 -87
- package/lib/runtime/components/react/pickerOverlay.tsx +0 -32
- package/lib/runtime/components/tenon/getInnerListeners.js +0 -334
- package/lib/runtime/components/tenon/tenon-button.vue +0 -309
- package/lib/runtime/components/tenon/tenon-image.vue +0 -66
- package/lib/runtime/components/tenon/tenon-input.vue +0 -171
- package/lib/runtime/components/tenon/tenon-rich-text.vue +0 -26
- package/lib/runtime/components/tenon/tenon-scroll-view.vue +0 -127
- package/lib/runtime/components/tenon/tenon-switch.vue +0 -96
- package/lib/runtime/components/tenon/tenon-text.vue +0 -70
- package/lib/runtime/components/tenon/tenon-textarea.vue +0 -86
- package/lib/runtime/components/tenon/tenon-view.vue +0 -93
- package/lib/runtime/components/web/event.js +0 -105
- package/lib/runtime/optionProcessor.tenon.js +0 -84
- package/lib/style-compiler/plugins/hm.js +0 -20
- package/lib/tenon/index.js +0 -117
- package/lib/tenon/processJSON.js +0 -352
- package/lib/tenon/processScript.js +0 -203
- package/lib/tenon/processStyles.js +0 -21
- package/lib/tenon/processTemplate.js +0 -126
- package/lib/tenon/script-helper.js +0 -223
- package/lib/utils/get-relative-path.js +0 -25
- /package/lib/runtime/components/react/types/{common.ts → common.d.ts} +0 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { View
|
|
1
|
+
import { View } from 'react-native';
|
|
2
2
|
import { GestureDetector, Gesture } from 'react-native-gesture-handler';
|
|
3
3
|
import Animated, { useAnimatedStyle, useSharedValue, withTiming, Easing, runOnJS, useAnimatedReaction, cancelAnimation } from 'react-native-reanimated';
|
|
4
|
-
import React, { forwardRef, useRef, useEffect,
|
|
4
|
+
import React, { forwardRef, useRef, useEffect, useMemo } from 'react';
|
|
5
5
|
import useInnerProps, { getCustomEvent } from './getInnerListeners';
|
|
6
6
|
import useNodesRef from './useNodesRef'; // 引入辅助函数
|
|
7
7
|
import { useTransformStyle, splitStyle, splitProps, useLayout, wrapChildren } from './utils';
|
|
8
|
+
import { SwiperContext } from './context';
|
|
8
9
|
/**
|
|
9
10
|
* 默认的Style类型
|
|
10
11
|
*/
|
|
@@ -29,12 +30,18 @@ const styles = {
|
|
|
29
30
|
justifyContent: 'center',
|
|
30
31
|
alignItems: 'center'
|
|
31
32
|
},
|
|
32
|
-
|
|
33
|
+
pagerWrapperx: {
|
|
33
34
|
position: 'absolute',
|
|
34
35
|
flexDirection: 'row',
|
|
35
36
|
justifyContent: 'center',
|
|
36
37
|
alignItems: 'center'
|
|
37
38
|
},
|
|
39
|
+
pagerWrappery: {
|
|
40
|
+
position: 'absolute',
|
|
41
|
+
flexDirection: 'column',
|
|
42
|
+
justifyContent: 'center',
|
|
43
|
+
alignItems: 'center'
|
|
44
|
+
},
|
|
38
45
|
swiper: {
|
|
39
46
|
overflow: 'scroll',
|
|
40
47
|
display: 'flex',
|
|
@@ -54,8 +61,6 @@ const dotCommonStyle = {
|
|
|
54
61
|
const activeDotStyle = {
|
|
55
62
|
zIndex: 99
|
|
56
63
|
};
|
|
57
|
-
// 默认前后补位的元素个数
|
|
58
|
-
const patchElementNum = 1;
|
|
59
64
|
const longPressRatio = 100;
|
|
60
65
|
const easeMap = {
|
|
61
66
|
default: Easing.linear,
|
|
@@ -65,16 +70,12 @@ const easeMap = {
|
|
|
65
70
|
easeInOutCubic: Easing.inOut(Easing.cubic)
|
|
66
71
|
};
|
|
67
72
|
const SwiperWrapper = forwardRef((props, ref) => {
|
|
68
|
-
const { 'indicator-dots': showsPagination, 'indicator-color': dotColor = 'rgba(0, 0, 0, .3)', 'indicator-active-color': activeDotColor = '#000000', 'enable-var': enableVar = false, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'external-var-context': externalVarContext, style = {} } = props;
|
|
69
|
-
const previousMargin = props['previous-margin'] ? parseInt(props['previous-margin']) : 0;
|
|
70
|
-
const nextMargin = props['next-margin'] ? parseInt(props['next-margin']) : 0;
|
|
73
|
+
const { 'indicator-dots': showsPagination, 'indicator-color': dotColor = 'rgba(0, 0, 0, .3)', 'indicator-active-color': activeDotColor = '#000000', 'enable-var': enableVar = false, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'external-var-context': externalVarContext, style = {}, autoplay = false, circular = false } = props;
|
|
71
74
|
const easeingFunc = props['easing-function'] || 'default';
|
|
72
75
|
const easeDuration = props.duration || 500;
|
|
73
76
|
const horizontal = props.vertical !== undefined ? !props.vertical : true;
|
|
74
77
|
const nodeRef = useRef(null);
|
|
75
78
|
useNodesRef(props, ref, nodeRef, {});
|
|
76
|
-
// 默认取水平方向的width
|
|
77
|
-
const { width } = Dimensions.get('window');
|
|
78
79
|
// 计算transfrom之类的
|
|
79
80
|
const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, {
|
|
80
81
|
enableVar,
|
|
@@ -85,40 +86,41 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
85
86
|
});
|
|
86
87
|
const { textStyle } = splitStyle(normalStyle);
|
|
87
88
|
const { textProps } = splitProps(props);
|
|
89
|
+
const preMargin = props['previous-margin'] ? global.__formatValue(props['previous-margin']) : 0;
|
|
90
|
+
const nextMargin = props['next-margin'] ? global.__formatValue(props['next-margin']) : 0;
|
|
91
|
+
const preMarginShared = useSharedValue(preMargin);
|
|
92
|
+
const nextMarginShared = useSharedValue(nextMargin);
|
|
93
|
+
const autoplayShared = useSharedValue(autoplay);
|
|
94
|
+
// 默认前后补位的元素个数
|
|
95
|
+
const patchElmNum = circular ? (preMargin ? 2 : 1) : 0;
|
|
96
|
+
const patchElmNumShared = useSharedValue(patchElmNum);
|
|
97
|
+
const circularShared = useSharedValue(circular);
|
|
88
98
|
const children = Array.isArray(props.children) ? props.children.filter(child => child) : (props.children ? [props.children] : []);
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
const initWidth = typeof
|
|
92
|
-
const initHeight = typeof
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
const dir = useSharedValue(horizontal === false ? 'y' : 'x');
|
|
96
|
-
const pstep = dir.value === 'x' ? widthState : heightState;
|
|
99
|
+
// 对有变化的变量,在worklet中只能使用sharedValue变量,useRef不能更新
|
|
100
|
+
const childrenLength = useSharedValue(children.length);
|
|
101
|
+
const initWidth = typeof normalStyle?.width === 'number' ? normalStyle.width - preMargin - nextMargin : normalStyle.width;
|
|
102
|
+
const initHeight = typeof normalStyle?.height === 'number' ? normalStyle.height - preMargin - nextMargin : normalStyle.height;
|
|
103
|
+
const dir = horizontal === false ? 'y' : 'x';
|
|
104
|
+
const pstep = dir === 'x' ? initWidth : initHeight;
|
|
97
105
|
const initStep = isNaN(pstep) ? 0 : pstep;
|
|
98
|
-
// 每个元素的宽度 or
|
|
106
|
+
// 每个元素的宽度 or 高度,有固定值直接初始化无则0
|
|
99
107
|
const step = useSharedValue(initStep);
|
|
100
|
-
const totalElements = useSharedValue(children.length);
|
|
101
108
|
// 记录选中元素的索引值
|
|
102
|
-
const
|
|
109
|
+
const currentIndex = useSharedValue(props.current || 0);
|
|
110
|
+
// const initOffset = getOffset(props.current || 0, initStep)
|
|
103
111
|
// 记录元素的偏移量
|
|
104
|
-
const offset = useSharedValue(0);
|
|
105
|
-
const
|
|
106
|
-
const strAbso = 'absolute' + dir.value.toUpperCase();
|
|
107
|
-
const strVelocity = 'velocity' + dir.value.toUpperCase();
|
|
108
|
-
const arrPages = renderItems();
|
|
109
|
-
// autoplay的状态下是否被暂停
|
|
110
|
-
const paused = useRef(false);
|
|
112
|
+
const offset = useSharedValue(getOffset(props.current || 0, initStep));
|
|
113
|
+
const strAbso = 'absolute' + dir.toUpperCase();
|
|
111
114
|
// 标识手指触摸和抬起, 起点在onBegin
|
|
112
|
-
const touchfinish = useSharedValue(
|
|
113
|
-
//
|
|
114
|
-
const isTriggerStart = useSharedValue(false);
|
|
115
|
-
// 记录用户点击时绝对定位坐标
|
|
115
|
+
const touchfinish = useSharedValue(true);
|
|
116
|
+
// 记录上一帧的绝对定位坐标
|
|
116
117
|
const preAbsolutePos = useSharedValue(0);
|
|
118
|
+
// 记录从onBegin 到 onTouchesUp 时移动的距离
|
|
119
|
+
const moveTranstion = useSharedValue(0);
|
|
120
|
+
// 记录从onBegin 到 onTouchesUp 的时间
|
|
121
|
+
const moveTime = useSharedValue(0);
|
|
117
122
|
const timerId = useRef(0);
|
|
118
|
-
// 用户点击未移动状态下,记录用户上一次操作的transtion 的 direction
|
|
119
|
-
const customTrans = useSharedValue(0);
|
|
120
123
|
const intervalTimer = props.interval || 500;
|
|
121
|
-
totalElements.value = children.length;
|
|
122
124
|
const {
|
|
123
125
|
// 存储layout布局信息
|
|
124
126
|
layoutRef, layoutProps, layoutStyle } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef, onLayout: onWrapperLayout });
|
|
@@ -141,42 +143,46 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
141
143
|
], { layoutRef: layoutRef });
|
|
142
144
|
function onWrapperLayout(e) {
|
|
143
145
|
const { width, height } = e.nativeEvent.layout;
|
|
144
|
-
const realWidth = dir
|
|
145
|
-
const realHeight = dir
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
const realWidth = dir === 'x' ? width - preMargin - nextMargin : width;
|
|
147
|
+
const realHeight = dir === 'y' ? height - preMargin - nextMargin : height;
|
|
148
|
+
const iStep = dir === 'x' ? realWidth : realHeight;
|
|
149
|
+
if (iStep !== step.value) {
|
|
150
|
+
step.value = iStep;
|
|
151
|
+
updateCurrent(props.current || 0, iStep);
|
|
152
|
+
updateAutoplay();
|
|
153
|
+
}
|
|
148
154
|
}
|
|
149
155
|
const dotAnimatedStyle = useAnimatedStyle(() => {
|
|
150
|
-
|
|
151
|
-
if (isNaN(+step))
|
|
156
|
+
if (!step.value)
|
|
152
157
|
return {};
|
|
153
158
|
const dotStep = dotCommonStyle.width + dotCommonStyle.marginRight + dotCommonStyle.marginLeft;
|
|
154
|
-
|
|
155
|
-
transform: [{
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
+
if (dir === 'x') {
|
|
160
|
+
return { transform: [{ translateX: currentIndex.value * dotStep }] };
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
return { transform: [{ translateY: currentIndex.value * dotStep }] };
|
|
164
|
+
}
|
|
159
165
|
});
|
|
160
166
|
function renderPagination() {
|
|
161
|
-
|
|
162
|
-
if (totalElements.value <= 1 || isNaN(+stepValue))
|
|
167
|
+
if (children.length <= 1)
|
|
163
168
|
return null;
|
|
164
169
|
const activeColor = activeDotColor || '#007aff';
|
|
165
170
|
const unActionColor = dotColor || 'rgba(0,0,0,.2)';
|
|
166
171
|
// 正常渲染所有dots
|
|
167
172
|
const dots = [];
|
|
168
|
-
for (let i = 0; i <
|
|
173
|
+
for (let i = 0; i < children.length; i++) {
|
|
169
174
|
dots.push(<View style={[dotCommonStyle, { backgroundColor: unActionColor }]} key={i}></View>);
|
|
170
175
|
}
|
|
171
|
-
return (<View pointerEvents="none" style={
|
|
172
|
-
<View style={[styles
|
|
176
|
+
return (<View pointerEvents="none" style={styles['pagination_' + dir]}>
|
|
177
|
+
<View style={[styles['pagerWrapper' + dir]]}>
|
|
173
178
|
<Animated.View style={[
|
|
174
179
|
dotCommonStyle,
|
|
175
180
|
activeDotStyle,
|
|
176
181
|
{
|
|
177
182
|
backgroundColor: activeColor,
|
|
178
183
|
position: 'absolute',
|
|
179
|
-
left: 0
|
|
184
|
+
left: 0,
|
|
185
|
+
top: 0
|
|
180
186
|
},
|
|
181
187
|
dotAnimatedStyle
|
|
182
188
|
]}/>
|
|
@@ -185,402 +191,460 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
185
191
|
</View>);
|
|
186
192
|
}
|
|
187
193
|
function renderItems() {
|
|
188
|
-
const
|
|
194
|
+
const intLen = children.length;
|
|
189
195
|
let renderChild = children.slice();
|
|
190
|
-
if (
|
|
196
|
+
if (circular && intLen > 1) {
|
|
191
197
|
// 最前面加最后一个元素
|
|
192
|
-
const lastChild = React.cloneElement(children[
|
|
198
|
+
const lastChild = React.cloneElement(children[intLen - 1], { key: 'clone0' });
|
|
193
199
|
// 最后面加第一个元素
|
|
194
|
-
const firstChild = React.cloneElement(children[0]);
|
|
195
|
-
|
|
200
|
+
const firstChild = React.cloneElement(children[0], { key: 'clone1' });
|
|
201
|
+
if (preMargin) {
|
|
202
|
+
const lastChild1 = React.cloneElement(children[intLen - 2], { key: 'clone2' });
|
|
203
|
+
const firstChild1 = React.cloneElement(children[1], { key: 'clone3' });
|
|
204
|
+
renderChild = [lastChild1, lastChild].concat(renderChild).concat([firstChild, firstChild1]);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
renderChild = [lastChild].concat(renderChild).concat([firstChild]);
|
|
208
|
+
}
|
|
196
209
|
}
|
|
197
|
-
|
|
210
|
+
const arrChildren = renderChild.map((child, index) => {
|
|
198
211
|
const extraStyle = {};
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
previousMargin && dir.value === 'x' && (extraStyle.marginLeft = previousMargin);
|
|
203
|
-
previousMargin && dir.value === 'y' && (extraStyle.marginTop = previousMargin);
|
|
212
|
+
if (index === 0 && !circular) {
|
|
213
|
+
preMargin && dir === 'x' && (extraStyle.marginLeft = preMargin);
|
|
214
|
+
preMargin && dir === 'y' && (extraStyle.marginTop = preMargin);
|
|
204
215
|
}
|
|
205
|
-
if (index ===
|
|
206
|
-
nextMargin && dir
|
|
207
|
-
nextMargin && dir
|
|
216
|
+
if (index === intLen - 1 && !circular) {
|
|
217
|
+
nextMargin && dir === 'x' && (extraStyle.marginRight = nextMargin);
|
|
218
|
+
nextMargin && dir === 'y' && (extraStyle.marginBottom = nextMargin);
|
|
208
219
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
220
|
+
// 业务swiper-item自己生成key,内部添加的元素自定义key
|
|
221
|
+
const newChild = React.cloneElement(child, {
|
|
222
|
+
itemIndex: index,
|
|
223
|
+
customStyle: extraStyle
|
|
224
|
+
});
|
|
225
|
+
return newChild;
|
|
215
226
|
});
|
|
227
|
+
const contextValue = {
|
|
228
|
+
offset,
|
|
229
|
+
step,
|
|
230
|
+
scale: props.scale,
|
|
231
|
+
dir
|
|
232
|
+
};
|
|
233
|
+
return (<SwiperContext.Provider value={contextValue}>{arrChildren}</SwiperContext.Provider>);
|
|
216
234
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
if (!props.circular) {
|
|
221
|
-
// 获取下一个位置的坐标, 循环到最后一个元素,直接停止, 取消定时器
|
|
222
|
-
if (targetIndex.value === totalElements.value - 1) {
|
|
223
|
-
pauseLoop();
|
|
235
|
+
const { loop, pauseLoop, resumeLoop } = useMemo(() => {
|
|
236
|
+
function createAutoPlay() {
|
|
237
|
+
if (!step.value)
|
|
224
238
|
return;
|
|
225
|
-
|
|
226
|
-
nextIndex
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
else {
|
|
237
|
-
// 默认向右, 向下
|
|
238
|
-
if (nextIndex === totalElements.value - 1) {
|
|
239
|
-
nextIndex = 0;
|
|
240
|
-
targetOffset = -(totalElements.value + patchElementNum) * step.value;
|
|
241
|
-
// 执行动画到下一帧
|
|
242
|
-
offset.value = withTiming(targetOffset, {
|
|
243
|
-
duration: easeDuration
|
|
244
|
-
}, () => {
|
|
245
|
-
const initOffset = -step.value * patchElementNum;
|
|
246
|
-
// 将开始位置设置为真正的位置
|
|
247
|
-
offset.value = initOffset;
|
|
248
|
-
targetIndex.value = nextIndex;
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
nextIndex = targetIndex.value + 1;
|
|
253
|
-
targetOffset = -(nextIndex + patchElementNum) * step.value;
|
|
254
|
-
// 执行动画到下一帧
|
|
239
|
+
let targetOffset = 0;
|
|
240
|
+
let nextIndex = currentIndex.value;
|
|
241
|
+
if (!circularShared.value) {
|
|
242
|
+
// 获取下一个位置的坐标, 循环到最后一个元素,直接停止, 取消定时器
|
|
243
|
+
if (currentIndex.value === childrenLength.value - 1) {
|
|
244
|
+
pauseLoop();
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
nextIndex += 1;
|
|
248
|
+
// targetOffset = -nextIndex * step.value - preMarginShared.value
|
|
249
|
+
targetOffset = -nextIndex * step.value;
|
|
255
250
|
offset.value = withTiming(targetOffset, {
|
|
256
251
|
duration: easeDuration,
|
|
257
252
|
easing: easeMap[easeingFunc]
|
|
258
253
|
}, () => {
|
|
259
|
-
|
|
260
|
-
|
|
254
|
+
currentIndex.value = nextIndex;
|
|
255
|
+
runOnJS(loop)();
|
|
261
256
|
});
|
|
262
257
|
}
|
|
258
|
+
else {
|
|
259
|
+
// 默认向右, 向下
|
|
260
|
+
if (nextIndex === childrenLength.value - 1) {
|
|
261
|
+
nextIndex = 0;
|
|
262
|
+
targetOffset = -(childrenLength.value + patchElmNumShared.value) * step.value + preMarginShared.value;
|
|
263
|
+
// 执行动画到下一帧
|
|
264
|
+
offset.value = withTiming(targetOffset, {
|
|
265
|
+
duration: easeDuration
|
|
266
|
+
}, () => {
|
|
267
|
+
const initOffset = -step.value * patchElmNumShared.value + preMarginShared.value;
|
|
268
|
+
// 将开始位置设置为真正的位置
|
|
269
|
+
offset.value = initOffset;
|
|
270
|
+
currentIndex.value = nextIndex;
|
|
271
|
+
runOnJS(loop)();
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
nextIndex = currentIndex.value + 1;
|
|
276
|
+
targetOffset = -(nextIndex + patchElmNumShared.value) * step.value + preMarginShared.value;
|
|
277
|
+
// 执行动画到下一帧
|
|
278
|
+
offset.value = withTiming(targetOffset, {
|
|
279
|
+
duration: easeDuration,
|
|
280
|
+
easing: easeMap[easeingFunc]
|
|
281
|
+
}, () => {
|
|
282
|
+
currentIndex.value = nextIndex;
|
|
283
|
+
runOnJS(loop)();
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
263
287
|
}
|
|
264
|
-
|
|
288
|
+
// loop在JS线程中调用,createAutoPlay + useEffect中
|
|
289
|
+
function loop() {
|
|
290
|
+
timerId.current && clearTimeout(timerId.current);
|
|
291
|
+
timerId.current = setTimeout(createAutoPlay, intervalTimer);
|
|
292
|
+
}
|
|
293
|
+
function pauseLoop() {
|
|
294
|
+
timerId.current && clearTimeout(timerId.current);
|
|
295
|
+
}
|
|
296
|
+
// resumeLoop在worklet中调用
|
|
297
|
+
function resumeLoop() {
|
|
298
|
+
if (autoplayShared.value && childrenLength.value > 1) {
|
|
299
|
+
loop();
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return {
|
|
303
|
+
loop,
|
|
304
|
+
pauseLoop,
|
|
305
|
+
resumeLoop
|
|
306
|
+
};
|
|
307
|
+
}, []);
|
|
265
308
|
function handleSwiperChange(current) {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
'worklet';
|
|
271
|
-
return dir.value === 'x' ? widthState : heightState;
|
|
309
|
+
if (props.current !== currentIndex.value) {
|
|
310
|
+
const eventData = getCustomEvent('change', {}, { detail: { current, source: 'touch' }, layoutRef: layoutRef });
|
|
311
|
+
props.bindchange && props.bindchange(eventData);
|
|
312
|
+
}
|
|
272
313
|
}
|
|
273
|
-
function
|
|
274
|
-
|
|
275
|
-
if (isNaN(+stepValue))
|
|
314
|
+
function getOffset(index, stepValue) {
|
|
315
|
+
if (!stepValue)
|
|
276
316
|
return 0;
|
|
277
317
|
let targetOffset = 0;
|
|
278
|
-
if (
|
|
279
|
-
const targetIndex =
|
|
280
|
-
targetOffset = -stepValue * targetIndex;
|
|
318
|
+
if (circular && children.length > 1) {
|
|
319
|
+
const targetIndex = index + patchElmNum;
|
|
320
|
+
targetOffset = -(stepValue * targetIndex - preMargin);
|
|
281
321
|
}
|
|
282
|
-
else
|
|
283
|
-
targetOffset = -
|
|
322
|
+
else {
|
|
323
|
+
targetOffset = -index * stepValue;
|
|
284
324
|
}
|
|
285
325
|
return targetOffset;
|
|
286
326
|
}
|
|
287
|
-
function
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
327
|
+
function updateCurrent(index, stepValue) {
|
|
328
|
+
const targetOffset = getOffset(index || 0, stepValue);
|
|
329
|
+
if (targetOffset !== offset.value) {
|
|
330
|
+
// 内部基于props.current!==currentIndex.value决定是否使用动画及更新currentIndex.value
|
|
331
|
+
if (props.current !== undefined && props.current !== currentIndex.value) {
|
|
332
|
+
offset.value = withTiming(targetOffset, {
|
|
333
|
+
duration: easeDuration,
|
|
334
|
+
easing: easeMap[easeingFunc]
|
|
335
|
+
}, () => {
|
|
336
|
+
currentIndex.value = props.current || 0;
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
offset.value = targetOffset;
|
|
341
|
+
}
|
|
293
342
|
}
|
|
294
343
|
}
|
|
295
|
-
function
|
|
296
|
-
|
|
297
|
-
clearTimeout(timerId.current);
|
|
298
|
-
}
|
|
299
|
-
function resumeLoop() {
|
|
300
|
-
if (props.autoplay && paused.current) {
|
|
301
|
-
paused.current = false;
|
|
344
|
+
function updateAutoplay() {
|
|
345
|
+
if (autoplay && children.length > 1) {
|
|
302
346
|
loop();
|
|
303
347
|
}
|
|
348
|
+
else {
|
|
349
|
+
pauseLoop();
|
|
350
|
+
}
|
|
304
351
|
}
|
|
305
|
-
|
|
352
|
+
// 1. 用户在当前页切换选中项,动画;用户携带选中index打开到swiper页直接选中不走动画
|
|
353
|
+
useAnimatedReaction(() => currentIndex.value, (newIndex, preIndex) => {
|
|
306
354
|
// 这里必须传递函数名, 直接写()=> {}形式会报 访问了未sharedValue信息
|
|
307
|
-
|
|
308
|
-
if (!isInit && props.current !== newIndex && props.bindchange) {
|
|
355
|
+
if (newIndex !== preIndex && props.bindchange) {
|
|
309
356
|
runOnJS(handleSwiperChange)(newIndex);
|
|
310
357
|
}
|
|
311
358
|
});
|
|
312
359
|
useEffect(() => {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
return;
|
|
360
|
+
let patchStep = 0;
|
|
361
|
+
if (preMargin !== preMarginShared.value) {
|
|
362
|
+
patchStep += preMargin - preMarginShared.value;
|
|
317
363
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
if (props.current !== undefined && (props.current !== targetIndex.value || (props.current === 0 && targetIndex.value > 0))) {
|
|
321
|
-
targetIndex.value = props.current;
|
|
322
|
-
offset.value = withTiming(targetOffset, {
|
|
323
|
-
duration: easeDuration,
|
|
324
|
-
easing: easeMap[easeingFunc]
|
|
325
|
-
}, () => {
|
|
326
|
-
offset.value = targetOffset;
|
|
327
|
-
});
|
|
364
|
+
if (nextMargin !== nextMarginShared.value) {
|
|
365
|
+
patchStep += nextMargin - nextMarginShared.value;
|
|
328
366
|
}
|
|
329
|
-
|
|
330
|
-
|
|
367
|
+
preMarginShared.value = preMargin;
|
|
368
|
+
nextMarginShared.value = nextMargin;
|
|
369
|
+
const newStep = step.value - patchStep;
|
|
370
|
+
if (step.value !== newStep) {
|
|
371
|
+
step.value = newStep;
|
|
372
|
+
offset.value = getOffset(currentIndex.value, newStep);
|
|
331
373
|
}
|
|
332
|
-
}, [
|
|
374
|
+
}, [preMargin, nextMargin]);
|
|
333
375
|
useEffect(() => {
|
|
334
|
-
|
|
335
|
-
if (
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
const targetOffset = getInitOffset();
|
|
339
|
-
if (props.autoplay) {
|
|
340
|
-
pauseLoop();
|
|
341
|
-
offset.value = targetOffset;
|
|
342
|
-
resumeLoop();
|
|
343
|
-
}
|
|
344
|
-
else {
|
|
376
|
+
childrenLength.value = children.length;
|
|
377
|
+
if (children.length - 1 < currentIndex.value) {
|
|
345
378
|
pauseLoop();
|
|
379
|
+
currentIndex.value = 0;
|
|
380
|
+
offset.value = getOffset(0, step.value);
|
|
381
|
+
if (autoplay && children.length > 1) {
|
|
382
|
+
loop();
|
|
383
|
+
}
|
|
346
384
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
// 真实滚动到的偏移量坐标
|
|
358
|
-
let moveToTargetPos = 0;
|
|
359
|
-
// 当前的位置
|
|
360
|
-
const currentOffset = offset.value;
|
|
361
|
-
const currentIndex = Math.abs(currentOffset) / step.value;
|
|
362
|
-
const moveToIndex = translation < 0 ? Math.ceil(currentIndex) : Math.floor(currentIndex);
|
|
363
|
-
// 实际应该定位的索引值
|
|
364
|
-
if (!props.circular) {
|
|
365
|
-
selectedIndex = moveToIndex;
|
|
366
|
-
moveToTargetPos = selectedIndex * step.value;
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
if (moveToIndex >= totalElements.value + patchElementNum) {
|
|
370
|
-
selectedIndex = moveToIndex - (totalElements.value + patchElementNum);
|
|
371
|
-
resetOffsetPos = (selectedIndex + patchElementNum) * step.value;
|
|
372
|
-
moveToTargetPos = moveToIndex * step.value;
|
|
373
|
-
isCriticalItem = true;
|
|
385
|
+
}, [children.length]);
|
|
386
|
+
useEffect(() => {
|
|
387
|
+
updateCurrent(props.current || 0, step.value);
|
|
388
|
+
}, [props.current]);
|
|
389
|
+
useEffect(() => {
|
|
390
|
+
autoplayShared.value = autoplay;
|
|
391
|
+
updateAutoplay();
|
|
392
|
+
return () => {
|
|
393
|
+
if (autoplay) {
|
|
394
|
+
pauseLoop();
|
|
374
395
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
396
|
+
};
|
|
397
|
+
}, [autoplay]);
|
|
398
|
+
useEffect(() => {
|
|
399
|
+
if (circular !== circularShared.value) {
|
|
400
|
+
circularShared.value = circular;
|
|
401
|
+
patchElmNumShared.value = circular ? (preMargin ? 2 : 1) : 0;
|
|
402
|
+
offset.value = getOffset(currentIndex.value, step.value);
|
|
403
|
+
}
|
|
404
|
+
}, [circular, preMargin]);
|
|
405
|
+
const { gestureHandler } = useMemo(() => {
|
|
406
|
+
function getTargetPosition(eventData) {
|
|
407
|
+
'worklet';
|
|
408
|
+
// 移动的距离
|
|
409
|
+
const { translation } = eventData;
|
|
410
|
+
let resetOffsetPos = 0;
|
|
411
|
+
let selectedIndex = currentIndex.value;
|
|
412
|
+
// 是否临界点
|
|
413
|
+
let isCriticalItem = false;
|
|
414
|
+
// 真实滚动到的偏移量坐标
|
|
415
|
+
let moveToTargetPos = 0;
|
|
416
|
+
const currentOffset = translation < 0 ? offset.value - preMarginShared.value : offset.value + preMarginShared.value;
|
|
417
|
+
const computedIndex = Math.abs(currentOffset) / step.value;
|
|
418
|
+
const moveToIndex = translation < 0 ? Math.ceil(computedIndex) : Math.floor(computedIndex);
|
|
419
|
+
// 实际应该定位的索引值
|
|
420
|
+
if (!circularShared.value) {
|
|
421
|
+
selectedIndex = moveToIndex;
|
|
422
|
+
moveToTargetPos = selectedIndex * step.value;
|
|
380
423
|
}
|
|
381
424
|
else {
|
|
382
|
-
|
|
383
|
-
|
|
425
|
+
if (moveToIndex >= childrenLength.value + patchElmNumShared.value) {
|
|
426
|
+
selectedIndex = moveToIndex - (childrenLength.value + patchElmNumShared.value);
|
|
427
|
+
resetOffsetPos = (selectedIndex + patchElmNumShared.value) * step.value - preMarginShared.value;
|
|
428
|
+
moveToTargetPos = moveToIndex * step.value - preMarginShared.value;
|
|
429
|
+
isCriticalItem = true;
|
|
430
|
+
}
|
|
431
|
+
else if (moveToIndex <= patchElmNumShared.value - 1) {
|
|
432
|
+
selectedIndex = moveToIndex === 0 ? childrenLength.value - patchElmNumShared.value : childrenLength.value - 1;
|
|
433
|
+
resetOffsetPos = (selectedIndex + patchElmNumShared.value) * step.value - preMarginShared.value;
|
|
434
|
+
moveToTargetPos = moveToIndex * step.value - preMarginShared.value;
|
|
435
|
+
isCriticalItem = true;
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
selectedIndex = moveToIndex - patchElmNumShared.value;
|
|
439
|
+
moveToTargetPos = moveToIndex * step.value - preMarginShared.value;
|
|
440
|
+
}
|
|
384
441
|
}
|
|
442
|
+
return {
|
|
443
|
+
selectedIndex,
|
|
444
|
+
isCriticalItem,
|
|
445
|
+
resetOffset: -resetOffsetPos,
|
|
446
|
+
targetOffset: -moveToTargetPos
|
|
447
|
+
};
|
|
385
448
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
const currentOffset = Math.abs(offset.value);
|
|
398
|
-
if (!props.circular) {
|
|
399
|
-
if (translation < 0) {
|
|
400
|
-
return currentOffset + Math.abs(translation) < stepValue * (totalElements.value - 1);
|
|
449
|
+
function canMove(eventData) {
|
|
450
|
+
'worklet';
|
|
451
|
+
const { translation } = eventData;
|
|
452
|
+
const currentOffset = Math.abs(offset.value);
|
|
453
|
+
if (!circularShared.value) {
|
|
454
|
+
if (translation < 0) {
|
|
455
|
+
return currentOffset < step.value * (childrenLength.value - 1);
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
return currentOffset > 0;
|
|
459
|
+
}
|
|
401
460
|
}
|
|
402
461
|
else {
|
|
403
|
-
return
|
|
462
|
+
return true;
|
|
404
463
|
}
|
|
405
464
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
465
|
+
function handleEnd(eventData) {
|
|
466
|
+
'worklet';
|
|
467
|
+
const { isCriticalItem, targetOffset, resetOffset, selectedIndex } = getTargetPosition(eventData);
|
|
468
|
+
if (isCriticalItem) {
|
|
469
|
+
offset.value = withTiming(targetOffset, {
|
|
470
|
+
duration: easeDuration,
|
|
471
|
+
easing: easeMap[easeingFunc]
|
|
472
|
+
}, () => {
|
|
473
|
+
if (touchfinish.value !== false) {
|
|
474
|
+
currentIndex.value = selectedIndex;
|
|
475
|
+
offset.value = resetOffset;
|
|
476
|
+
runOnJS(resumeLoop)();
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
offset.value = withTiming(targetOffset, {
|
|
482
|
+
duration: easeDuration,
|
|
483
|
+
easing: easeMap[easeingFunc]
|
|
484
|
+
}, () => {
|
|
485
|
+
if (touchfinish.value !== false) {
|
|
486
|
+
currentIndex.value = selectedIndex;
|
|
487
|
+
runOnJS(resumeLoop)();
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
}
|
|
424
491
|
}
|
|
425
|
-
|
|
492
|
+
function handleBack(eventData) {
|
|
493
|
+
'worklet';
|
|
494
|
+
const { translation } = eventData;
|
|
495
|
+
// 向右滑动的back:trans < 0, 向左滑动的back: trans < 0
|
|
496
|
+
let currentOffset = Math.abs(offset.value);
|
|
497
|
+
if (circularShared.value) {
|
|
498
|
+
currentOffset += translation < 0 ? preMarginShared.value : -preMarginShared.value;
|
|
499
|
+
}
|
|
500
|
+
const curIndex = currentOffset / step.value;
|
|
501
|
+
const moveToIndex = (translation < 0 ? Math.floor(curIndex) : Math.ceil(curIndex)) - patchElmNumShared.value;
|
|
502
|
+
const targetOffset = -(moveToIndex + patchElmNumShared.value) * step.value + (circularShared.value ? preMarginShared.value : 0);
|
|
426
503
|
offset.value = withTiming(targetOffset, {
|
|
427
504
|
duration: easeDuration,
|
|
428
505
|
easing: easeMap[easeingFunc]
|
|
429
506
|
}, () => {
|
|
430
507
|
if (touchfinish.value !== false) {
|
|
431
|
-
|
|
432
|
-
offset.value = targetOffset;
|
|
508
|
+
currentIndex.value = moveToIndex;
|
|
433
509
|
runOnJS(resumeLoop)();
|
|
434
510
|
}
|
|
435
511
|
});
|
|
436
512
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
easing: easeMap[easeingFunc]
|
|
449
|
-
}, () => {
|
|
450
|
-
if (touchfinish.value !== false) {
|
|
451
|
-
offset.value = targetOffset;
|
|
452
|
-
targetIndex.value = moveToIndex;
|
|
513
|
+
function handleLongPress() {
|
|
514
|
+
'worklet';
|
|
515
|
+
const currentOffset = Math.abs(offset.value);
|
|
516
|
+
let preOffset = (currentIndex.value + patchElmNumShared.value) * step.value;
|
|
517
|
+
if (circularShared.value) {
|
|
518
|
+
preOffset -= preMarginShared.value;
|
|
519
|
+
}
|
|
520
|
+
// 正常事件中拿到的transition值(正向滑动<0,倒着滑>0)
|
|
521
|
+
const diffOffset = preOffset - currentOffset;
|
|
522
|
+
const half = Math.abs(diffOffset) > step.value / 2;
|
|
523
|
+
if (+diffOffset === 0) {
|
|
453
524
|
runOnJS(resumeLoop)();
|
|
454
525
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
function handleLongPress(eventData) {
|
|
458
|
-
'worklet';
|
|
459
|
-
const { translation } = eventData;
|
|
460
|
-
const currentOffset = Math.abs(offset.value);
|
|
461
|
-
const half = currentOffset % step.value > step.value / 2;
|
|
462
|
-
// 向右trans < 0, 向左trans > 0
|
|
463
|
-
const isExceedHalf = translation < 0 ? half : !half;
|
|
464
|
-
if (+translation === 0) {
|
|
465
|
-
runOnJS(resumeLoop)();
|
|
466
|
-
}
|
|
467
|
-
else if (isExceedHalf) {
|
|
468
|
-
handleEnd(eventData);
|
|
469
|
-
}
|
|
470
|
-
else {
|
|
471
|
-
handleBack(eventData);
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
function reachBoundary(eventData) {
|
|
475
|
-
'worklet';
|
|
476
|
-
// 移动的距离
|
|
477
|
-
const { translation } = eventData;
|
|
478
|
-
const elementsLength = step.value * totalElements.value;
|
|
479
|
-
let isBoundary = false;
|
|
480
|
-
let resetOffset = 0;
|
|
481
|
-
// Y轴向下滚动, transDistance > 0, 向上滚动 < 0 X轴向左滚动, transDistance > 0
|
|
482
|
-
const currentOffset = offset.value;
|
|
483
|
-
const moveStep = Math.ceil(translation / elementsLength);
|
|
484
|
-
if (translation < 0) {
|
|
485
|
-
const posEnd = (totalElements.value + patchElementNum + 1) * step.value;
|
|
486
|
-
const posReverseEnd = (patchElementNum - 1) * step.value;
|
|
487
|
-
if (currentOffset < -posEnd + step.value) {
|
|
488
|
-
isBoundary = true;
|
|
489
|
-
resetOffset = Math.abs(moveStep) === 0 ? patchElementNum * step.value + translation : moveStep * elementsLength;
|
|
526
|
+
else if (half) {
|
|
527
|
+
handleEnd({ translation: diffOffset });
|
|
490
528
|
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
resetOffset = moveStep * elementsLength;
|
|
529
|
+
else {
|
|
530
|
+
handleBack({ translation: diffOffset });
|
|
494
531
|
}
|
|
495
532
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
533
|
+
function reachBoundary(eventData) {
|
|
534
|
+
'worklet';
|
|
535
|
+
// 移动的距离
|
|
536
|
+
const { translation } = eventData;
|
|
537
|
+
const elementsLength = step.value * childrenLength.value;
|
|
538
|
+
let isBoundary = false;
|
|
539
|
+
let resetOffset = 0;
|
|
540
|
+
// Y轴向下滚动, transDistance > 0, 向上滚动 < 0 X轴向左滚动, transDistance > 0
|
|
541
|
+
const currentOffset = offset.value;
|
|
542
|
+
const moveStep = Math.ceil(translation / elementsLength);
|
|
543
|
+
if (translation < 0) {
|
|
544
|
+
const posEnd = (childrenLength.value + patchElmNumShared.value + 1) * step.value;
|
|
545
|
+
const posReverseEnd = (patchElmNumShared.value - 1) * step.value;
|
|
546
|
+
if (currentOffset < -posEnd + step.value) {
|
|
547
|
+
isBoundary = true;
|
|
548
|
+
resetOffset = Math.abs(moveStep) === 0 ? patchElmNumShared.value * step.value + translation : moveStep * elementsLength;
|
|
549
|
+
}
|
|
550
|
+
if (currentOffset > -posReverseEnd) {
|
|
551
|
+
isBoundary = true;
|
|
552
|
+
resetOffset = moveStep * elementsLength;
|
|
553
|
+
}
|
|
502
554
|
}
|
|
503
|
-
if (
|
|
504
|
-
|
|
505
|
-
|
|
555
|
+
else if (translation > 0) {
|
|
556
|
+
const posEnd = (patchElmNumShared.value - 1) * step.value;
|
|
557
|
+
const posReverseEnd = (patchElmNumShared.value + childrenLength.value) * step.value;
|
|
558
|
+
if (currentOffset > -posEnd) {
|
|
559
|
+
isBoundary = true;
|
|
560
|
+
resetOffset = moveStep * elementsLength + step.value + (moveStep === 1 ? translation : 0);
|
|
561
|
+
}
|
|
562
|
+
if (currentOffset < -posReverseEnd) {
|
|
563
|
+
isBoundary = true;
|
|
564
|
+
resetOffset = moveStep * elementsLength + patchElmNumShared.value * step.value;
|
|
565
|
+
}
|
|
506
566
|
}
|
|
567
|
+
return {
|
|
568
|
+
isBoundary,
|
|
569
|
+
resetOffset: -resetOffset
|
|
570
|
+
};
|
|
507
571
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
'worklet';
|
|
527
|
-
const touchEventData = e.changedTouches[0];
|
|
528
|
-
const moveDistance = touchEventData[strAbso] - preAbsolutePos.value;
|
|
529
|
-
customTrans.value = moveDistance;
|
|
530
|
-
const eventData = {
|
|
531
|
-
translation: moveDistance
|
|
532
|
-
};
|
|
533
|
-
// 处理用户一直拖拽到临界点的场景, 不会执行onEnd
|
|
534
|
-
if (!props.circular && !canMove(eventData)) {
|
|
535
|
-
return;
|
|
536
|
-
}
|
|
537
|
-
const { isBoundary, resetOffset } = reachBoundary(eventData);
|
|
538
|
-
if (isBoundary && props.circular && !touchfinish.value) {
|
|
539
|
-
offset.value = resetOffset;
|
|
540
|
-
}
|
|
541
|
-
else {
|
|
542
|
-
offset.value = moveDistance + offset.value;
|
|
543
|
-
}
|
|
544
|
-
preAbsolutePos.value = touchEventData[strAbso];
|
|
545
|
-
})
|
|
546
|
-
.onTouchesUp((e) => {
|
|
547
|
-
'worklet';
|
|
548
|
-
// 未触发移动不会触发onStart事件, touches事件拿到的数据只有absoluteX 和 x, 无法判断方向
|
|
549
|
-
if (!isTriggerStart.value) {
|
|
572
|
+
const gesturePan = Gesture.Pan()
|
|
573
|
+
.onBegin((e) => {
|
|
574
|
+
'worklet';
|
|
575
|
+
if (!step.value)
|
|
576
|
+
return;
|
|
577
|
+
touchfinish.value = false;
|
|
578
|
+
cancelAnimation(offset);
|
|
579
|
+
runOnJS(pauseLoop)();
|
|
580
|
+
preAbsolutePos.value = e[strAbso];
|
|
581
|
+
moveTranstion.value = e[strAbso];
|
|
582
|
+
moveTime.value = new Date().getTime();
|
|
583
|
+
})
|
|
584
|
+
.onTouchesMove((e) => {
|
|
585
|
+
'worklet';
|
|
586
|
+
if (touchfinish.value)
|
|
587
|
+
return;
|
|
588
|
+
const touchEventData = e.changedTouches[0];
|
|
589
|
+
const moveDistance = touchEventData[strAbso] - preAbsolutePos.value;
|
|
550
590
|
const eventData = {
|
|
551
|
-
translation:
|
|
591
|
+
translation: moveDistance
|
|
552
592
|
};
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
593
|
+
// 处理用户一直拖拽到临界点的场景, 不会执行onEnd
|
|
594
|
+
if (!circularShared.value && !canMove(eventData)) {
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
const { isBoundary, resetOffset } = reachBoundary(eventData);
|
|
598
|
+
if (isBoundary && circularShared.value) {
|
|
599
|
+
offset.value = resetOffset;
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
offset.value = moveDistance + offset.value;
|
|
603
|
+
}
|
|
604
|
+
preAbsolutePos.value = touchEventData[strAbso];
|
|
605
|
+
})
|
|
606
|
+
.onTouchesUp((e) => {
|
|
607
|
+
'worklet';
|
|
608
|
+
if (touchfinish.value)
|
|
609
|
+
return;
|
|
610
|
+
const touchEventData = e.changedTouches[0];
|
|
611
|
+
const moveDistance = touchEventData[strAbso] - moveTranstion.value;
|
|
612
|
+
touchfinish.value = true;
|
|
613
|
+
const eventData = {
|
|
614
|
+
translation: moveDistance
|
|
615
|
+
};
|
|
616
|
+
// 用户手指按下起来, 需要计算正确的位置, 比如在滑动过程中突然按下然后起来,需要计算到正确的位置
|
|
617
|
+
if (!circularShared.value && !canMove(eventData)) {
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
const strVelocity = moveDistance / (new Date().getTime() - moveTime.value) * 1000;
|
|
621
|
+
if (Math.abs(strVelocity) < longPressRatio) {
|
|
622
|
+
handleLongPress();
|
|
623
|
+
}
|
|
624
|
+
else {
|
|
625
|
+
handleEnd(eventData);
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
return {
|
|
629
|
+
gestureHandler: gesturePan
|
|
562
630
|
};
|
|
563
|
-
|
|
564
|
-
return;
|
|
565
|
-
}
|
|
566
|
-
if (Math.abs(e[strVelocity]) < longPressRatio) {
|
|
567
|
-
handleLongPress(eventData);
|
|
568
|
-
}
|
|
569
|
-
else {
|
|
570
|
-
handleEnd(eventData);
|
|
571
|
-
}
|
|
572
|
-
});
|
|
631
|
+
}, []);
|
|
573
632
|
const animatedStyles = useAnimatedStyle(() => {
|
|
574
|
-
if (dir
|
|
575
|
-
return { transform: [{ translateX: offset.value }] };
|
|
633
|
+
if (dir === 'x') {
|
|
634
|
+
return { transform: [{ translateX: offset.value }], opacity: step.value > 0 ? 1 : 0 };
|
|
576
635
|
}
|
|
577
636
|
else {
|
|
578
|
-
return { transform: [{ translateY: offset.value }] };
|
|
637
|
+
return { transform: [{ translateY: offset.value }], opacity: step.value > 0 ? 1 : 0 };
|
|
579
638
|
}
|
|
580
639
|
});
|
|
581
640
|
function renderSwiper() {
|
|
641
|
+
const arrPages = renderItems();
|
|
582
642
|
return (<View style={[normalStyle, layoutStyle, styles.swiper]} {...layoutProps} {...innerProps}>
|
|
583
|
-
<Animated.View style={[{
|
|
643
|
+
<Animated.View style={[{
|
|
644
|
+
flexDirection: dir === 'x' ? 'row' : 'column',
|
|
645
|
+
width: '100%',
|
|
646
|
+
height: '100%'
|
|
647
|
+
}, animatedStyles]}>
|
|
584
648
|
{wrapChildren({
|
|
585
649
|
children: arrPages
|
|
586
650
|
}, {
|
|
@@ -593,7 +657,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
593
657
|
{showsPagination && renderPagination()}
|
|
594
658
|
</View>);
|
|
595
659
|
}
|
|
596
|
-
if (
|
|
660
|
+
if (children.length === 1) {
|
|
597
661
|
return renderSwiper();
|
|
598
662
|
}
|
|
599
663
|
else {
|