@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.
- package/lib/index.js +1 -3
- package/lib/platform/style/wx/index.js +344 -270
- package/lib/platform/template/wx/component-config/checkbox-group.js +8 -0
- package/lib/platform/template/wx/component-config/checkbox.js +8 -0
- package/lib/platform/template/wx/component-config/cover-image.js +15 -0
- package/lib/platform/template/wx/component-config/cover-view.js +9 -0
- package/lib/platform/template/wx/component-config/form.js +13 -1
- package/lib/platform/template/wx/component-config/icon.js +8 -0
- package/lib/platform/template/wx/component-config/index.js +5 -1
- package/lib/platform/template/wx/component-config/label.js +15 -0
- package/lib/platform/template/wx/component-config/movable-area.js +18 -1
- package/lib/platform/template/wx/component-config/movable-view.js +18 -1
- package/lib/platform/template/wx/component-config/navigator.js +8 -0
- package/lib/platform/template/wx/component-config/picker-view-column.js +8 -0
- package/lib/platform/template/wx/component-config/picker-view.js +18 -2
- package/lib/platform/template/wx/component-config/picker.js +14 -1
- package/lib/platform/template/wx/component-config/radio-group.js +8 -0
- package/lib/platform/template/wx/component-config/radio.js +8 -0
- package/lib/platform/template/wx/component-config/root-portal.js +15 -0
- package/lib/platform/template/wx/component-config/switch.js +8 -0
- package/lib/platform/template/wx/component-config/unsupported.js +1 -3
- package/lib/react/processScript.js +2 -0
- package/lib/react/processStyles.js +1 -0
- package/lib/react/processTemplate.js +2 -3
- package/lib/react/style-helper.js +12 -7
- package/lib/runtime/components/react/context.ts +40 -0
- package/lib/runtime/components/react/dist/context.js +8 -0
- package/lib/runtime/components/react/dist/getInnerListeners.js +34 -12
- package/lib/runtime/components/react/dist/mpx-button.jsx +88 -88
- package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +82 -0
- package/lib/runtime/components/react/dist/mpx-checkbox.jsx +139 -0
- package/lib/runtime/components/react/dist/mpx-form.jsx +61 -0
- package/lib/runtime/components/react/dist/mpx-icon.jsx +48 -0
- package/lib/runtime/components/react/dist/mpx-image/index.jsx +39 -43
- package/lib/runtime/components/react/dist/mpx-image/svg.jsx +3 -2
- package/lib/runtime/components/react/dist/mpx-input.jsx +63 -37
- package/lib/runtime/components/react/dist/mpx-label.jsx +55 -0
- package/lib/runtime/components/react/dist/mpx-movable-area.jsx +41 -0
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +346 -0
- package/lib/runtime/components/react/dist/mpx-navigator.jsx +35 -0
- package/lib/runtime/components/react/dist/mpx-picker/date.jsx +69 -0
- package/lib/runtime/components/react/dist/mpx-picker/index.jsx +138 -0
- package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +142 -0
- package/lib/runtime/components/react/dist/mpx-picker/region.jsx +94 -0
- package/lib/runtime/components/react/dist/mpx-picker/regionData.js +6099 -0
- package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +76 -0
- package/lib/runtime/components/react/dist/mpx-picker/time.jsx +244 -0
- package/lib/runtime/components/react/dist/mpx-picker/type.js +1 -0
- package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +107 -0
- package/lib/runtime/components/react/dist/mpx-picker-view.jsx +162 -0
- package/lib/runtime/components/react/dist/mpx-radio-group.jsx +80 -0
- package/lib/runtime/components/react/dist/mpx-radio.jsx +154 -0
- package/lib/runtime/components/react/dist/mpx-root-portal.jsx +15 -0
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +93 -70
- package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +281 -157
- package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +21 -11
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +19 -11
- package/lib/runtime/components/react/dist/mpx-switch.jsx +79 -0
- package/lib/runtime/components/react/dist/mpx-text.jsx +21 -49
- package/lib/runtime/components/react/dist/mpx-textarea.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-view.jsx +451 -146
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +17 -20
- package/lib/runtime/components/react/dist/parser.js +218 -0
- package/lib/runtime/components/react/dist/types/common.js +1 -0
- package/lib/runtime/components/react/dist/useNodesRef.js +3 -8
- package/lib/runtime/components/react/dist/utils.jsx +433 -0
- package/lib/runtime/components/react/getInnerListeners.ts +43 -21
- package/lib/runtime/components/react/mpx-button.tsx +129 -119
- package/lib/runtime/components/react/mpx-checkbox-group.tsx +152 -0
- package/lib/runtime/components/react/mpx-checkbox.tsx +234 -0
- package/lib/runtime/components/react/mpx-form.tsx +117 -0
- package/lib/runtime/components/react/mpx-icon.tsx +106 -0
- package/lib/runtime/components/react/mpx-image/index.tsx +62 -68
- package/lib/runtime/components/react/mpx-image/svg.tsx +7 -5
- package/lib/runtime/components/react/mpx-input.tsx +90 -42
- package/lib/runtime/components/react/mpx-label.tsx +110 -0
- package/lib/runtime/components/react/mpx-movable-area.tsx +81 -0
- package/lib/runtime/components/react/mpx-movable-view.tsx +424 -0
- package/lib/runtime/components/react/mpx-navigator.tsx +67 -0
- package/lib/runtime/components/react/mpx-picker/date.tsx +82 -0
- package/lib/runtime/components/react/mpx-picker/index.tsx +155 -0
- package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +156 -0
- package/lib/runtime/components/react/mpx-picker/region.tsx +107 -0
- package/lib/runtime/components/react/mpx-picker/regionData.ts +6101 -0
- package/lib/runtime/components/react/mpx-picker/selector.tsx +91 -0
- package/lib/runtime/components/react/mpx-picker/time.tsx +270 -0
- package/lib/runtime/components/react/mpx-picker/type.ts +107 -0
- package/lib/runtime/components/react/mpx-picker-view-column.tsx +156 -0
- package/lib/runtime/components/react/mpx-picker-view.tsx +220 -0
- package/lib/runtime/components/react/mpx-radio-group.tsx +150 -0
- package/lib/runtime/components/react/mpx-radio.tsx +230 -0
- package/lib/runtime/components/react/mpx-root-portal.tsx +27 -0
- package/lib/runtime/components/react/mpx-scroll-view.tsx +184 -130
- package/lib/runtime/components/react/mpx-swiper/carouse.tsx +308 -183
- package/lib/runtime/components/react/mpx-swiper/index.tsx +27 -19
- package/lib/runtime/components/react/mpx-swiper/type.ts +23 -5
- package/lib/runtime/components/react/mpx-swiper-item.tsx +49 -14
- package/lib/runtime/components/react/mpx-switch.tsx +148 -0
- package/lib/runtime/components/react/mpx-text.tsx +53 -77
- package/lib/runtime/components/react/mpx-textarea.tsx +3 -3
- package/lib/runtime/components/react/mpx-view.tsx +576 -195
- package/lib/runtime/components/react/mpx-web-view.tsx +34 -39
- package/lib/runtime/components/react/parser.ts +245 -0
- package/lib/runtime/components/react/types/common.ts +12 -0
- package/lib/runtime/components/react/types/getInnerListeners.ts +2 -1
- package/lib/runtime/components/react/types/global.d.ts +17 -1
- package/lib/runtime/components/react/useNodesRef.ts +4 -10
- package/lib/runtime/components/react/utils.tsx +505 -0
- package/lib/runtime/optionProcessor.js +19 -17
- package/lib/template-compiler/compiler.js +84 -61
- package/lib/template-compiler/gen-node-react.js +7 -9
- package/lib/web/processStyles.js +2 -5
- package/package.json +8 -3
- package/lib/runtime/components/react/dist/utils.js +0 -80
- package/lib/runtime/components/react/utils.ts +0 -92
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* swiper 实现
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
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
|
|
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
|
|
46
|
-
|
|
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
|
|
73
|
+
const {
|
|
55
74
|
// 存储layout布局信息
|
|
56
|
-
|
|
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:
|
|
68
|
-
height: defaultHeight,
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
110
|
+
createAutoPlay();
|
|
82
111
|
}
|
|
83
|
-
|
|
84
|
-
|
|
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.
|
|
133
|
+
}, [props.current]);
|
|
87
134
|
/**
|
|
88
|
-
*
|
|
135
|
+
* @desc: 更新状态: index和offset, 并响应索引变化的事件
|
|
136
|
+
* scrollViewOffset: 移动到的目标位置
|
|
89
137
|
*/
|
|
90
|
-
function updateIndex(scrollViewOffset) {
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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:
|
|
119
|
-
offset
|
|
120
|
-
|
|
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:
|
|
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
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
163
|
+
* @desc: 获取下一个位置的索引、scrollView的contentOffset、scrollTo到的offset
|
|
164
|
+
* @desc: 包括正循环、反向循环、不循环
|
|
165
|
+
* 其中循环模式为了实现无缝链接, 会将结合contentOffset, 和 scrollTo的offset,
|
|
166
|
+
* 先scrollTo一个位置的坐标, 然后通过updateIndex设置真正的index和内容的offset,视觉上是无缝
|
|
135
167
|
*/
|
|
136
|
-
function
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
|
|
143
|
-
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
155
|
-
|
|
228
|
+
if (state.width && isNaN(+state.width)) {
|
|
229
|
+
createAutoPlay();
|
|
156
230
|
return;
|
|
157
231
|
}
|
|
158
|
-
|
|
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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
|
203
|
-
if (previousOffset ===
|
|
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
|
|
211
|
-
if (
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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
|
-
|
|
369
|
+
const offsetsArray = getOffset();
|
|
370
|
+
const scrollElementProps = {
|
|
254
371
|
ref: scrollViewRef,
|
|
255
372
|
horizontal: props.horizontal,
|
|
256
|
-
pagingEnabled:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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 (
|
|
321
|
-
extraStyle.
|
|
443
|
+
if (i === 0 && dir === 'x' && typeof width === 'number') {
|
|
444
|
+
previousMargin && (extraStyle.marginLeft = previousMargin);
|
|
322
445
|
}
|
|
323
|
-
if (
|
|
324
|
-
|
|
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={[
|
|
329
|
-
|
|
330
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
474
|
+
</View>);
|
|
351
475
|
});
|
|
352
476
|
_Carouse.displayName = '_Carouse';
|
|
353
477
|
export default _Carouse;
|