@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,21 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* swiper 实现
|
|
3
3
|
*/
|
|
4
|
-
import { View, ScrollView, Dimensions,
|
|
5
|
-
import
|
|
4
|
+
import { Animated, View, ScrollView, Dimensions, NativeSyntheticEvent, NativeScrollEvent, NativeScrollPoint, Platform, LayoutChangeEvent } from 'react-native'
|
|
5
|
+
import { JSX, forwardRef, useState, useRef, useEffect, ReactNode } from 'react'
|
|
6
6
|
import { CarouseProps, CarouseState } from './type'
|
|
7
7
|
import { getCustomEvent } from '../getInnerListeners'
|
|
8
8
|
import useNodesRef, { HandlerRef } from '../useNodesRef' // 引入辅助函数
|
|
9
|
+
import { useTransformStyle, splitStyle, splitProps, useLayout, wrapChildren } from '../utils'
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* 默认的Style类型
|
|
12
13
|
*/
|
|
13
14
|
const styles: { [key: string]: Object } = {
|
|
15
|
+
slide: {
|
|
16
|
+
backgroundColor: 'transparent'
|
|
17
|
+
},
|
|
14
18
|
container_x: {
|
|
15
|
-
position: 'relative'
|
|
19
|
+
position: 'relative'
|
|
16
20
|
},
|
|
17
21
|
container_y: {
|
|
18
|
-
position: 'relative'
|
|
22
|
+
position: 'relative'
|
|
19
23
|
},
|
|
20
24
|
pagination_x: {
|
|
21
25
|
position: 'absolute',
|
|
@@ -25,7 +29,7 @@ const styles: { [key: string]: Object } = {
|
|
|
25
29
|
flexDirection: 'row',
|
|
26
30
|
flex: 1,
|
|
27
31
|
justifyContent: 'center',
|
|
28
|
-
alignItems: 'center'
|
|
32
|
+
alignItems: 'center'
|
|
29
33
|
},
|
|
30
34
|
|
|
31
35
|
pagination_y: {
|
|
@@ -36,30 +40,62 @@ const styles: { [key: string]: Object } = {
|
|
|
36
40
|
flexDirection: 'column',
|
|
37
41
|
flex: 1,
|
|
38
42
|
justifyContent: 'center',
|
|
39
|
-
alignItems: 'center'
|
|
43
|
+
alignItems: 'center'
|
|
40
44
|
}
|
|
41
45
|
}
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>((props , ref): React.JSX.Element => {
|
|
47
|
+
const _Carouse = forwardRef<HandlerRef<ScrollView & View, CarouseProps>, CarouseProps>((props, ref): JSX.Element => {
|
|
45
48
|
// 默认取水平方向的width
|
|
46
49
|
const { width } = Dimensions.get('window')
|
|
47
|
-
const
|
|
50
|
+
const {
|
|
51
|
+
style,
|
|
52
|
+
previousMargin = 0,
|
|
53
|
+
nextMargin = 0,
|
|
54
|
+
enableVar,
|
|
55
|
+
externalVarContext,
|
|
56
|
+
parentFontSize,
|
|
57
|
+
parentWidth,
|
|
58
|
+
parentHeight
|
|
59
|
+
} = props
|
|
60
|
+
// 计算transfrom之类的
|
|
61
|
+
const {
|
|
62
|
+
normalStyle,
|
|
63
|
+
hasVarDec,
|
|
64
|
+
varContextRef,
|
|
65
|
+
hasSelfPercent,
|
|
66
|
+
setWidth,
|
|
67
|
+
setHeight
|
|
68
|
+
} = useTransformStyle(style, {
|
|
69
|
+
enableVar,
|
|
70
|
+
externalVarContext,
|
|
71
|
+
parentFontSize,
|
|
72
|
+
parentWidth,
|
|
73
|
+
parentHeight
|
|
74
|
+
})
|
|
75
|
+
const { textStyle, innerStyle } = splitStyle(normalStyle)
|
|
76
|
+
const { textProps } = splitProps(props)
|
|
77
|
+
const newChild = Array.isArray(props.children) ? props.children.filter(child => child) : props.children
|
|
78
|
+
const totalElements = Array.isArray(newChild) ? newChild.length : (newChild ? 1 : 0)
|
|
79
|
+
const defaultHeight = (normalStyle?.height || 150)
|
|
80
|
+
const defaultWidth = (normalStyle?.width || width || 375)
|
|
48
81
|
const dir = props.horizontal === false ? 'y' : 'x'
|
|
49
82
|
// state的offset默认值
|
|
50
|
-
const
|
|
51
|
-
|
|
83
|
+
// const initIndex = props.circular ? props.current + 1: (props.current || 0)
|
|
84
|
+
// 记录真正的下标索引, 不包括循环前后加入的索引, 游标
|
|
85
|
+
const initIndex = props.current || 0
|
|
86
|
+
// 这里要排除超过元素个数的设置
|
|
87
|
+
const initOffsetIndex = initIndex + (props.circular && totalElements > 1 ? 1 : 0)
|
|
88
|
+
const defaultX = (defaultWidth * initOffsetIndex) || 0
|
|
89
|
+
const defaultY = (defaultHeight * initOffsetIndex) || 0
|
|
52
90
|
// 内部存储上一次的offset值
|
|
53
|
-
const newChild = Array.isArray(props.children) ? props.children.filter(child => child) : props.children
|
|
54
|
-
// 默认设置为初次渲染
|
|
55
|
-
const initRenderRef = useRef(true)
|
|
56
91
|
const autoplayTimerRef = useRef<ReturnType <typeof setTimeout> | null>(null)
|
|
57
|
-
|
|
58
|
-
const {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
92
|
+
const { nodeRef: scrollViewRef } = useNodesRef<ScrollView & View, CarouseProps>(props, ref, {})
|
|
93
|
+
const {
|
|
94
|
+
// 存储layout布局信息
|
|
95
|
+
layoutRef,
|
|
96
|
+
layoutProps,
|
|
97
|
+
layoutStyle
|
|
98
|
+
} = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout: onWrapperLayout })
|
|
63
99
|
// 内部存储上一次的偏移量
|
|
64
100
|
const internalsRef = useRef({
|
|
65
101
|
offset: {
|
|
@@ -68,125 +104,194 @@ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>(
|
|
|
68
104
|
},
|
|
69
105
|
isScrolling: false
|
|
70
106
|
})
|
|
107
|
+
const isDragRef = useRef(false)
|
|
71
108
|
const [state, setState] = useState({
|
|
72
109
|
children: newChild,
|
|
73
|
-
width:
|
|
74
|
-
height: defaultHeight,
|
|
75
|
-
|
|
76
|
-
|
|
110
|
+
width: dir === 'x' && typeof defaultWidth === 'number' ? defaultWidth - previousMargin - nextMargin : defaultWidth,
|
|
111
|
+
height: dir === 'y' && typeof defaultHeight === 'number' ? defaultHeight - previousMargin - nextMargin : defaultHeight,
|
|
112
|
+
// 真正的游标索引, 从0开始
|
|
113
|
+
index: initIndex,
|
|
114
|
+
total: totalElements,
|
|
77
115
|
offset: {
|
|
78
116
|
x: dir === 'x' ? defaultX : 0,
|
|
79
|
-
y: dir === 'y' ? defaultY: 0
|
|
117
|
+
y: dir === 'y' ? defaultY : 0
|
|
80
118
|
},
|
|
81
|
-
loopJump: false,
|
|
82
119
|
dir
|
|
83
|
-
} as CarouseState)
|
|
120
|
+
} as CarouseState)
|
|
121
|
+
/**
|
|
122
|
+
* @desc: 开启下一次自动轮播
|
|
123
|
+
*/
|
|
124
|
+
function createAutoPlay () {
|
|
125
|
+
autoplayTimerRef.current && clearTimeout(autoplayTimerRef.current)
|
|
126
|
+
autoplayTimerRef.current = setTimeout(() => {
|
|
127
|
+
startAutoPlay()
|
|
128
|
+
}, props.interval || 500)
|
|
129
|
+
}
|
|
84
130
|
|
|
85
131
|
useEffect(() => {
|
|
86
132
|
// 确认这个是变化的props变化的时候才执行,还是初始化的时候就执行
|
|
87
133
|
if (props.autoplay) {
|
|
88
|
-
|
|
89
|
-
} else {
|
|
90
|
-
startSwiperLoop()
|
|
134
|
+
createAutoPlay()
|
|
91
135
|
}
|
|
92
|
-
}, [props.autoplay, props.current, state.index])
|
|
136
|
+
}, [props.autoplay, props.current, state.index, state.width, state.height])
|
|
93
137
|
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
// 确认这个是变化的props变化的时候才执行,还是初始化的时候就执行
|
|
140
|
+
if (!props.autoplay && props.current !== state.index) {
|
|
141
|
+
const initIndex = props.current || 0
|
|
142
|
+
// 这里要排除超过元素个数的设置
|
|
143
|
+
const initOffsetIndex = initIndex + (props.circular && totalElements > 1 ? 1 : 0)
|
|
144
|
+
const defaultX = (defaultWidth * initOffsetIndex) || 0
|
|
145
|
+
const offset = {
|
|
146
|
+
x: dir === 'x' ? defaultX : 0,
|
|
147
|
+
y: dir === 'y' ? defaultY : 0
|
|
148
|
+
}
|
|
149
|
+
state.offset = offset
|
|
150
|
+
internalsRef.current.offset = offset
|
|
151
|
+
setState((preState) => {
|
|
152
|
+
return {
|
|
153
|
+
...preState,
|
|
154
|
+
offset
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
}, [props.current])
|
|
94
159
|
/**
|
|
95
|
-
*
|
|
160
|
+
* @desc: 更新状态: index和offset, 并响应索引变化的事件
|
|
161
|
+
* scrollViewOffset: 移动到的目标位置
|
|
96
162
|
*/
|
|
97
|
-
function updateIndex (scrollViewOffset: NativeScrollPoint) {
|
|
98
|
-
const
|
|
99
|
-
|
|
163
|
+
function updateIndex (scrollViewOffset: NativeScrollPoint, useIndex = false) {
|
|
164
|
+
const { nextIndex, nextOffset } = getNextConfig(scrollViewOffset)
|
|
165
|
+
updateState(nextIndex, nextOffset)
|
|
166
|
+
// 更新完状态之后, 开启新的loop
|
|
167
|
+
}
|
|
100
168
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// 2. 当前索引>total, 初始化为第一个元素,且scrollView的偏移量设置为一个元素的步长
|
|
107
|
-
if (props.circular) {
|
|
108
|
-
if (state.index <= -1) {
|
|
109
|
-
newIndex = state.total - 1
|
|
110
|
-
scrollViewOffset[state.dir] = step * state.total
|
|
111
|
-
loopJump = true
|
|
112
|
-
} else if (newIndex >= state.total) {
|
|
113
|
-
newIndex = 0
|
|
114
|
-
scrollViewOffset[state.dir] = step
|
|
115
|
-
loopJump = true
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
// 存储当前的偏移量
|
|
119
|
-
internalsRef.current.offset = scrollViewOffset
|
|
120
|
-
// 这里需不需要区分是否loop,初始化????
|
|
169
|
+
/**
|
|
170
|
+
* 更新索引状态
|
|
171
|
+
*/
|
|
172
|
+
function updateState (index: number, offset: { x: number, y: number}) {
|
|
173
|
+
internalsRef.current.offset = offset
|
|
121
174
|
setState((preState) => {
|
|
122
|
-
const newState =
|
|
175
|
+
const newState = {
|
|
123
176
|
...preState,
|
|
124
|
-
index:
|
|
125
|
-
offset
|
|
126
|
-
|
|
177
|
+
index: index,
|
|
178
|
+
// offset用来指示当前scrollView的偏移量
|
|
179
|
+
offset: offset
|
|
127
180
|
}
|
|
128
181
|
return newState
|
|
129
182
|
})
|
|
130
183
|
internalsRef.current.isScrolling = false
|
|
131
184
|
// getCustomEvent
|
|
132
|
-
const eventData = getCustomEvent('change', {}, { detail: {current:
|
|
185
|
+
const eventData = getCustomEvent('change', {}, { detail: { current: index, source: 'touch' }, layoutRef: layoutRef })
|
|
133
186
|
props.bindchange && props.bindchange(eventData)
|
|
134
|
-
// 更新完状态之后, 开启新的loop
|
|
135
187
|
}
|
|
136
188
|
|
|
137
189
|
/**
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
190
|
+
* @desc: 获取下一个位置的索引、scrollView的contentOffset、scrollTo到的offset
|
|
191
|
+
* @desc: 包括正循环、反向循环、不循环
|
|
192
|
+
* 其中循环模式为了实现无缝链接, 会将结合contentOffset, 和 scrollTo的offset,
|
|
193
|
+
* 先scrollTo一个位置的坐标, 然后通过updateIndex设置真正的index和内容的offset,视觉上是无缝
|
|
142
194
|
*/
|
|
143
|
-
function
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
195
|
+
function getNextConfig (scrollViewOffset: NativeScrollPoint) {
|
|
196
|
+
const step = state.dir === 'x' ? state.width : state.height
|
|
197
|
+
const currentOffset = state.offset
|
|
198
|
+
let nextIndex = state.index + 1
|
|
199
|
+
let nextOffset = currentOffset
|
|
200
|
+
// autoMoveOffset scrollView 滚动到前后增加的位置
|
|
201
|
+
let autoMoveOffset = currentOffset
|
|
202
|
+
let isBack = false
|
|
203
|
+
let isAutoEnd = false
|
|
204
|
+
// 如果是循环反向的
|
|
205
|
+
if (scrollViewOffset?.[state.dir] < currentOffset[state.dir]) {
|
|
206
|
+
isBack = true
|
|
207
|
+
nextIndex = isBack ? nextIndex - 2 : nextIndex
|
|
208
|
+
}
|
|
209
|
+
if (!props.circular) {
|
|
210
|
+
// nextIndex = isBack ? nextIndex - 2 : nextIndex
|
|
211
|
+
nextOffset = Object.assign({}, currentOffset, { [state.dir]: step * nextIndex })
|
|
212
|
+
} else {
|
|
213
|
+
if (isBack) {
|
|
214
|
+
if (nextIndex < 0) {
|
|
215
|
+
// 反向: scollView 滚动到虚拟的位置
|
|
216
|
+
autoMoveOffset = Object.assign({}, currentOffset, { [state.dir]: 0 })
|
|
217
|
+
nextIndex = state.total - 1
|
|
218
|
+
// 反向: 数组最后一个index
|
|
219
|
+
nextOffset = Object.assign({}, currentOffset, { [state.dir]: step * state.total })
|
|
220
|
+
isAutoEnd = true
|
|
221
|
+
} else {
|
|
222
|
+
// 反向非最后一个
|
|
223
|
+
nextOffset = Object.assign({}, currentOffset, { [state.dir]: (nextIndex + 1) * step })
|
|
224
|
+
}
|
|
225
|
+
} else {
|
|
226
|
+
if (nextIndex > state.total - 1) {
|
|
227
|
+
autoMoveOffset = Object.assign({}, currentOffset, { [state.dir]: step * (nextIndex + 1) })
|
|
228
|
+
nextIndex = 0
|
|
229
|
+
nextOffset = Object.assign({}, currentOffset, { [state.dir]: step })
|
|
230
|
+
isAutoEnd = true
|
|
231
|
+
} else {
|
|
232
|
+
// nextIndex = nextIndex,
|
|
233
|
+
nextOffset = Object.assign({}, currentOffset, { [state.dir]: (nextIndex + 1) * step })
|
|
234
|
+
}
|
|
151
235
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
// 下一个要滚动到的实际元素的索引
|
|
239
|
+
nextIndex,
|
|
240
|
+
// 下一个要滚动到实际元素的offset
|
|
241
|
+
nextOffset,
|
|
242
|
+
// scrollTo一个位置的坐标, 虚拟元素的位置
|
|
243
|
+
autoMoveOffset,
|
|
244
|
+
isAutoEnd
|
|
245
|
+
}
|
|
155
246
|
}
|
|
156
247
|
|
|
157
248
|
/**
|
|
158
|
-
* 开启自动轮播
|
|
159
|
-
* 每间隔interval scrollView的offset更改到下一个位置,通过onScrollEnd来获取contentOffset再计算要更新的索引index
|
|
249
|
+
* @desc: 开启自动轮播
|
|
160
250
|
*/
|
|
161
251
|
function startAutoPlay () {
|
|
162
|
-
|
|
163
|
-
|
|
252
|
+
if (state.width && isNaN(+state.width)) {
|
|
253
|
+
createAutoPlay()
|
|
164
254
|
return
|
|
165
255
|
}
|
|
166
|
-
|
|
167
|
-
// 非循环自动播放的形式下 到最后一帧 结束自动播放
|
|
168
|
-
if (!props.circular && state.index === state.total -1) {
|
|
169
|
-
autoplayEndRef.current = true
|
|
256
|
+
if (!Array.isArray(state.children)) {
|
|
170
257
|
return
|
|
171
258
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
259
|
+
const step = state.dir === 'x' ? state.width : state.height
|
|
260
|
+
const { nextOffset, autoMoveOffset, isAutoEnd } = getNextConfig(state.offset)
|
|
261
|
+
// 这里可以scroll到下一个元素, 但是把scrollView的偏移量在设置为content,视觉效果就没了吧
|
|
262
|
+
// scrollViewRef.current?.scrollTo({ x: nextOffset['x'], y: nextOffset['y'], animated: true })
|
|
263
|
+
if (Platform.OS === 'ios') {
|
|
264
|
+
if (!isAutoEnd) {
|
|
265
|
+
scrollViewRef.current?.scrollTo({ x: nextOffset.x, y: nextOffset.y, animated: true })
|
|
266
|
+
} else {
|
|
267
|
+
if (state.dir === 'x') {
|
|
268
|
+
scrollViewRef.current?.scrollTo({ x: autoMoveOffset.x, y: autoMoveOffset.x, animated: true })
|
|
269
|
+
} else {
|
|
270
|
+
scrollViewRef.current?.scrollTo({ x: autoMoveOffset.y, y: autoMoveOffset.y, animated: true })
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
} else {
|
|
274
|
+
if (!isAutoEnd) {
|
|
275
|
+
scrollViewRef.current?.scrollTo({ x: nextOffset.x, y: nextOffset.y, animated: true })
|
|
276
|
+
onScrollEnd({
|
|
277
|
+
nativeEvent: {
|
|
278
|
+
contentOffset: {
|
|
279
|
+
x: +nextOffset.x,
|
|
280
|
+
y: +nextOffset.y
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
} as NativeSyntheticEvent<NativeScrollEvent>)
|
|
284
|
+
} else {
|
|
285
|
+
// 安卓无法实现视觉的无缝连接, 只能回到真正的位置, 且安卓调用scrollTo不能触发onMomentumScrollEnd,还未找到为啥
|
|
286
|
+
if (state.dir === 'x') {
|
|
287
|
+
scrollViewRef.current?.scrollTo({ x: step, y: step, animated: true })
|
|
288
|
+
// scrollViewRef.current?.scrollTo({ x: autoMoveOffset.x, y: autoMoveOffset.y, animated: true })
|
|
289
|
+
} else {
|
|
290
|
+
scrollViewRef.current?.scrollTo({ x: autoMoveOffset.x, y: step, animated: true })
|
|
291
|
+
}
|
|
292
|
+
updateState(0, nextOffset)
|
|
293
|
+
}
|
|
294
|
+
}
|
|
190
295
|
}
|
|
191
296
|
|
|
192
297
|
/**
|
|
@@ -195,11 +300,18 @@ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>(
|
|
|
195
300
|
function onScrollBegin () {
|
|
196
301
|
internalsRef.current.isScrolling = true
|
|
197
302
|
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* 当用户开始拖动结束
|
|
306
|
+
*/
|
|
198
307
|
function onScrollEnd (event: NativeSyntheticEvent<NativeScrollEvent>) {
|
|
308
|
+
// 这里安卓好像没有触发onScrollEnd, 调用scrollTo的时候
|
|
309
|
+
if (totalElements === 1) {
|
|
310
|
+
return
|
|
311
|
+
}
|
|
199
312
|
internalsRef.current.isScrolling = false
|
|
200
|
-
|
|
201
313
|
// 用户手动滑动更新索引后,如果开启了自动轮播等重新开始
|
|
202
|
-
updateIndex(event.nativeEvent.contentOffset)
|
|
314
|
+
updateIndex(event.nativeEvent.contentOffset, true)
|
|
203
315
|
}
|
|
204
316
|
|
|
205
317
|
/**
|
|
@@ -208,66 +320,82 @@ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>(
|
|
|
208
320
|
function onScrollEndDrag (event: NativeSyntheticEvent<NativeScrollEvent>) {
|
|
209
321
|
const { contentOffset } = event.nativeEvent
|
|
210
322
|
const { index, total } = state
|
|
211
|
-
|
|
323
|
+
isDragRef.current = true
|
|
212
324
|
const internalOffset = internalsRef.current.offset
|
|
213
325
|
const previousOffset = props.horizontal ? internalOffset.x : internalOffset.y
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
if (previousOffset === newOffset && (index === 0 || index === total - 1)) {
|
|
326
|
+
const moveOffset = props.horizontal ? contentOffset.x : contentOffset.y
|
|
327
|
+
if (previousOffset === moveOffset && (index === 0 || index === total - 1)) {
|
|
217
328
|
internalsRef.current.isScrolling = false
|
|
218
329
|
}
|
|
219
330
|
}
|
|
220
|
-
/**
|
|
221
|
-
* 垂直方向时,获取单个元素的布局,更新
|
|
222
|
-
*/
|
|
223
|
-
function onItemLayout (event: LayoutChangeEvent) {
|
|
224
|
-
if (!initRenderRef.current || state.dir === 'x') return
|
|
225
|
-
const { width, height } = event.nativeEvent.layout
|
|
226
|
-
if (state.total > 1) {
|
|
227
|
-
internalsRef.current.offset[state.dir] = (state.dir === 'y' ? height * state.index : state.width * state.index)
|
|
228
|
-
}
|
|
229
331
|
|
|
230
|
-
if (!state.offset.x && !state.offset.y) {
|
|
231
|
-
state.offset = internalsRef.current.offset
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
if (initRenderRef.current && state.total > 1) {
|
|
235
|
-
scrollViewRef.current?.scrollTo({ ...internalsRef.current.offset, animated: false })
|
|
236
|
-
initRenderRef.current = false
|
|
237
|
-
}
|
|
238
|
-
setState((preState) => {
|
|
239
|
-
return {
|
|
240
|
-
...preState,
|
|
241
|
-
height
|
|
242
|
-
}
|
|
243
|
-
})
|
|
244
|
-
}
|
|
245
332
|
/**
|
|
246
|
-
*
|
|
333
|
+
* @desc: 水平方向时,获取元素的布局,更新, 其中如果传递100%时需要依赖measure计算元算的宽高
|
|
247
334
|
*/
|
|
248
|
-
function onWrapperLayout () {
|
|
335
|
+
function onWrapperLayout (e: LayoutChangeEvent) {
|
|
336
|
+
if (hasSelfPercent) {
|
|
337
|
+
const { width, height } = e?.nativeEvent?.layout || {}
|
|
338
|
+
setWidth(width || 0)
|
|
339
|
+
setHeight(height || 0)
|
|
340
|
+
}
|
|
249
341
|
if (props.enableOffset) {
|
|
250
|
-
// @ts-ignore
|
|
251
342
|
scrollViewRef.current?.measure((x: number, y: number, width: number, height: number, offsetLeft: number, offsetTop: number) => {
|
|
252
343
|
layoutRef.current = { x, y, width, height, offsetLeft, offsetTop }
|
|
344
|
+
const isWDiff = state.width !== width
|
|
345
|
+
const isHDiff = state.height !== height
|
|
346
|
+
if (isWDiff || isHDiff) {
|
|
347
|
+
const changeState = {
|
|
348
|
+
width: isWDiff ? width : state.width,
|
|
349
|
+
height: isHDiff ? height : state.height
|
|
350
|
+
}
|
|
351
|
+
const attr = state.dir === 'x' ? 'width' : 'height'
|
|
352
|
+
changeState[attr] = changeState[attr] - previousMargin - nextMargin
|
|
353
|
+
const correctOffset = Object.assign({}, state.offset, {
|
|
354
|
+
[state.dir]: initOffsetIndex * (state.dir === 'x' ? changeState.width : changeState.height)
|
|
355
|
+
})
|
|
356
|
+
state.offset = correctOffset
|
|
357
|
+
state.width = changeState.width
|
|
358
|
+
state.height = changeState.height
|
|
359
|
+
setState((preState) => {
|
|
360
|
+
return {
|
|
361
|
+
...preState,
|
|
362
|
+
offset: correctOffset,
|
|
363
|
+
width: changeState.width,
|
|
364
|
+
height: changeState.height
|
|
365
|
+
}
|
|
366
|
+
})
|
|
367
|
+
scrollViewRef.current?.scrollTo({ x: correctOffset.x, y: correctOffset.y, animated: false })
|
|
368
|
+
}
|
|
253
369
|
props.getInnerLayout && props.getInnerLayout(layoutRef)
|
|
254
370
|
})
|
|
255
371
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
if (!
|
|
261
|
-
|
|
262
|
-
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function getOffset (): Array<number> {
|
|
375
|
+
const step = state.dir === 'x' ? state.width : state.height
|
|
376
|
+
if (!step || Number.isNaN(+step)) return []
|
|
377
|
+
const offsetArray = []
|
|
378
|
+
if (previousMargin) {
|
|
379
|
+
offsetArray.push(0)
|
|
380
|
+
for (let i = 1; i < totalElements; i++) {
|
|
381
|
+
offsetArray.push(i * step - previousMargin)
|
|
382
|
+
}
|
|
383
|
+
} else {
|
|
384
|
+
for (let i = 0; i < totalElements; i++) {
|
|
385
|
+
offsetArray.push(i * step)
|
|
386
|
+
}
|
|
263
387
|
}
|
|
388
|
+
return offsetArray
|
|
264
389
|
}
|
|
265
390
|
|
|
266
391
|
function renderScrollView (pages: ReactNode) {
|
|
267
|
-
|
|
392
|
+
const offsetsArray = getOffset()
|
|
393
|
+
const scrollElementProps = {
|
|
268
394
|
ref: scrollViewRef,
|
|
269
395
|
horizontal: props.horizontal,
|
|
270
|
-
pagingEnabled:
|
|
396
|
+
pagingEnabled: false,
|
|
397
|
+
snapToOffsets: offsetsArray,
|
|
398
|
+
decelerationRate: 0.99, // 'fast'
|
|
271
399
|
showsHorizontalScrollIndicator: false,
|
|
272
400
|
showsVerticalScrollIndicator: false,
|
|
273
401
|
bounces: false,
|
|
@@ -275,9 +403,11 @@ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>(
|
|
|
275
403
|
removeClippedSubviews: true,
|
|
276
404
|
automaticallyAdjustContentInsets: false
|
|
277
405
|
}
|
|
406
|
+
const layoutStyle = dir === 'x' ? { width: defaultWidth, height: defaultHeight } : { width: defaultWidth }
|
|
278
407
|
return (
|
|
279
|
-
<ScrollView
|
|
408
|
+
<Animated.ScrollView
|
|
280
409
|
{...scrollElementProps}
|
|
410
|
+
style={[layoutStyle]}
|
|
281
411
|
overScrollMode="always"
|
|
282
412
|
contentOffset={state.offset}
|
|
283
413
|
onScrollBeginDrag={onScrollBegin}
|
|
@@ -285,14 +415,14 @@ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>(
|
|
|
285
415
|
onScrollEndDrag={onScrollEndDrag}
|
|
286
416
|
>
|
|
287
417
|
{pages}
|
|
288
|
-
</ScrollView>
|
|
418
|
+
</Animated.ScrollView>
|
|
289
419
|
)
|
|
290
420
|
}
|
|
291
421
|
|
|
292
422
|
function renderPagination () {
|
|
293
423
|
if (state.total <= 1) return null
|
|
294
|
-
|
|
295
|
-
const activeDotStyle = [
|
|
424
|
+
const dots: Array<ReactNode> = []
|
|
425
|
+
const activeDotStyle = [{
|
|
296
426
|
backgroundColor: props.activeDotColor || '#007aff',
|
|
297
427
|
width: 8,
|
|
298
428
|
height: 8,
|
|
@@ -331,68 +461,63 @@ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>(
|
|
|
331
461
|
|
|
332
462
|
function renderPages () {
|
|
333
463
|
const { width, height, total, children } = state
|
|
334
|
-
const { circular
|
|
464
|
+
const { circular } = props
|
|
335
465
|
const pageStyle = { width: width, height: height }
|
|
466
|
+
// 设置了previousMargin或者nextMargin,
|
|
467
|
+
// 1. 元素的宽度是减去这两个数目之和
|
|
468
|
+
// 2. previousMargin设置marginLeft正值, nextmargin设置marginRight负值
|
|
469
|
+
// 3. 第一个元素设置previousMargin 和 nextMargin, 最后一个元素
|
|
336
470
|
if (total > 1 && Array.isArray(children)) {
|
|
337
471
|
let arrElements: (Array<ReactNode>) = []
|
|
338
472
|
// pages = ["2", "0", "1", "2", "0"]
|
|
339
|
-
|
|
473
|
+
const pages = Array.isArray(children) ? Object.keys(children) : []
|
|
340
474
|
/* 无限循环的时候 */
|
|
341
475
|
if (circular) {
|
|
342
476
|
pages.unshift(total - 1 + '')
|
|
343
477
|
pages.push('0')
|
|
344
478
|
}
|
|
345
479
|
arrElements = pages.map((page, i) => {
|
|
346
|
-
let pageStyle2 = { width: width, height: height }
|
|
347
480
|
const extraStyle = {} as {
|
|
348
|
-
|
|
349
|
-
marginLeft?: number;
|
|
350
|
-
paddingLeft?: number
|
|
481
|
+
[key: string]: any
|
|
351
482
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
if (nextMargin && state.index === i - 1) {
|
|
357
|
-
const half = Math.floor(+nextMargin / 2)
|
|
358
|
-
extraStyle.marginLeft = - half
|
|
359
|
-
extraStyle.paddingLeft = half
|
|
483
|
+
if (i === 0 && dir === 'x' && typeof width === 'number') {
|
|
484
|
+
previousMargin && (extraStyle.marginLeft = previousMargin)
|
|
485
|
+
} else if (i === pages.length - 1 && typeof width === 'number') {
|
|
486
|
+
nextMargin && (extraStyle.marginRight = nextMargin)
|
|
360
487
|
}
|
|
361
|
-
return (
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
488
|
+
// return (<View style={[pageStyle, styles.slide, extraStyle]} key={ 'page' + i}>{children[+page]}</View>)
|
|
489
|
+
return (<View style={[pageStyle, styles.slide, extraStyle]} key={ 'page' + i}>
|
|
490
|
+
{wrapChildren(
|
|
491
|
+
{
|
|
492
|
+
children: children[+page]
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
hasVarDec,
|
|
496
|
+
varContext: varContextRef.current,
|
|
497
|
+
textStyle,
|
|
498
|
+
textProps
|
|
499
|
+
}
|
|
500
|
+
)}
|
|
501
|
+
</View>)
|
|
366
502
|
})
|
|
367
503
|
return arrElements
|
|
368
504
|
} else {
|
|
369
|
-
|
|
505
|
+
const realElement = (
|
|
370
506
|
<View style={pageStyle} key={0}>
|
|
371
507
|
{children}
|
|
372
508
|
</View>
|
|
373
509
|
)
|
|
510
|
+
return realElement
|
|
374
511
|
}
|
|
375
512
|
}
|
|
376
513
|
|
|
377
|
-
const vStyle = {} as { height: number }
|
|
378
|
-
if (dir === 'y') {
|
|
379
|
-
vStyle.height = defaultHeight
|
|
380
|
-
}
|
|
381
514
|
const pages: Array<ReactNode> | ReactNode = renderPages()
|
|
382
|
-
|
|
383
|
-
const eventProps = props.innerProps || {}
|
|
384
|
-
|
|
385
|
-
return (
|
|
386
|
-
<View
|
|
387
|
-
style={[styles[strStyle], vStyle]}
|
|
388
|
-
{...eventProps}
|
|
389
|
-
onLayout={onWrapperLayout}>
|
|
515
|
+
return (<View style={[normalStyle, innerStyle, layoutStyle]} {...layoutProps}>
|
|
390
516
|
{renderScrollView(pages)}
|
|
391
517
|
{props.showsPagination && renderPagination()}
|
|
392
|
-
|
|
393
|
-
|
|
518
|
+
</View>)
|
|
394
519
|
})
|
|
395
520
|
|
|
396
|
-
_Carouse.displayName = '_Carouse'
|
|
521
|
+
_Carouse.displayName = '_Carouse'
|
|
397
522
|
|
|
398
523
|
export default _Carouse
|