@mpxjs/webpack-plugin 2.9.59 → 2.9.64

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 (115) hide show
  1. package/lib/index.js +1 -3
  2. package/lib/platform/style/wx/index.js +344 -270
  3. package/lib/platform/template/wx/component-config/checkbox-group.js +8 -0
  4. package/lib/platform/template/wx/component-config/checkbox.js +8 -0
  5. package/lib/platform/template/wx/component-config/cover-image.js +15 -0
  6. package/lib/platform/template/wx/component-config/cover-view.js +9 -0
  7. package/lib/platform/template/wx/component-config/form.js +13 -1
  8. package/lib/platform/template/wx/component-config/icon.js +8 -0
  9. package/lib/platform/template/wx/component-config/index.js +5 -1
  10. package/lib/platform/template/wx/component-config/label.js +15 -0
  11. package/lib/platform/template/wx/component-config/movable-area.js +18 -1
  12. package/lib/platform/template/wx/component-config/movable-view.js +18 -1
  13. package/lib/platform/template/wx/component-config/navigator.js +8 -0
  14. package/lib/platform/template/wx/component-config/picker-view-column.js +8 -0
  15. package/lib/platform/template/wx/component-config/picker-view.js +18 -2
  16. package/lib/platform/template/wx/component-config/picker.js +14 -1
  17. package/lib/platform/template/wx/component-config/radio-group.js +8 -0
  18. package/lib/platform/template/wx/component-config/radio.js +8 -0
  19. package/lib/platform/template/wx/component-config/root-portal.js +15 -0
  20. package/lib/platform/template/wx/component-config/switch.js +8 -0
  21. package/lib/platform/template/wx/component-config/unsupported.js +1 -3
  22. package/lib/react/processScript.js +2 -0
  23. package/lib/react/processStyles.js +1 -0
  24. package/lib/react/processTemplate.js +2 -3
  25. package/lib/react/style-helper.js +12 -7
  26. package/lib/runtime/components/react/context.ts +40 -0
  27. package/lib/runtime/components/react/dist/context.js +8 -0
  28. package/lib/runtime/components/react/dist/getInnerListeners.js +34 -12
  29. package/lib/runtime/components/react/dist/mpx-button.jsx +88 -88
  30. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +82 -0
  31. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +139 -0
  32. package/lib/runtime/components/react/dist/mpx-form.jsx +61 -0
  33. package/lib/runtime/components/react/dist/mpx-icon.jsx +48 -0
  34. package/lib/runtime/components/react/dist/mpx-image/index.jsx +39 -43
  35. package/lib/runtime/components/react/dist/mpx-image/svg.jsx +3 -2
  36. package/lib/runtime/components/react/dist/mpx-input.jsx +63 -37
  37. package/lib/runtime/components/react/dist/mpx-label.jsx +55 -0
  38. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +41 -0
  39. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +346 -0
  40. package/lib/runtime/components/react/dist/mpx-navigator.jsx +35 -0
  41. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +69 -0
  42. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +138 -0
  43. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +142 -0
  44. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +94 -0
  45. package/lib/runtime/components/react/dist/mpx-picker/regionData.js +6099 -0
  46. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +76 -0
  47. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +244 -0
  48. package/lib/runtime/components/react/dist/mpx-picker/type.js +1 -0
  49. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +107 -0
  50. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +162 -0
  51. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +80 -0
  52. package/lib/runtime/components/react/dist/mpx-radio.jsx +154 -0
  53. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +15 -0
  54. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +93 -70
  55. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +281 -157
  56. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +21 -11
  57. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +19 -11
  58. package/lib/runtime/components/react/dist/mpx-switch.jsx +79 -0
  59. package/lib/runtime/components/react/dist/mpx-text.jsx +21 -49
  60. package/lib/runtime/components/react/dist/mpx-textarea.jsx +2 -2
  61. package/lib/runtime/components/react/dist/mpx-view.jsx +451 -146
  62. package/lib/runtime/components/react/dist/mpx-web-view.jsx +17 -20
  63. package/lib/runtime/components/react/dist/parser.js +218 -0
  64. package/lib/runtime/components/react/dist/types/common.js +1 -0
  65. package/lib/runtime/components/react/dist/useNodesRef.js +3 -8
  66. package/lib/runtime/components/react/dist/utils.jsx +433 -0
  67. package/lib/runtime/components/react/getInnerListeners.ts +43 -21
  68. package/lib/runtime/components/react/mpx-button.tsx +129 -119
  69. package/lib/runtime/components/react/mpx-checkbox-group.tsx +152 -0
  70. package/lib/runtime/components/react/mpx-checkbox.tsx +234 -0
  71. package/lib/runtime/components/react/mpx-form.tsx +117 -0
  72. package/lib/runtime/components/react/mpx-icon.tsx +106 -0
  73. package/lib/runtime/components/react/mpx-image/index.tsx +62 -68
  74. package/lib/runtime/components/react/mpx-image/svg.tsx +7 -5
  75. package/lib/runtime/components/react/mpx-input.tsx +90 -42
  76. package/lib/runtime/components/react/mpx-label.tsx +110 -0
  77. package/lib/runtime/components/react/mpx-movable-area.tsx +81 -0
  78. package/lib/runtime/components/react/mpx-movable-view.tsx +424 -0
  79. package/lib/runtime/components/react/mpx-navigator.tsx +67 -0
  80. package/lib/runtime/components/react/mpx-picker/date.tsx +82 -0
  81. package/lib/runtime/components/react/mpx-picker/index.tsx +155 -0
  82. package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +156 -0
  83. package/lib/runtime/components/react/mpx-picker/region.tsx +107 -0
  84. package/lib/runtime/components/react/mpx-picker/regionData.ts +6101 -0
  85. package/lib/runtime/components/react/mpx-picker/selector.tsx +91 -0
  86. package/lib/runtime/components/react/mpx-picker/time.tsx +270 -0
  87. package/lib/runtime/components/react/mpx-picker/type.ts +107 -0
  88. package/lib/runtime/components/react/mpx-picker-view-column.tsx +156 -0
  89. package/lib/runtime/components/react/mpx-picker-view.tsx +220 -0
  90. package/lib/runtime/components/react/mpx-radio-group.tsx +150 -0
  91. package/lib/runtime/components/react/mpx-radio.tsx +230 -0
  92. package/lib/runtime/components/react/mpx-root-portal.tsx +27 -0
  93. package/lib/runtime/components/react/mpx-scroll-view.tsx +184 -130
  94. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +308 -183
  95. package/lib/runtime/components/react/mpx-swiper/index.tsx +27 -19
  96. package/lib/runtime/components/react/mpx-swiper/type.ts +23 -5
  97. package/lib/runtime/components/react/mpx-swiper-item.tsx +49 -14
  98. package/lib/runtime/components/react/mpx-switch.tsx +148 -0
  99. package/lib/runtime/components/react/mpx-text.tsx +53 -77
  100. package/lib/runtime/components/react/mpx-textarea.tsx +3 -3
  101. package/lib/runtime/components/react/mpx-view.tsx +576 -195
  102. package/lib/runtime/components/react/mpx-web-view.tsx +34 -39
  103. package/lib/runtime/components/react/parser.ts +245 -0
  104. package/lib/runtime/components/react/types/common.ts +12 -0
  105. package/lib/runtime/components/react/types/getInnerListeners.ts +2 -1
  106. package/lib/runtime/components/react/types/global.d.ts +17 -1
  107. package/lib/runtime/components/react/useNodesRef.ts +4 -10
  108. package/lib/runtime/components/react/utils.tsx +505 -0
  109. package/lib/runtime/optionProcessor.js +19 -17
  110. package/lib/template-compiler/compiler.js +84 -61
  111. package/lib/template-compiler/gen-node-react.js +7 -9
  112. package/lib/web/processStyles.js +2 -5
  113. package/package.json +8 -3
  114. package/lib/runtime/components/react/dist/utils.js +0 -80
  115. package/lib/runtime/components/react/utils.ts +0 -92
