@tarojs/components-react 4.1.9-beta.1 → 4.1.9-beta.1-patch.1
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/dist/components/picker/index.js +22 -3
- package/dist/components/picker/index.js.map +1 -1
- package/dist/components/picker/picker-group.js +242 -81
- package/dist/components/picker/picker-group.js.map +1 -1
- package/dist/components/scroll-view/index.js +104 -30
- package/dist/components/scroll-view/index.js.map +1 -1
- package/dist/contexts/ScrollElementContext.js +6 -0
- package/dist/contexts/ScrollElementContext.js.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/original/components/picker/index.js +22 -3
- package/dist/original/components/picker/index.js.map +1 -1
- package/dist/original/components/picker/picker-group.js +242 -81
- package/dist/original/components/picker/picker-group.js.map +1 -1
- package/dist/original/components/picker/style/index.scss +146 -46
- package/dist/original/components/scroll-view/index.js +104 -30
- package/dist/original/components/scroll-view/index.js.map +1 -1
- package/dist/original/contexts/ScrollElementContext.js +6 -0
- package/dist/original/contexts/ScrollElementContext.js.map +1 -0
- package/dist/original/index.js +1 -0
- package/dist/original/index.js.map +1 -1
- package/dist/solid/components/picker/index.js +33 -14
- package/dist/solid/components/picker/index.js.map +1 -1
- package/dist/solid/components/picker/picker-group.js +243 -86
- package/dist/solid/components/picker/picker-group.js.map +1 -1
- package/dist/solid/components/scroll-view/index.js +109 -35
- package/dist/solid/components/scroll-view/index.js.map +1 -1
- package/dist/solid/contexts/ScrollElementContext.js +6 -0
- package/dist/solid/contexts/ScrollElementContext.js.map +1 -0
- package/dist/solid/index.css +1 -1
- package/package.json +6 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createComponent } from 'solid-js/web';
|
|
1
|
+
import { createComponent, mergeProps } from 'solid-js/web';
|
|
2
2
|
import { View, ScrollView } from '@tarojs/components';
|
|
3
3
|
import Taro from '@tarojs/taro';
|
|
4
4
|
import * as React from 'react';
|
|
@@ -7,27 +7,146 @@ import * as React from 'react';
|
|
|
7
7
|
const PICKER_LINE_HEIGHT = 34; // px
|
|
8
8
|
const PICKER_VISIBLE_ITEMS = 7; // 可见行数
|
|
9
9
|
const PICKER_BLANK_ITEMS = 3; // 空白行数
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
10
|
+
const getIndicatorStyle = lineColor => {
|
|
11
|
+
return {
|
|
12
|
+
borderTopColor: lineColor,
|
|
13
|
+
borderBottomColor: lineColor
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
// 大屏方案版本要求
|
|
17
|
+
const MIN_DESIGN_APP_VERSION = 16;
|
|
18
|
+
const MIN_APP_VERSION = '15.7.0';
|
|
19
|
+
// semver 版本比较
|
|
20
|
+
const isAppVersionAtLeast = (version, min) => {
|
|
21
|
+
var _a, _b;
|
|
22
|
+
if (!version || typeof version !== 'string') return false;
|
|
23
|
+
const parts = v => {
|
|
24
|
+
const m = String(v).trim().match(/^(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
|
|
25
|
+
if (!m) return [];
|
|
26
|
+
return [parseInt(m[1], 10) || 0, parseInt(m[2] || '0', 10) || 0, parseInt(m[3] || '0', 10) || 0];
|
|
27
|
+
};
|
|
28
|
+
const a = parts(version);
|
|
29
|
+
const b = parts(min);
|
|
30
|
+
if (a.length === 0) return false;
|
|
31
|
+
if (b.length === 0) return true;
|
|
32
|
+
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
|
33
|
+
const da = (_a = a[i]) !== null && _a !== void 0 ? _a : 0;
|
|
34
|
+
const db = (_b = b[i]) !== null && _b !== void 0 ? _b : 0;
|
|
35
|
+
if (da > db) return true;
|
|
36
|
+
if (da < db) return false;
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
};
|
|
40
|
+
// 读取 JDMobileConfig,异常时返回 undefined
|
|
41
|
+
const tryGetMobileConfigSync = opt => {
|
|
42
|
+
var _a;
|
|
43
|
+
try {
|
|
44
|
+
const fn = (_a = Taro.JDMobileConfig) === null || _a === void 0 ? void 0 : _a.getMobileConfigSync;
|
|
45
|
+
if (typeof fn !== 'function') return undefined;
|
|
46
|
+
return fn(opt);
|
|
47
|
+
} catch (_b) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
// 判断是否启用测量值缩放适配(true=启用, false=使用系统侧缩放)
|
|
52
|
+
const resolveUseMeasuredScale = res => {
|
|
53
|
+
// H5/weapp 不参与大屏系数
|
|
54
|
+
if (process.env.TARO_ENV === 'h5' || process.env.TARO_ENV === 'weapp') {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
// 条件1: designAppVersion < 16,不满足则使用系统侧缩放
|
|
58
|
+
const designAppVersionRaw = res.designAppVersion;
|
|
59
|
+
const designAppVersionMajor = designAppVersionRaw != null ? parseInt(String(designAppVersionRaw).trim(), 10) : Number.NaN;
|
|
60
|
+
if (!Number.isFinite(designAppVersionMajor) || designAppVersionMajor < MIN_DESIGN_APP_VERSION) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
// 条件2: appVersion < 15.7.0,不满足则使用系统侧缩放
|
|
64
|
+
if (!isAppVersionAtLeast(res.version, MIN_APP_VERSION)) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
// 条件3: 平台判断
|
|
68
|
+
const platform = String(res.platform || '').toLowerCase();
|
|
69
|
+
if (platform === 'harmony') {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
if (platform === 'android') {
|
|
73
|
+
const raw = tryGetMobileConfigSync({
|
|
74
|
+
space: 'taro',
|
|
75
|
+
configName: 'config',
|
|
76
|
+
key: 'disableFixBoundingScaleRatio'
|
|
77
|
+
});
|
|
78
|
+
return raw !== 1 && raw !== '1';
|
|
79
|
+
}
|
|
80
|
+
if (platform === 'ios') {
|
|
81
|
+
const raw = tryGetMobileConfigSync({
|
|
82
|
+
space: 'Taro',
|
|
83
|
+
configName: 'excutor',
|
|
84
|
+
key: 'disableBoundingScaleRatio'
|
|
85
|
+
});
|
|
86
|
+
return raw !== 1 && raw !== '1';
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
};
|
|
90
|
+
// 辅助函数:计算 lengthScaleRatio
|
|
91
|
+
const calculateLengthScaleRatio = res => {
|
|
92
|
+
let lengthScaleRatio = res === null || res === void 0 ? void 0 : res.lengthScaleRatio;
|
|
93
|
+
if (lengthScaleRatio == null || lengthScaleRatio === 0) {
|
|
94
|
+
console.warn('Taro.getSystemInfo: lengthScaleRatio 不存在,使用计算值');
|
|
95
|
+
lengthScaleRatio = 1;
|
|
96
|
+
if (res.windowWidth < 320) {
|
|
97
|
+
lengthScaleRatio = res.windowWidth / 320;
|
|
98
|
+
} else if (res.windowWidth >= 400 && res.windowWidth < 600) {
|
|
99
|
+
lengthScaleRatio = res.windowWidth / 400;
|
|
100
|
+
}
|
|
101
|
+
const shortSide = res.windowWidth < res.windowHeight ? res.windowWidth : res.windowHeight;
|
|
102
|
+
const isBigScreen = shortSide >= 600;
|
|
103
|
+
if (isBigScreen) {
|
|
104
|
+
lengthScaleRatio = shortSide / 720;
|
|
29
105
|
}
|
|
30
|
-
}
|
|
106
|
+
}
|
|
107
|
+
return lengthScaleRatio;
|
|
108
|
+
};
|
|
109
|
+
// 辅助函数:获取系统信息的 lengthScaleRatio 并设置 targetScrollTop
|
|
110
|
+
const setTargetScrollTopWithScale = function (setTargetScrollTop, baseValue, randomOffset) {
|
|
111
|
+
let lengthScaleRatio = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
|
|
112
|
+
// H5 和 weapp 不参与放大计算,直接使用 baseValue
|
|
113
|
+
if (process.env.TARO_ENV === 'h5' || process.env.TARO_ENV === 'weapp') {
|
|
114
|
+
const finalValue = randomOffset !== undefined ? baseValue + randomOffset : baseValue;
|
|
115
|
+
setTargetScrollTop(finalValue);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (process.env.TARO_PLATFORM === 'harmony') {
|
|
119
|
+
const scaledValue = baseValue;
|
|
120
|
+
const finalValue = randomOffset !== undefined ? scaledValue + randomOffset : scaledValue;
|
|
121
|
+
setTargetScrollTop(finalValue);
|
|
122
|
+
} else {
|
|
123
|
+
const scaledValue = baseValue * lengthScaleRatio;
|
|
124
|
+
const finalValue = randomOffset !== undefined ? scaledValue + randomOffset : scaledValue;
|
|
125
|
+
setTargetScrollTop(finalValue);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
// 根据 scrollTop 计算选中索引
|
|
129
|
+
// 系统侧缩放模式:scrollHeight 已被系统缩放,直接相除即可
|
|
130
|
+
// 自行缩放模式:需要除以 ratio 换算(harmony 特殊处理,ratio 已内嵌在 itemHeight 中)
|
|
131
|
+
const getSelectedIndex = function (scrollTop, itemHeight) {
|
|
132
|
+
let lengthScaleRatio = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
|
|
133
|
+
let useMeasuredScale = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
134
|
+
if (!useMeasuredScale || process.env.TARO_PLATFORM === 'harmony') {
|
|
135
|
+
return Math.round(scrollTop / itemHeight);
|
|
136
|
+
}
|
|
137
|
+
return Math.round(scrollTop / lengthScaleRatio / itemHeight);
|
|
138
|
+
};
|
|
139
|
+
// 计算单项高度(返回设计稿值)
|
|
140
|
+
const calculateItemHeight = function (scrollView, lengthScaleRatio) {
|
|
141
|
+
let useMeasuredScale = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
142
|
+
if (process.env.TARO_PLATFORM === 'harmony') {
|
|
143
|
+
return useMeasuredScale ? PICKER_LINE_HEIGHT * lengthScaleRatio : PICKER_LINE_HEIGHT;
|
|
144
|
+
}
|
|
145
|
+
if (scrollView && (scrollView === null || scrollView === void 0 ? void 0 : scrollView.scrollHeight)) {
|
|
146
|
+
return useMeasuredScale ? scrollView.scrollHeight / lengthScaleRatio / scrollView.childNodes.length : scrollView.scrollHeight / scrollView.childNodes.length;
|
|
147
|
+
}
|
|
148
|
+
console.warn('Height measurement anomaly');
|
|
149
|
+
return PICKER_LINE_HEIGHT;
|
|
31
150
|
};
|
|
32
151
|
function PickerGroupBasic(props) {
|
|
33
152
|
const {
|
|
@@ -40,6 +159,7 @@ function PickerGroupBasic(props) {
|
|
|
40
159
|
// 使用selectedIndex参数,默认为0
|
|
41
160
|
colors = {}
|
|
42
161
|
} = props;
|
|
162
|
+
const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
|
|
43
163
|
const [targetScrollTop, setTargetScrollTop] = React.useState(0);
|
|
44
164
|
const scrollViewRef = React.useRef(null);
|
|
45
165
|
const itemRefs = React.useRef([]);
|
|
@@ -47,26 +167,31 @@ function PickerGroupBasic(props) {
|
|
|
47
167
|
const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
|
|
48
168
|
// 触摸状态用于优化用户体验
|
|
49
169
|
const [isTouching, setIsTouching] = React.useState(false);
|
|
170
|
+
const lengthScaleRatioRef = React.useRef(1);
|
|
171
|
+
const useMeasuredScaleRef = React.useRef(false);
|
|
50
172
|
const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
|
|
173
|
+
// 初始化时计算 lengthScaleRatio 并判定缩放模式
|
|
51
174
|
React.useEffect(() => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
175
|
+
Taro.getSystemInfo({
|
|
176
|
+
success: res => {
|
|
177
|
+
lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
|
|
178
|
+
useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
|
|
179
|
+
itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
180
|
+
},
|
|
181
|
+
fail: () => {
|
|
182
|
+
lengthScaleRatioRef.current = 1;
|
|
183
|
+
useMeasuredScaleRef.current = false;
|
|
58
184
|
}
|
|
59
|
-
}
|
|
185
|
+
});
|
|
186
|
+
}, []);
|
|
187
|
+
React.useEffect(() => {
|
|
188
|
+
itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
60
189
|
}, [range.length]); // 只在range长度变化时重新计算
|
|
61
|
-
// 获取选中的索引
|
|
62
|
-
const getSelectedIndex = scrollTop => {
|
|
63
|
-
return Math.round(scrollTop / itemHeightRef.current);
|
|
64
|
-
};
|
|
65
190
|
// 当selectedIndex变化时,调整滚动位置
|
|
66
191
|
React.useEffect(() => {
|
|
67
192
|
if (scrollViewRef.current && range.length > 0 && !isTouching) {
|
|
68
193
|
const baseValue = selectedIndex * itemHeightRef.current;
|
|
69
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
|
|
194
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
|
|
70
195
|
setCurrentIndex(selectedIndex);
|
|
71
196
|
}
|
|
72
197
|
}, [selectedIndex, range]);
|
|
@@ -83,16 +208,17 @@ function PickerGroupBasic(props) {
|
|
|
83
208
|
isCenterTimerId.current = setTimeout(() => {
|
|
84
209
|
if (!scrollViewRef.current) return;
|
|
85
210
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
86
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
211
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
87
212
|
setIsTouching(false);
|
|
88
213
|
const baseValue = newIndex * itemHeightRef.current;
|
|
89
214
|
const randomOffset = Math.random() * 0.001; // 随机数为了在一个项内滚动时强制刷新
|
|
90
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
|
|
215
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
|
|
91
216
|
updateIndex(newIndex, columnId);
|
|
92
217
|
onColumnChange === null || onColumnChange === void 0 ? void 0 : onColumnChange({
|
|
93
218
|
columnId,
|
|
94
219
|
index: newIndex
|
|
95
220
|
});
|
|
221
|
+
isCenterTimerId.current = null;
|
|
96
222
|
}, 100);
|
|
97
223
|
};
|
|
98
224
|
// 滚动处理 - 在滚动时计算索引然后更新选中项样式
|
|
@@ -103,7 +229,7 @@ function PickerGroupBasic(props) {
|
|
|
103
229
|
isCenterTimerId.current = null;
|
|
104
230
|
}
|
|
105
231
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
106
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
232
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
107
233
|
if (newIndex !== currentIndex) {
|
|
108
234
|
setCurrentIndex(newIndex);
|
|
109
235
|
}
|
|
@@ -143,9 +269,11 @@ function PickerGroupBasic(props) {
|
|
|
143
269
|
get children() {
|
|
144
270
|
return [createComponent(View, {
|
|
145
271
|
className: "taro-picker__mask"
|
|
146
|
-
}), createComponent(View, {
|
|
272
|
+
}), createComponent(View, mergeProps({
|
|
147
273
|
className: "taro-picker__indicator"
|
|
148
|
-
}
|
|
274
|
+
}, indicatorStyle ? {
|
|
275
|
+
style: indicatorStyle
|
|
276
|
+
} : {})), createComponent(ScrollView, {
|
|
149
277
|
ref: scrollViewRef,
|
|
150
278
|
scrollY: true,
|
|
151
279
|
showScrollbar: false,
|
|
@@ -173,30 +301,37 @@ function PickerGroupTime(props) {
|
|
|
173
301
|
selectedIndex = 0,
|
|
174
302
|
colors = {}
|
|
175
303
|
} = props;
|
|
304
|
+
const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
|
|
176
305
|
const [targetScrollTop, setTargetScrollTop] = React.useState(0);
|
|
177
306
|
const scrollViewRef = React.useRef(null);
|
|
178
307
|
const itemRefs = React.useRef([]);
|
|
179
308
|
const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
|
|
180
309
|
const [isTouching, setIsTouching] = React.useState(false);
|
|
310
|
+
const lengthScaleRatioRef = React.useRef(1);
|
|
311
|
+
const useMeasuredScaleRef = React.useRef(false);
|
|
181
312
|
const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
|
|
313
|
+
// 初始化时计算 lengthScaleRatio 并判定缩放模式
|
|
182
314
|
React.useEffect(() => {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
315
|
+
Taro.getSystemInfo({
|
|
316
|
+
success: res => {
|
|
317
|
+
lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
|
|
318
|
+
useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
|
|
319
|
+
itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
320
|
+
},
|
|
321
|
+
fail: () => {
|
|
322
|
+
lengthScaleRatioRef.current = 1;
|
|
323
|
+
useMeasuredScaleRef.current = false;
|
|
189
324
|
}
|
|
190
|
-
}
|
|
325
|
+
});
|
|
326
|
+
}, []);
|
|
327
|
+
React.useEffect(() => {
|
|
328
|
+
itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
191
329
|
}, [range.length]); // 只在range长度变化时重新计算
|
|
192
|
-
const getSelectedIndex = scrollTop => {
|
|
193
|
-
return Math.round(scrollTop / itemHeightRef.current);
|
|
194
|
-
};
|
|
195
330
|
// 当selectedIndex变化时,调整滚动位置
|
|
196
331
|
React.useEffect(() => {
|
|
197
332
|
if (scrollViewRef.current && range.length > 0 && !isTouching) {
|
|
198
333
|
const baseValue = selectedIndex * itemHeightRef.current;
|
|
199
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
|
|
334
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
|
|
200
335
|
setCurrentIndex(selectedIndex);
|
|
201
336
|
}
|
|
202
337
|
}, [selectedIndex, range]);
|
|
@@ -213,7 +348,7 @@ function PickerGroupTime(props) {
|
|
|
213
348
|
isCenterTimerId.current = setTimeout(() => {
|
|
214
349
|
if (!scrollViewRef.current) return;
|
|
215
350
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
216
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
351
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
217
352
|
setIsTouching(false);
|
|
218
353
|
// 调用updateIndex执行限位逻辑,获取是否触发了限位
|
|
219
354
|
const isLimited = Boolean(updateIndex(newIndex, columnId, true));
|
|
@@ -221,8 +356,9 @@ function PickerGroupTime(props) {
|
|
|
221
356
|
if (!isLimited) {
|
|
222
357
|
const baseValue = newIndex * itemHeightRef.current;
|
|
223
358
|
const randomOffset = Math.random() * 0.001;
|
|
224
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
|
|
359
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
|
|
225
360
|
}
|
|
361
|
+
isCenterTimerId.current = null;
|
|
226
362
|
}, 100);
|
|
227
363
|
};
|
|
228
364
|
// 滚动处理
|
|
@@ -233,7 +369,7 @@ function PickerGroupTime(props) {
|
|
|
233
369
|
isCenterTimerId.current = null;
|
|
234
370
|
}
|
|
235
371
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
236
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
372
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
237
373
|
if (newIndex !== currentIndex) {
|
|
238
374
|
setCurrentIndex(newIndex);
|
|
239
375
|
}
|
|
@@ -273,9 +409,11 @@ function PickerGroupTime(props) {
|
|
|
273
409
|
get children() {
|
|
274
410
|
return [createComponent(View, {
|
|
275
411
|
className: "taro-picker__mask"
|
|
276
|
-
}), createComponent(View, {
|
|
412
|
+
}), createComponent(View, mergeProps({
|
|
277
413
|
className: "taro-picker__indicator"
|
|
278
|
-
}
|
|
414
|
+
}, indicatorStyle ? {
|
|
415
|
+
style: indicatorStyle
|
|
416
|
+
} : {})), createComponent(ScrollView, {
|
|
279
417
|
ref: scrollViewRef,
|
|
280
418
|
scrollY: true,
|
|
281
419
|
showScrollbar: false,
|
|
@@ -302,29 +440,36 @@ function PickerGroupDate(props) {
|
|
|
302
440
|
selectedIndex = 0,
|
|
303
441
|
colors = {}
|
|
304
442
|
} = props;
|
|
443
|
+
const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
|
|
305
444
|
const [targetScrollTop, setTargetScrollTop] = React.useState(0);
|
|
306
445
|
const scrollViewRef = React.useRef(null);
|
|
307
446
|
const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
|
|
308
447
|
const [isTouching, setIsTouching] = React.useState(false);
|
|
448
|
+
const lengthScaleRatioRef = React.useRef(1);
|
|
449
|
+
const useMeasuredScaleRef = React.useRef(false);
|
|
309
450
|
const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
|
|
451
|
+
// 初始化时计算 lengthScaleRatio 并判定缩放模式
|
|
310
452
|
React.useEffect(() => {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
453
|
+
Taro.getSystemInfo({
|
|
454
|
+
success: res => {
|
|
455
|
+
lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
|
|
456
|
+
useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
|
|
457
|
+
itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
458
|
+
},
|
|
459
|
+
fail: () => {
|
|
460
|
+
lengthScaleRatioRef.current = 1;
|
|
461
|
+
useMeasuredScaleRef.current = false;
|
|
317
462
|
}
|
|
318
|
-
}
|
|
463
|
+
});
|
|
464
|
+
}, []);
|
|
465
|
+
React.useEffect(() => {
|
|
466
|
+
itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
319
467
|
}, [range.length]); // 只在range长度变化时重新计算
|
|
320
|
-
const getSelectedIndex = scrollTop => {
|
|
321
|
-
return Math.round(scrollTop / itemHeightRef.current);
|
|
322
|
-
};
|
|
323
468
|
// 当selectedIndex变化时,调整滚动位置
|
|
324
469
|
React.useEffect(() => {
|
|
325
470
|
if (scrollViewRef.current && range.length > 0 && !isTouching) {
|
|
326
471
|
const baseValue = selectedIndex * itemHeightRef.current;
|
|
327
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
|
|
472
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
|
|
328
473
|
setCurrentIndex(selectedIndex);
|
|
329
474
|
}
|
|
330
475
|
}, [selectedIndex, range]);
|
|
@@ -341,11 +486,11 @@ function PickerGroupDate(props) {
|
|
|
341
486
|
isCenterTimerId.current = setTimeout(() => {
|
|
342
487
|
if (!scrollViewRef.current) return;
|
|
343
488
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
344
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
489
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
345
490
|
setIsTouching(false);
|
|
346
491
|
const baseValue = newIndex * itemHeightRef.current;
|
|
347
492
|
const randomOffset = Math.random() * 0.001; // 随机数为了在一个项内滚动时强制刷新
|
|
348
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
|
|
493
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
|
|
349
494
|
// 更新日期值
|
|
350
495
|
if (updateDay) {
|
|
351
496
|
// 解析文本中的数字(移除年、月、日等后缀)
|
|
@@ -353,6 +498,7 @@ function PickerGroupDate(props) {
|
|
|
353
498
|
const numericValue = parseInt(valueText.replace(/[^0-9]/g, ''));
|
|
354
499
|
updateDay(isNaN(numericValue) ? 0 : numericValue, parseInt(columnId));
|
|
355
500
|
}
|
|
501
|
+
isCenterTimerId.current = null;
|
|
356
502
|
}, 100);
|
|
357
503
|
};
|
|
358
504
|
// 滚动处理
|
|
@@ -363,7 +509,7 @@ function PickerGroupDate(props) {
|
|
|
363
509
|
isCenterTimerId.current = null;
|
|
364
510
|
}
|
|
365
511
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
366
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
512
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
367
513
|
if (newIndex !== currentIndex) {
|
|
368
514
|
setCurrentIndex(newIndex);
|
|
369
515
|
}
|
|
@@ -401,9 +547,11 @@ function PickerGroupDate(props) {
|
|
|
401
547
|
get children() {
|
|
402
548
|
return [createComponent(View, {
|
|
403
549
|
className: "taro-picker__mask"
|
|
404
|
-
}), createComponent(View, {
|
|
550
|
+
}), createComponent(View, mergeProps({
|
|
405
551
|
className: "taro-picker__indicator"
|
|
406
|
-
}
|
|
552
|
+
}, indicatorStyle ? {
|
|
553
|
+
style: indicatorStyle
|
|
554
|
+
} : {})), createComponent(ScrollView, {
|
|
407
555
|
ref: scrollViewRef,
|
|
408
556
|
scrollY: true,
|
|
409
557
|
showScrollbar: false,
|
|
@@ -432,30 +580,37 @@ function PickerGroupRegion(props) {
|
|
|
432
580
|
// 使用selectedIndex参数,默认为0
|
|
433
581
|
colors = {}
|
|
434
582
|
} = props;
|
|
583
|
+
const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
|
|
435
584
|
const scrollViewRef = React.useRef(null);
|
|
436
585
|
const [targetScrollTop, setTargetScrollTop] = React.useState(0);
|
|
437
586
|
const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
|
|
438
587
|
const [isTouching, setIsTouching] = React.useState(false);
|
|
588
|
+
const lengthScaleRatioRef = React.useRef(1);
|
|
589
|
+
const useMeasuredScaleRef = React.useRef(false);
|
|
439
590
|
const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
|
|
440
591
|
const isUserBeginScrollRef = React.useRef(false);
|
|
592
|
+
// 初始化时计算 lengthScaleRatio 并判定缩放模式
|
|
441
593
|
React.useEffect(() => {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
594
|
+
Taro.getSystemInfo({
|
|
595
|
+
success: res => {
|
|
596
|
+
lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
|
|
597
|
+
useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
|
|
598
|
+
itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
599
|
+
},
|
|
600
|
+
fail: () => {
|
|
601
|
+
lengthScaleRatioRef.current = 1;
|
|
602
|
+
useMeasuredScaleRef.current = false;
|
|
448
603
|
}
|
|
449
|
-
}
|
|
604
|
+
});
|
|
605
|
+
}, []);
|
|
606
|
+
React.useEffect(() => {
|
|
607
|
+
itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
450
608
|
}, [range.length]); // 只在range长度变化时重新计算
|
|
451
|
-
const getSelectedIndex = scrollTop => {
|
|
452
|
-
return Math.round(scrollTop / itemHeightRef.current);
|
|
453
|
-
};
|
|
454
609
|
// 当selectedIndex变化时,调整滚动位置
|
|
455
610
|
React.useEffect(() => {
|
|
456
611
|
if (scrollViewRef.current && range.length > 0 && !isTouching) {
|
|
457
612
|
const baseValue = selectedIndex * itemHeightRef.current;
|
|
458
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
|
|
613
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
|
|
459
614
|
setCurrentIndex(selectedIndex);
|
|
460
615
|
}
|
|
461
616
|
}, [selectedIndex, range]);
|
|
@@ -471,11 +626,11 @@ function PickerGroupRegion(props) {
|
|
|
471
626
|
isCenterTimerId.current = setTimeout(() => {
|
|
472
627
|
if (!scrollViewRef.current) return;
|
|
473
628
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
474
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
629
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
475
630
|
setIsTouching(false);
|
|
476
631
|
const baseValue = newIndex * itemHeightRef.current;
|
|
477
632
|
const randomOffset = Math.random() * 0.001; // 随机数为了在一个项内滚动时强制刷新
|
|
478
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
|
|
633
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
|
|
479
634
|
updateIndex(newIndex, columnId, false, isUserBeginScrollRef.current);
|
|
480
635
|
}, 100);
|
|
481
636
|
};
|
|
@@ -487,7 +642,7 @@ function PickerGroupRegion(props) {
|
|
|
487
642
|
isCenterTimerId.current = null;
|
|
488
643
|
}
|
|
489
644
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
490
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
645
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
491
646
|
if (newIndex !== currentIndex) {
|
|
492
647
|
setCurrentIndex(newIndex);
|
|
493
648
|
}
|
|
@@ -526,9 +681,11 @@ function PickerGroupRegion(props) {
|
|
|
526
681
|
get children() {
|
|
527
682
|
return [createComponent(View, {
|
|
528
683
|
className: "taro-picker__mask"
|
|
529
|
-
}), createComponent(View, {
|
|
684
|
+
}), createComponent(View, mergeProps({
|
|
530
685
|
className: "taro-picker__indicator"
|
|
531
|
-
}
|
|
686
|
+
}, indicatorStyle ? {
|
|
687
|
+
style: indicatorStyle
|
|
688
|
+
} : {})), createComponent(ScrollView, {
|
|
532
689
|
ref: scrollViewRef,
|
|
533
690
|
scrollY: true,
|
|
534
691
|
showScrollbar: false,
|