@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.
Files changed (126) hide show
  1. package/LICENSE +433 -0
  2. package/README.md +1 -1
  3. package/lib/config.js +0 -14
  4. package/lib/dependencies/ResolveDependency.js +0 -5
  5. package/lib/index.js +7 -38
  6. package/lib/json-compiler/helper.js +3 -3
  7. package/lib/loader.js +0 -53
  8. package/lib/parser.js +1 -1
  9. package/lib/platform/json/wx/index.js +21 -8
  10. package/lib/platform/style/wx/index.js +51 -54
  11. package/lib/platform/template/wx/component-config/button.js +2 -14
  12. package/lib/platform/template/wx/component-config/fix-component-name.js +15 -12
  13. package/lib/platform/template/wx/component-config/image.js +0 -4
  14. package/lib/platform/template/wx/component-config/index.js +1 -1
  15. package/lib/platform/template/wx/component-config/input.js +0 -4
  16. package/lib/platform/template/wx/component-config/movable-view.js +8 -1
  17. package/lib/platform/template/wx/component-config/picker-view.js +1 -5
  18. package/lib/platform/template/wx/component-config/rich-text.js +6 -2
  19. package/lib/platform/template/wx/component-config/scroll-view.js +1 -5
  20. package/lib/platform/template/wx/component-config/switch.js +0 -4
  21. package/lib/platform/template/wx/component-config/text.js +0 -4
  22. package/lib/platform/template/wx/component-config/textarea.js +0 -5
  23. package/lib/platform/template/wx/component-config/unsupported.js +1 -1
  24. package/lib/platform/template/wx/component-config/view.js +0 -4
  25. package/lib/platform/template/wx/index.js +1 -131
  26. package/lib/resolve-loader.js +1 -4
  27. package/lib/runtime/components/react/context.ts +8 -0
  28. package/lib/runtime/components/react/dist/context.js +2 -0
  29. package/lib/runtime/components/react/dist/getInnerListeners.js +39 -37
  30. package/lib/runtime/components/react/dist/mpx-button.jsx +16 -44
  31. package/lib/runtime/components/react/dist/mpx-canvas/html.js +2 -4
  32. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +5 -1
  33. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +93 -58
  34. package/lib/runtime/components/react/dist/mpx-navigator.jsx +1 -1
  35. package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +10 -14
  36. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +94 -81
  37. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +19 -16
  38. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +10 -11
  39. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +11 -4
  40. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +31 -8
  41. package/lib/runtime/components/react/dist/mpx-swiper.jsx +435 -371
  42. package/lib/runtime/components/react/dist/mpx-view.jsx +18 -53
  43. package/lib/runtime/components/react/dist/pickerFaces.js +3 -8
  44. package/lib/runtime/components/react/dist/pickerVIewContext.js +5 -0
  45. package/lib/runtime/components/react/dist/{pickerViewOverlay.jsx → pickerViewIndicator.jsx} +6 -6
  46. package/lib/runtime/components/react/dist/pickerViewMask.jsx +2 -2
  47. package/lib/runtime/components/react/dist/useAnimationHooks.js +27 -10
  48. package/lib/runtime/components/react/dist/utils.jsx +162 -70
  49. package/lib/runtime/components/react/event.config.ts +25 -26
  50. package/lib/runtime/components/react/getInnerListeners.ts +236 -182
  51. package/lib/runtime/components/react/mpx-button.tsx +27 -69
  52. package/lib/runtime/components/react/mpx-canvas/html.ts +2 -4
  53. package/lib/runtime/components/react/mpx-canvas/index.tsx +44 -46
  54. package/lib/runtime/components/react/mpx-checkbox-group.tsx +15 -13
  55. package/lib/runtime/components/react/mpx-checkbox.tsx +20 -21
  56. package/lib/runtime/components/react/mpx-form.tsx +15 -20
  57. package/lib/runtime/components/react/mpx-icon.tsx +2 -2
  58. package/lib/runtime/components/react/mpx-image.tsx +87 -47
  59. package/lib/runtime/components/react/mpx-input.tsx +24 -32
  60. package/lib/runtime/components/react/mpx-label.tsx +12 -14
  61. package/lib/runtime/components/react/mpx-movable-area.tsx +10 -16
  62. package/lib/runtime/components/react/mpx-movable-view.tsx +133 -92
  63. package/lib/runtime/components/react/mpx-navigator.tsx +3 -9
  64. package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +76 -0
  65. package/lib/runtime/components/react/mpx-picker-view-column.tsx +206 -183
  66. package/lib/runtime/components/react/mpx-picker-view.tsx +49 -48
  67. package/lib/runtime/components/react/mpx-radio-group.tsx +13 -15
  68. package/lib/runtime/components/react/mpx-radio.tsx +19 -25
  69. package/lib/runtime/components/react/mpx-rich-text/html.ts +40 -0
  70. package/lib/runtime/components/react/mpx-rich-text/index.tsx +115 -0
  71. package/lib/runtime/components/react/mpx-root-portal.tsx +3 -5
  72. package/lib/runtime/components/react/mpx-scroll-view.tsx +53 -43
  73. package/lib/runtime/components/react/mpx-swiper-item.tsx +45 -11
  74. package/lib/runtime/components/react/mpx-swiper.tsx +742 -0
  75. package/lib/runtime/components/react/mpx-switch.tsx +19 -15
  76. package/lib/runtime/components/react/mpx-text.tsx +8 -16
  77. package/lib/runtime/components/react/mpx-textarea.tsx +11 -10
  78. package/lib/runtime/components/react/mpx-view.tsx +28 -77
  79. package/lib/runtime/components/react/mpx-web-view.tsx +94 -59
  80. package/lib/runtime/components/react/pickerFaces.ts +10 -7
  81. package/lib/runtime/components/react/pickerVIewContext.ts +27 -0
  82. package/lib/runtime/components/react/pickerViewIndicator.tsx +34 -0
  83. package/lib/runtime/components/react/pickerViewMask.tsx +30 -0
  84. package/lib/runtime/components/react/types/{getInnerListeners.ts → getInnerListeners.d.ts} +4 -5
  85. package/lib/runtime/components/react/types/global.d.ts +12 -1
  86. package/lib/runtime/components/react/useAnimationHooks.ts +60 -15
  87. package/lib/runtime/components/react/utils.tsx +175 -71
  88. package/lib/runtime/components/web/mpx-checkbox.vue +1 -1
  89. package/lib/runtime/components/web/mpx-picker-view-column.vue +9 -4
  90. package/lib/runtime/components/web/mpx-web-view.vue +34 -20
  91. package/lib/runtime/optionProcessor.js +0 -22
  92. package/lib/style-compiler/index.js +1 -1
  93. package/lib/style-compiler/plugins/scope-id.js +30 -2
  94. package/lib/template-compiler/compiler.js +91 -39
  95. package/lib/utils/env.js +1 -6
  96. package/lib/utils/pre-process-json.js +9 -5
  97. package/lib/wxss/loader.js +15 -2
  98. package/package.json +4 -7
  99. package/lib/dependencies/AddEntryDependency.js +0 -24
  100. package/lib/runtime/components/react/dist/types/common.js +0 -1
  101. package/lib/runtime/components/react/dist/types/getInnerListeners.js +0 -1
  102. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +0 -527
  103. package/lib/runtime/components/react/mpx-swiper/index.tsx +0 -80
  104. package/lib/runtime/components/react/mpx-swiper/type.ts +0 -87
  105. package/lib/runtime/components/react/pickerOverlay.tsx +0 -32
  106. package/lib/runtime/components/tenon/getInnerListeners.js +0 -334
  107. package/lib/runtime/components/tenon/tenon-button.vue +0 -309
  108. package/lib/runtime/components/tenon/tenon-image.vue +0 -66
  109. package/lib/runtime/components/tenon/tenon-input.vue +0 -171
  110. package/lib/runtime/components/tenon/tenon-rich-text.vue +0 -26
  111. package/lib/runtime/components/tenon/tenon-scroll-view.vue +0 -127
  112. package/lib/runtime/components/tenon/tenon-switch.vue +0 -96
  113. package/lib/runtime/components/tenon/tenon-text.vue +0 -70
  114. package/lib/runtime/components/tenon/tenon-textarea.vue +0 -86
  115. package/lib/runtime/components/tenon/tenon-view.vue +0 -93
  116. package/lib/runtime/components/web/event.js +0 -105
  117. package/lib/runtime/optionProcessor.tenon.js +0 -84
  118. package/lib/style-compiler/plugins/hm.js +0 -20
  119. package/lib/tenon/index.js +0 -117
  120. package/lib/tenon/processJSON.js +0 -352
  121. package/lib/tenon/processScript.js +0 -203
  122. package/lib/tenon/processStyles.js +0 -21
  123. package/lib/tenon/processTemplate.js +0 -126
  124. package/lib/tenon/script-helper.js +0 -223
  125. package/lib/utils/get-relative-path.js +0 -25
  126. /package/lib/runtime/components/react/types/{common.ts → common.d.ts} +0 -0