@@ -1,19 +1,23 @@
1
1
  /**
2
2
  * swiper 实现
3
3
  */
4
- import { View, ScrollView, Dimensions } from 'react-native';
5
- import React, { forwardRef, useState, useRef, useEffect } from 'react';
4
+ import { Animated, View, Dimensions, Platform } from 'react-native';
5
+ import { forwardRef, useState, useRef, useEffect } from 'react';
6
6
  import { getCustomEvent } from '../getInnerListeners';
7
7
  import useNodesRef from '../useNodesRef'; // 引入辅助函数
8
+ import { useTransformStyle, splitStyle, splitProps, useLayout, wrapChildren } from '../utils';
8
9
  /**
9
10
  * 默认的Style类型
10
11
  */
11
12
  const styles = {
13
+ slide: {
14
+ backgroundColor: 'transparent'
15
+ },
12
16
  container_x: {
13
- position: 'relative',
17
+ position: 'relative'
14
18
  },
15
19
  container_y: {
16
- position: 'relative',
20
+ position: 'relative'
17
21
  },
18
22
  pagination_x: {
19
23
  position: 'absolute',
@@ -23,7 +27,7 @@ const styles = {
23
27
  flexDirection: 'row',
24
28
  flex: 1,
25
29
  justifyContent: 'center',
26
- alignItems: 'center',
30
+ alignItems: 'center'
27
31
  },
28
32
  pagination_y: {
29
33
  position: 'absolute',
@@ -33,27 +37,42 @@ const styles = {
33
37
  flexDirection: 'column',
34
38
  flex: 1,
35
39
  justifyContent: 'center',
36
- alignItems: 'center',
40
+ alignItems: 'center'
37
41
  }
38
42
  };
39
43
  const _Carouse = forwardRef((props, ref) => {
40
44
  // 默认取水平方向的width
41
45
  const { width } = Dimensions.get('window');
42
- const defaultHeight = 150;
46
+ const { style, previousMargin = 0, nextMargin = 0, enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight } = props;
47
+ // 计算transfrom之类的
48
+ const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, {
49
+ enableVar,
50
+ externalVarContext,
51
+ parentFontSize,
52
+ parentWidth,
53
+ parentHeight
54
+ });
55
+ const { textStyle, innerStyle } = splitStyle(normalStyle);
56
+ const { textProps } = splitProps(props);
57
+ const newChild = Array.isArray(props.children) ? props.children.filter(child => child) : props.children;
58
+ const totalElements = Array.isArray(newChild) ? newChild.length : (newChild ? 1 : 0);
59
+ const defaultHeight = (normalStyle?.height || 150);
60
+ const defaultWidth = (normalStyle?.width || width || 375);
43
61
  const dir = props.horizontal === false ? 'y' : 'x';
44
62
  // state的offset默认值
45
- const defaultX = width * (props.circular ? props.current + 1 : props.current) || 0;
46
- const defaultY = defaultHeight * (props.circular ? props.current + 1 : props.current) || 0;
63
+ // const initIndex = props.circular ? props.current + 1: (props.current || 0)
64
+ // 记录真正的下标索引, 不包括循环前后加入的索引, 游标
65
+ const initIndex = props.current || 0;
66
+ // 这里要排除超过元素个数的设置
67
+ const initOffsetIndex = initIndex + (props.circular && totalElements > 1 ? 1 : 0);
68
+ const defaultX = (defaultWidth * initOffsetIndex) || 0;
69
+ const defaultY = (defaultHeight * initOffsetIndex) || 0;
47
70
  // 内部存储上一次的offset值
48
- const newChild = Array.isArray(props.children) ? props.children.filter(child => child) : props.children;
49
- // 默认设置为初次渲染
50
- const initRenderRef = useRef(true);
51
71
  const autoplayTimerRef = useRef(null);
52
- let loopJumpTimerRef = useRef(null);
53
72
  const { nodeRef: scrollViewRef } = useNodesRef(props, ref, {});
54
- const autoplayEndRef = useRef(false);
73
+ const {
55
74
  // 存储layout布局信息
56
- const layoutRef = useRef({});
75
+ layoutRef, layoutProps, layoutStyle } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout: onWrapperLayout });
57
76
  // 内部存储上一次的偏移量
58
77
  const internalsRef = useRef({
59
78
  offset: {
@@ -62,123 +81,198 @@ const _Carouse = forwardRef((props, ref) => {
62
81
  },
63
82
  isScrolling: false
64
83
  });
84
+ const isDragRef = useRef(false);
65
85
  const [state, setState] = useState({
66
86
  children: newChild,
67
- width: width || 375,
68
- height: defaultHeight,
69
- index: 0,
70
- total: Array.isArray(newChild) ? newChild.length : (newChild ? 1 : 0),
87
+ width: dir === 'x' && typeof defaultWidth === 'number' ? defaultWidth - previousMargin - nextMargin : defaultWidth,
88
+ height: dir === 'y' && typeof defaultHeight === 'number' ? defaultHeight - previousMargin - nextMargin : defaultHeight,
89
+ // 真正的游标索引, 从0开始
90
+ index: initIndex,
91
+ total: totalElements,
71
92
  offset: {
72
93
  x: dir === 'x' ? defaultX : 0,
73
94
  y: dir === 'y' ? defaultY : 0
74
95
  },
75
- loopJump: false,
76
96
  dir
77
97
  });
98
+ /**
99
+ * @desc: 开启下一次自动轮播
100
+ */
101
+ function createAutoPlay() {
102
+ autoplayTimerRef.current && clearTimeout(autoplayTimerRef.current);
103
+ autoplayTimerRef.current = setTimeout(() => {
104
+ startAutoPlay();
105
+ }, props.interval || 500);
106
+ }
78
107
  useEffect(() => {
79
108
  // 确认这个是变化的props变化的时候才执行,还是初始化的时候就执行
80
109
  if (props.autoplay) {
81
- startAutoPlay();
110
+ createAutoPlay();
82
111
  }
83
- else {
84
- startSwiperLoop();
112
+ }, [props.autoplay, props.current, state.index, state.width, state.height]);
113
+ useEffect(() => {
114
+ // 确认这个是变化的props变化的时候才执行,还是初始化的时候就执行
115
+ if (!props.autoplay && props.current !== state.index) {
116
+ const initIndex = props.current || 0;
117
+ // 这里要排除超过元素个数的设置
118
+ const initOffsetIndex = initIndex + (props.circular && totalElements > 1 ? 1 : 0);
119
+ const defaultX = (defaultWidth * initOffsetIndex) || 0;
120
+ const offset = {
121
+ x: dir === 'x' ? defaultX : 0,
122
+ y: dir === 'y' ? defaultY : 0
123
+ };
124
+ state.offset = offset;
125
+ internalsRef.current.offset = offset;
126
+ setState((preState) => {
127
+ return {
128
+ ...preState,
129
+ offset
130
+ };
131
+ });
85
132
  }
86
- }, [props.autoplay, props.current, state.index]);
133
+ }, [props.current]);
87
134
  /**
88
- * 更新index,以视图的offset计算当前的索引
135
+ * @desc: 更新状态: indexoffset, 并响应索引变化的事件
136
+ * scrollViewOffset: 移动到的目标位置
89
137
  */
90
- function updateIndex(scrollViewOffset) {
91
- const diff = scrollViewOffset[dir] - internalsRef.current.offset[state.dir];
92
- if (!diff)
93
- return;
94
- const step = dir === 'x' ? state.width : state.height;
95
- let loopJump = false;
96
- let newIndex = state.index + Math.round(diff / step);
97
- // 若是循环circular
98
- // 1. 当前索引-1, 初始化为最后一个索引, 且scrollView的偏移量设置为 每个元素的步长 * 一共多少个元素, 这里为什么不减一呢
99
- // 2. 当前索引>total, 初始化为第一个元素,且scrollView的偏移量设置为一个元素的步长
100
- if (props.circular) {
101
- if (state.index <= -1) {
102
- newIndex = state.total - 1;
103
- scrollViewOffset[state.dir] = step * state.total;
104
- loopJump = true;
105
- }
106
- else if (newIndex >= state.total) {
107
- newIndex = 0;
108
- scrollViewOffset[state.dir] = step;
109
- loopJump = true;
110
- }
111
- }
112
- // 存储当前的偏移量
113
- internalsRef.current.offset = scrollViewOffset;
114
- // 这里需不需要区分是否loop,初始化????
138
+ function updateIndex(scrollViewOffset, useIndex = false) {
139
+ const { nextIndex, nextOffset } = getNextConfig(scrollViewOffset);
140
+ updateState(nextIndex, nextOffset);
141
+ // 更新完状态之后, 开启新的loop
142
+ }
143
+ /**
144
+ * 更新索引状态
145
+ */
146
+ function updateState(index, offset) {
147
+ internalsRef.current.offset = offset;
115
148
  setState((preState) => {
116
149
  const newState = {
117
150
  ...preState,
118
- index: newIndex,
119
- offset: scrollViewOffset,
120
- loopJump
151
+ index: index,
152
+ // offset用来指示当前scrollView的偏移量
153
+ offset: offset
121
154
  };
122
155
  return newState;
123
156
  });
124
157
  internalsRef.current.isScrolling = false;
125
158
  // getCustomEvent
126
- const eventData = getCustomEvent('change', {}, { detail: { current: newIndex, source: 'touch' }, layoutRef: layoutRef });
159
+ const eventData = getCustomEvent('change', {}, { detail: { current: index, source: 'touch' }, layoutRef: layoutRef });
127
160
  props.bindchange && props.bindchange(eventData);
128
- // 更新完状态之后, 开启新的loop
129
161
  }
130
162
  /**
131
- * 用户手动点击播放
132
- * 触发scrollView的onScrollEnd事件 => 然后更新索引 => 通过useEffect事件 => startSwiperLoop => 主动更新scrollView到指定的位置
133
- * 若是circular, 到最后一个索引会更新为0,但是视觉要scrollView到下一个
134
- * 若是circular, 到第一个再往前索引会更新为total-1, 但是视觉是展示的最后一个
163
+ * @desc: 获取下一个位置的索引、scrollView的contentOffset、scrollTo到的offset
164
+ * @desc: 包括正循环、反向循环、不循环
165
+ * 其中循环模式为了实现无缝链接, 会将结合contentOffset, 和 scrollTo的offset,
166
+ * 先scrollTo一个位置的坐标, 然后通过updateIndex设置真正的index和内容的offset,视觉上是无缝
135
167
  */
136
- function startSwiperLoop() {
137
- loopJumpTimerRef.current = setTimeout(() => {
138
- let offset = { x: 0, y: 0, animated: false };
139
- if (state.index > 0) {
140
- offset = props.horizontal ? { x: state.width * state.index, y: 0, animated: false } : { x: 0, y: state.height * state.index, animated: false };
168
+ function getNextConfig(scrollViewOffset) {
169
+ const step = state.dir === 'x' ? state.width : state.height;
170
+ const currentOffset = state.offset;
171
+ let nextIndex = state.index + 1;
172
+ let nextOffset = currentOffset;
173
+ // autoMoveOffset scrollView 滚动到前后增加的位置
174
+ let autoMoveOffset = currentOffset;
175
+ let isBack = false;
176
+ let isAutoEnd = false;
177
+ // 如果是循环反向的
178
+ if (scrollViewOffset?.[state.dir] < currentOffset[state.dir]) {
179
+ isBack = true;
180
+ nextIndex = isBack ? nextIndex - 2 : nextIndex;
181
+ }
182
+ if (!props.circular) {
183
+ // nextIndex = isBack ? nextIndex - 2 : nextIndex
184
+ nextOffset = Object.assign({}, currentOffset, { [state.dir]: step * nextIndex });
185
+ }
186
+ else {
187
+ if (isBack) {
188
+ if (nextIndex < 0) {
189
+ // 反向: scollView 滚动到虚拟的位置
190
+ autoMoveOffset = Object.assign({}, currentOffset, { [state.dir]: 0 });
191
+ nextIndex = state.total - 1;
192
+ // 反向: 数组最后一个index
193
+ nextOffset = Object.assign({}, currentOffset, { [state.dir]: step * state.total });
194
+ isAutoEnd = true;
195
+ }
196
+ else {
197
+ // 反向非最后一个
198
+ nextOffset = Object.assign({}, currentOffset, { [state.dir]: (nextIndex + 1) * step });
199
+ }
141
200
  }
142
- if (props.circular) {
143
- offset = props.horizontal ? { x: state.width * (state.index + 1), y: 0, animated: false } : { x: 0, y: state.height * (state.index + 1), animated: false };
201
+ else {
202
+ if (nextIndex > state.total - 1) {
203
+ autoMoveOffset = Object.assign({}, currentOffset, { [state.dir]: step * (nextIndex + 1) });
204
+ nextIndex = 0;
205
+ nextOffset = Object.assign({}, currentOffset, { [state.dir]: step });
206
+ isAutoEnd = true;
207
+ }
208
+ else {
209
+ // nextIndex = nextIndex,
210
+ nextOffset = Object.assign({}, currentOffset, { [state.dir]: (nextIndex + 1) * step });
211
+ }
144
212
  }
145
- scrollViewRef.current?.scrollTo(offset);
146
- internalsRef.current.offset = offset;
147
- }, props.duration || 500);
213
+ }
214
+ return {
215
+ // 下一个要滚动到的实际元素的索引
216
+ nextIndex,
217
+ // 下一个要滚动到实际元素的offset
218
+ nextOffset,
219
+ // scrollTo一个位置的坐标, 虚拟元素的位置
220
+ autoMoveOffset,
221
+ isAutoEnd
222
+ };
148
223
  }
149
224
  /**
150
- * 开启自动轮播
151
- * 每间隔interval scrollView的offset更改到下一个位置,通过onScrollEnd来获取contentOffset再计算要更新的索引index
225
+ * @desc: 开启自动轮播
152
226
  */
153
227
  function startAutoPlay() {
154
- // 已经开启过autopaly则不重新创建
155
- if (!Array.isArray(state.children) || !props.autoplay || internalsRef.current.isScrolling || autoplayEndRef.current) {
228
+ if (state.width && isNaN(+state.width)) {
229
+ createAutoPlay();
156
230
  return;
157
231
  }
158
- autoplayTimerRef.current && clearTimeout(autoplayTimerRef.current);
159
- // 非循环自动播放的形式下 到最后一帧 结束自动播放
160
- if (!props.circular && state.index === state.total - 1) {
161
- autoplayEndRef.current = true;
232
+ if (!Array.isArray(state.children)) {
162
233
  return;
163
234
  }
164
- // 开启自动播放
165
- autoplayTimerRef.current = setTimeout(() => {
166
- if (state.total < 2)
167
- return;
168
- const nexStep = 1;
169
- const toIndex = (props.circular ? 1 : 0) + nexStep + state.index;
170
- let x = 0;
171
- let y = 0;
172
- if (state.dir === 'x')
173
- x = toIndex * state.width;
174
- if (state.dir === 'y')
175
- y = toIndex * state.height;
176
- // animated会影响切换的offset,先改为false
177
- scrollViewRef.current?.scrollTo({ x, y, animated: false });
178
- internalsRef.current.isScrolling = true;
179
- autoplayEndRef.current = false;
180
- updateIndex({ x, y });
181
- }, props.interval || 5000);
235
+ const step = state.dir === 'x' ? state.width : state.height;
236
+ const { nextOffset, autoMoveOffset, isAutoEnd } = getNextConfig(state.offset);
237
+ // 这里可以scroll到下一个元素, 但是把scrollView的偏移量在设置为content,视觉效果就没了吧
238
+ // scrollViewRef.current?.scrollTo({ x: nextOffset['x'], y: nextOffset['y'], animated: true })
239
+ if (Platform.OS === 'ios') {
240
+ if (!isAutoEnd) {
241
+ scrollViewRef.current?.scrollTo({ x: nextOffset.x, y: nextOffset.y, animated: true });
242
+ }
243
+ else {
244
+ if (state.dir === 'x') {
245
+ scrollViewRef.current?.scrollTo({ x: autoMoveOffset.x, y: autoMoveOffset.x, animated: true });
246
+ }
247
+ else {
248
+ scrollViewRef.current?.scrollTo({ x: autoMoveOffset.y, y: autoMoveOffset.y, animated: true });
249
+ }
250
+ }
251
+ }
252
+ else {
253
+ if (!isAutoEnd) {
254
+ scrollViewRef.current?.scrollTo({ x: nextOffset.x, y: nextOffset.y, animated: true });
255
+ onScrollEnd({
256
+ nativeEvent: {
257
+ contentOffset: {
258
+ x: +nextOffset.x,
259
+ y: +nextOffset.y
260
+ }
261
+ }
262
+ });
263
+ }
264
+ else {
265
+ // 安卓无法实现视觉的无缝连接, 只能回到真正的位置, 且安卓调用scrollTo不能触发onMomentumScrollEnd,还未找到为啥
266
+ if (state.dir === 'x') {
267
+ scrollViewRef.current?.scrollTo({ x: step, y: step, animated: true });
268
+ // scrollViewRef.current?.scrollTo({ x: autoMoveOffset.x, y: autoMoveOffset.y, animated: true })
269
+ }
270
+ else {
271
+ scrollViewRef.current?.scrollTo({ x: autoMoveOffset.x, y: step, animated: true });
272
+ }
273
+ updateState(0, nextOffset);
274
+ }
275
+ }
182
276
  }
183
277
  /**
184
278
  * 当用户开始拖动此视图时调用此函数, 更新当前在滚动态
@@ -186,10 +280,17 @@ const _Carouse = forwardRef((props, ref) => {
186
280
  function onScrollBegin() {
187
281
  internalsRef.current.isScrolling = true;
188
282
  }
283
+ /**
284
+ * 当用户开始拖动结束
285
+ */
189
286
  function onScrollEnd(event) {
287
+ // 这里安卓好像没有触发onScrollEnd, 调用scrollTo的时候
288
+ if (totalElements === 1) {
289
+ return;
290
+ }
190
291
  internalsRef.current.isScrolling = false;
191
292
  // 用户手动滑动更新索引后,如果开启了自动轮播等重新开始
192
- updateIndex(event.nativeEvent.contentOffset);
293
+ updateIndex(event.nativeEvent.contentOffset, true);
193
294
  }
194
295
  /**
195
296
  * 当拖拽结束时,检测是否可滚动
@@ -197,63 +298,81 @@ const _Carouse = forwardRef((props, ref) => {
197
298
  function onScrollEndDrag(event) {
198
299
  const { contentOffset } = event.nativeEvent;
199
300
  const { index, total } = state;
301
+ isDragRef.current = true;
200
302
  const internalOffset = internalsRef.current.offset;
201
303
  const previousOffset = props.horizontal ? internalOffset.x : internalOffset.y;
202
- const newOffset = props.horizontal ? contentOffset.x : contentOffset.y;
203
- if (previousOffset === newOffset && (index === 0 || index === total - 1)) {
304
+ const moveOffset = props.horizontal ? contentOffset.x : contentOffset.y;
305
+ if (previousOffset === moveOffset && (index === 0 || index === total - 1)) {
204
306
  internalsRef.current.isScrolling = false;
205
307
  }
206
308
  }
207
309
  /**
208
- * 垂直方向时,获取单个元素的布局,更新
310
+ * @desc: 水平方向时,获取元素的布局,更新, 其中如果传递100%时需要依赖measure计算元算的宽高
209
311
  */
210
- function onItemLayout(event) {
211
- if (!initRenderRef.current || state.dir === 'x')
212
- return;
213
- const { width, height } = event.nativeEvent.layout;
214
- if (state.total > 1) {
215
- internalsRef.current.offset[state.dir] = (state.dir === 'y' ? height * state.index : state.width * state.index);
216
- }
217
- if (!state.offset.x && !state.offset.y) {
218
- state.offset = internalsRef.current.offset;
219
- }
220
- if (initRenderRef.current && state.total > 1) {
221
- scrollViewRef.current?.scrollTo({ ...internalsRef.current.offset, animated: false });
222
- initRenderRef.current = false;
312
+ function onWrapperLayout(e) {
313
+ if (hasSelfPercent) {
314
+ const { width, height } = e?.nativeEvent?.layout || {};
315
+ setWidth(width || 0);
316
+ setHeight(height || 0);
223
317
  }
224
- setState((preState) => {
225
- return {
226
- ...preState,
227
- height
228
- };
229
- });
230
- }
231
- /**
232
- * 水平方向时,获取单个元素的布局,更新
233
- */
234
- function onWrapperLayout() {
235
318
  if (props.enableOffset) {
236
- // @ts-ignore
237
319
  scrollViewRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
238
320
  layoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
321
+ const isWDiff = state.width !== width;
322
+ const isHDiff = state.height !== height;
323
+ if (isWDiff || isHDiff) {
324
+ const changeState = {
325
+ width: isWDiff ? width : state.width,
326
+ height: isHDiff ? height : state.height
327
+ };
328
+ const attr = state.dir === 'x' ? 'width' : 'height';
329
+ changeState[attr] = changeState[attr] - previousMargin - nextMargin;
330
+ const correctOffset = Object.assign({}, state.offset, {
331
+ [state.dir]: initOffsetIndex * (state.dir === 'x' ? changeState.width : changeState.height)
332
+ });
333
+ state.offset = correctOffset;
334
+ state.width = changeState.width;
335
+ state.height = changeState.height;
336
+ setState((preState) => {
337
+ return {
338
+ ...preState,
339
+ offset: correctOffset,
340
+ width: changeState.width,
341
+ height: changeState.height
342
+ };
343
+ });
344
+ scrollViewRef.current?.scrollTo({ x: correctOffset.x, y: correctOffset.y, animated: false });
345
+ }
239
346
  props.getInnerLayout && props.getInnerLayout(layoutRef);
240
347
  });
241
348
  }
242
- if (state.dir === 'y')
243
- return;
244
- if (!state.offset.x && !state.offset.y) {
245
- state.offset = internalsRef.current.offset;
349
+ }
350
+ function getOffset() {
351
+ const step = state.dir === 'x' ? state.width : state.height;
352
+ if (!step || Number.isNaN(+step))
353
+ return [];
354
+ const offsetArray = [];
355
+ if (previousMargin) {
356
+ offsetArray.push(0);
357
+ for (let i = 1; i < totalElements; i++) {
358
+ offsetArray.push(i * step - previousMargin);
359
+ }
246
360
  }
247
- if (!initRenderRef.current && state.total > 1) {
248
- scrollViewRef.current?.scrollTo({ ...state.offset, animated: false });
249
- initRenderRef.current = false;
361
+ else {
362
+ for (let i = 0; i < totalElements; i++) {
363
+ offsetArray.push(i * step);
364
+ }
250
365
  }
366
+ return offsetArray;
251
367
  }
252
368
  function renderScrollView(pages) {
253
- let scrollElementProps = {
369
+ const offsetsArray = getOffset();
370
+ const scrollElementProps = {
254
371
  ref: scrollViewRef,
255
372
  horizontal: props.horizontal,
256
- pagingEnabled: true,
373
+ pagingEnabled: false,
374
+ snapToOffsets: offsetsArray,
375
+ decelerationRate: 0.99,
257
376
  showsHorizontalScrollIndicator: false,
258
377
  showsVerticalScrollIndicator: false,
259
378
  bounces: false,
@@ -261,14 +380,15 @@ const _Carouse = forwardRef((props, ref) => {
261
380
  removeClippedSubviews: true,
262
381
  automaticallyAdjustContentInsets: false
263
382
  };
264
- return (<ScrollView {...scrollElementProps} overScrollMode="always" contentOffset={state.offset} onScrollBeginDrag={onScrollBegin} onMomentumScrollEnd={onScrollEnd} onScrollEndDrag={onScrollEndDrag}>
383
+ const layoutStyle = dir === 'x' ? { width: defaultWidth, height: defaultHeight } : { width: defaultWidth };
384
+ return (<Animated.ScrollView {...scrollElementProps} style={[layoutStyle]} overScrollMode="always" contentOffset={state.offset} onScrollBeginDrag={onScrollBegin} onMomentumScrollEnd={onScrollEnd} onScrollEndDrag={onScrollEndDrag}>
265
385
  {pages}
266
- </ScrollView>);
386
+ </Animated.ScrollView>);
267
387
  }
268
388
  function renderPagination() {
269
389
  if (state.total <= 1)
270
390
  return null;
271
- let dots = [];
391
+ const dots = [];
272
392
  const activeDotStyle = [{
273
393
  backgroundColor: props.activeDotColor || '#007aff',
274
394
  width: 8,
@@ -303,51 +423,55 @@ const _Carouse = forwardRef((props, ref) => {
303
423
  }
304
424
  function renderPages() {
305
425
  const { width, height, total, children } = state;
306
- const { circular, previousMargin, nextMargin, innerProps } = props;
426
+ const { circular } = props;
307
427
  const pageStyle = { width: width, height: height };
428
+ // 设置了previousMargin或者nextMargin,
429
+ // 1. 元素的宽度是减去这两个数目之和
430
+ // 2. previousMargin设置marginLeft正值, nextmargin设置marginRight负值
431
+ // 3. 第一个元素设置previousMargin 和 nextMargin, 最后一个元素
308
432
  if (total > 1 && Array.isArray(children)) {
309
433
  let arrElements = [];
310
434
  // pages = ["2", "0", "1", "2", "0"]
311
- let pages = Array.isArray(children) && Object.keys(children) || [];
435
+ const pages = Array.isArray(children) ? Object.keys(children) : [];
312
436
  /* 无限循环的时候 */
313
437
  if (circular) {
314
438
  pages.unshift(total - 1 + '');
315
439
  pages.push('0');
316
440
  }
317
441
  arrElements = pages.map((page, i) => {
318
- let pageStyle2 = { width: width, height: height };
319
442
  const extraStyle = {};
320
- if (previousMargin) {
321
- extraStyle.left = +previousMargin;
443
+ if (i === 0 && dir === 'x' && typeof width === 'number') {
444
+ previousMargin && (extraStyle.marginLeft = previousMargin);
322
445
  }
323
- if (nextMargin && state.index === i - 1) {
324
- const half = Math.floor(+nextMargin / 2);
325
- extraStyle.marginLeft = -half;
326
- extraStyle.paddingLeft = half;
446
+ else if (i === pages.length - 1 && typeof width === 'number') {
447
+ nextMargin && (extraStyle.marginRight = nextMargin);
327
448
  }
328
- return (<View style={[pageStyle2, extraStyle]} key={'page' + i} onLayout={onItemLayout}>
329
- {children[+page]}
330
- </View>);
449
+ // return (<View style={[pageStyle, styles.slide, extraStyle]} key={ 'page' + i}>{children[+page]}</View>)
450
+ return (<View style={[pageStyle, styles.slide, extraStyle]} key={'page' + i}>
451
+ {wrapChildren({
452
+ children: children[+page]
453
+ }, {
454
+ hasVarDec,
455
+ varContext: varContextRef.current,
456
+ textStyle,
457
+ textProps
458
+ })}
459
+ </View>);
331
460
  });
332
461
  return arrElements;
333
462
  }
334
463
  else {
335
- return (<View style={pageStyle} key={0}>
464
+ const realElement = (<View style={pageStyle} key={0}>
336
465
  {children}
337
466
  </View>);
467
+ return realElement;
338
468
  }
339
469
  }
340
- const vStyle = {};
341
- if (dir === 'y') {
342
- vStyle.height = defaultHeight;
343
- }
344
470
  const pages = renderPages();
345
- const strStyle = 'container_' + state.dir;
346
- const eventProps = props.innerProps || {};
347
- return (<View style={[styles[strStyle], vStyle]} {...eventProps} onLayout={onWrapperLayout}>
471
+ return (<View style={[normalStyle, innerStyle, layoutStyle]} {...layoutProps}>
348
472
  {renderScrollView(pages)}
349
473
  {props.showsPagination && renderPagination()}
350
- </View>);
474
+ </View>);
351
475
  });
352
476
  _Carouse.displayName = '_Carouse';
353
477
  export default _Carouse;