@@ -1,10 +1,11 @@
1
- import { View, Dimensions } from 'react-native';
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, useState } from 'react';
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
- pagerWrapper: {
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
- const defaultHeight = (normalStyle?.height || 150);
90
- const defaultWidth = (normalStyle?.width || width || 375);
91
- const initWidth = typeof defaultWidth === 'number' ? defaultWidth - previousMargin - nextMargin : defaultWidth;
92
- const initHeight = typeof defaultHeight === 'number' ? defaultHeight - previousMargin - nextMargin : defaultHeight;
93
- const [widthState, setWidthState] = useState(initWidth);
94
- const [heightState, setHeightState] = useState(initHeight);
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 targetIndex = useSharedValue(0);
109
+ const currentIndex = useSharedValue(props.current || 0);
110
+ // const initOffset = getOffset(props.current || 0, initStep)
103
111
  // 记录元素的偏移量
104
- const offset = useSharedValue(0);
105
- const strTrans = 'translation' + dir.value.toUpperCase();
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(false);
113
- // 用户是否触发了move事件,起点在onStart, 触发move事件才会执行onEnd, 1. 移动一定会触发onStart, onTouchesMove, onEnd 2. 点击未进行操作, 会触发onTouchsUp
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.value === 'x' ? width - previousMargin - nextMargin : width;
145
- const realHeight = dir.value === 'y' ? height - previousMargin - nextMargin : height;
146
- setWidthState(realWidth);
147
- setHeightState(realHeight);
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
- const step = dir.value === 'x' ? widthState : heightState;
151
- if (isNaN(+step))
156
+ if (!step.value)
152
157
  return {};
153
158
  const dotStep = dotCommonStyle.width + dotCommonStyle.marginRight + dotCommonStyle.marginLeft;
154
- return {
155
- transform: [{
156
- translateX: targetIndex.value * dotStep
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
- const stepValue = getStepValue();
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 < totalElements.value; 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={[styles['pagination_' + [dir.value]]]}>
172
- <View style={[styles.pagerWrapper]}>
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 pageStyle = { width: widthState, height: heightState };
194
+ const intLen = children.length;
189
195
  let renderChild = children.slice();
190
- if (props.circular && totalElements.value > 1) {
196
+ if (circular && intLen > 1) {
191
197
  // 最前面加最后一个元素
192
- const lastChild = React.cloneElement(children[totalElements.value - 1]);
198
+ const lastChild = React.cloneElement(children[intLen - 1], { key: 'clone0' });
193
199
  // 最后面加第一个元素
194
- const firstChild = React.cloneElement(children[0]);
195
- renderChild = [lastChild].concat(renderChild).concat(firstChild);
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
- return renderChild.map((child, index) => {
210
+ const arrChildren = renderChild.map((child, index) => {
198
211
  const extraStyle = {};
199
- const xCondition = dir.value === 'x' && typeof widthState === 'number';
200
- const yCondition = dir.value === 'y' && typeof heightState === 'number';
201
- if (index === 0 && (xCondition || yCondition)) {
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 === totalElements.value - 1 && (xCondition || yCondition)) {
206
- nextMargin && dir.value === 'x' && (extraStyle.marginRight = nextMargin);
207
- nextMargin && dir.value === 'y' && (extraStyle.marginBottom = nextMargin);
216
+ if (index === intLen - 1 && !circular) {
217
+ nextMargin && dir === 'x' && (extraStyle.marginRight = nextMargin);
218
+ nextMargin && dir === 'y' && (extraStyle.marginBottom = nextMargin);
208
219
  }
209
- return (<Animated.View style={[
210
- pageStyle,
211
- extraStyle
212
- ]} key={'page' + index}>
213
- {child}
214
- </Animated.View>);
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
- function createAutoPlay() {
218
- let targetOffset = 0;
219
- let nextIndex = targetIndex.value;
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 += 1;
227
- targetOffset = -nextIndex * step.value;
228
- offset.value = withTiming(targetOffset, {
229
- duration: easeDuration,
230
- easing: easeMap[easeingFunc]
231
- }, () => {
232
- offset.value = targetOffset;
233
- targetIndex.value = nextIndex;
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
- offset.value = targetOffset;
260
- targetIndex.value = nextIndex;
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
- const eventData = getCustomEvent('change', {}, { detail: { current, source: 'touch' }, layoutRef: layoutRef });
267
- props.bindchange && props.bindchange(eventData);
268
- }
269
- function getStepValue() {
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 getInitOffset() {
274
- const stepValue = getStepValue();
275
- if (isNaN(+stepValue))
314
+ function getOffset(index, stepValue) {
315
+ if (!stepValue)
276
316
  return 0;
277
317
  let targetOffset = 0;
278
- if (props.circular && totalElements.value > 1) {
279
- const targetIndex = (props.current || 0) + patchElementNum;
280
- targetOffset = -stepValue * targetIndex;
318
+ if (circular && children.length > 1) {
319
+ const targetIndex = index + patchElmNum;
320
+ targetOffset = -(stepValue * targetIndex - preMargin);
281
321
  }
282
- else if (props.current && props.current > 0) {
283
- targetOffset = -props.current * stepValue;
322
+ else {
323
+ targetOffset = -index * stepValue;
284
324
  }
285
325
  return targetOffset;
286
326
  }
287
- function loop() {
288
- if (!paused.current) {
289
- timerId.current = setTimeout(() => {
290
- createAutoPlay();
291
- loop();
292
- }, intervalTimer);
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 pauseLoop() {
296
- paused.current = true;
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
- useAnimatedReaction(() => targetIndex.value, (newIndex, preIndex) => {
352
+ // 1. 用户在当前页切换选中项,动画;用户携带选中index打开到swiper页直接选中不走动画
353
+ useAnimatedReaction(() => currentIndex.value, (newIndex, preIndex) => {
306
354
  // 这里必须传递函数名, 直接写()=> {}形式会报 访问了未sharedValue信息
307
- const isInit = !preIndex && newIndex === 0;
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
- // 这里stepValue 有时候拿不到
314
- const stepValue = getStepValue();
315
- if (isNaN(+stepValue)) {
316
- return;
360
+ let patchStep = 0;
361
+ if (preMargin !== preMarginShared.value) {
362
+ patchStep += preMargin - preMarginShared.value;
317
363
  }
318
- step.value = stepValue;
319
- const targetOffset = getInitOffset();
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
- else {
330
- offset.value = targetOffset;
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
- }, [props.current, widthState, heightState]);
374
+ }, [preMargin, nextMargin]);
333
375
  useEffect(() => {
334
- const stepValue = getStepValue();
335
- if (isNaN(+stepValue)) {
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
- return () => { pauseLoop(); };
348
- }, [props.autoplay, widthState, heightState]);
349
- function getTargetPosition(eventData) {
350
- 'worklet';
351
- // 移动的距离
352
- const { translation } = eventData;
353
- let resetOffsetPos = 0;
354
- let selectedIndex = targetIndex.value;
355
- // 是否临界点
356
- let isCriticalItem = false;
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
- else if (moveToIndex <= patchElementNum - 1) {
376
- selectedIndex = moveToIndex === 0 ? totalElements.value - patchElementNum : totalElements.value - 1;
377
- resetOffsetPos = (selectedIndex + patchElementNum) * step.value;
378
- moveToTargetPos = moveToIndex * step.value;
379
- isCriticalItem = true;
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
- selectedIndex = moveToIndex - patchElementNum;
383
- moveToTargetPos = moveToIndex * step.value;
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
- return {
387
- selectedIndex,
388
- isCriticalItem,
389
- resetOffset: -resetOffsetPos,
390
- targetOffset: -moveToTargetPos
391
- };
392
- }
393
- function canMove(eventData) {
394
- 'worklet';
395
- const { translation } = eventData;
396
- const stepValue = getStepValue();
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 currentOffset - Math.abs(translation) > 0;
462
+ return true;
404
463
  }
405
464
  }
406
- else {
407
- return true;
408
- }
409
- }
410
- function handleEnd(eventData) {
411
- 'worklet';
412
- const { isCriticalItem, targetOffset, resetOffset, selectedIndex } = getTargetPosition(eventData);
413
- if (isCriticalItem) {
414
- offset.value = withTiming(targetOffset, {
415
- duration: easeDuration,
416
- easing: easeMap[easeingFunc]
417
- }, () => {
418
- if (touchfinish.value !== false) {
419
- targetIndex.value = selectedIndex;
420
- offset.value = resetOffset;
421
- runOnJS(resumeLoop)();
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
- else {
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
- targetIndex.value = selectedIndex;
432
- offset.value = targetOffset;
508
+ currentIndex.value = moveToIndex;
433
509
  runOnJS(resumeLoop)();
434
510
  }
435
511
  });
436
512
  }
437
- }
438
- function handleBack(eventData) {
439
- 'worklet';
440
- const { translation } = eventData;
441
- // 向右滑动的back:trans < 0, 向左滑动的back: trans < 0
442
- const currentOffset = Math.abs(offset.value);
443
- const curIndex = currentOffset / step.value;
444
- const moveToIndex = (translation < 0 ? Math.floor(curIndex) : Math.ceil(curIndex)) - patchElementNum;
445
- const targetOffset = -(moveToIndex + patchElementNum) * step.value;
446
- offset.value = withTiming(targetOffset, {
447
- duration: easeDuration,
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
- if (currentOffset > -posReverseEnd) {
492
- isBoundary = true;
493
- resetOffset = moveStep * elementsLength;
529
+ else {
530
+ handleBack({ translation: diffOffset });
494
531
  }
495
532
  }
496
- else if (translation > 0) {
497
- const posEnd = (patchElementNum - 1) * step.value;
498
- const posReverseEnd = (patchElementNum + totalElements.value) * step.value;
499
- if (currentOffset > -posEnd) {
500
- isBoundary = true;
501
- resetOffset = moveStep * elementsLength + step.value + (moveStep === 1 ? translation : 0);
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 (currentOffset < -posReverseEnd) {
504
- isBoundary = true;
505
- resetOffset = moveStep * elementsLength + patchElementNum * step.value;
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
- return {
509
- isBoundary,
510
- resetOffset: -resetOffset
511
- };
512
- }
513
- const gestureHandler = Gesture.Pan()
514
- .onBegin((e) => {
515
- 'worklet';
516
- touchfinish.value = false;
517
- cancelAnimation(offset);
518
- runOnJS(pauseLoop)();
519
- preAbsolutePos.value = e[strAbso];
520
- })
521
- .onStart(() => {
522
- 'worklet';
523
- isTriggerStart.value = true;
524
- })
525
- .onTouchesMove((e) => {
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: customTrans.value
591
+ translation: moveDistance
552
592
  };
553
- handleLongPress(eventData);
554
- }
555
- isTriggerStart.value = false;
556
- touchfinish.value = true;
557
- })
558
- .onEnd((e) => {
559
- 'worklet';
560
- const eventData = {
561
- translation: e[strTrans]
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
- if (!props.circular && !canMove(eventData) && isTriggerStart.value) {
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.value === 'x') {
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={[{ flexDirection: dir.value === 'x' ? 'row' : 'column' }, animatedStyles]}>
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 (totalElements.value === 1) {
660
+ if (children.length === 1) {
597
661
  return renderSwiper();
598
662
  }
599
663
  else {