@tarojs/components-react 4.1.9-beta.0 → 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 +246 -65
- 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 +246 -65
- 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 +247 -70
- 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,21 +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
|
-
|
|
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;
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}, []);
|
|
187
|
+
React.useEffect(() => {
|
|
188
|
+
itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
55
189
|
}, [range.length]); // 只在range长度变化时重新计算
|
|
56
|
-
// 获取选中的索引
|
|
57
|
-
const getSelectedIndex = scrollTop => {
|
|
58
|
-
return Math.round(scrollTop / itemHeightRef.current);
|
|
59
|
-
};
|
|
60
190
|
// 当selectedIndex变化时,调整滚动位置
|
|
61
191
|
React.useEffect(() => {
|
|
62
192
|
if (scrollViewRef.current && range.length > 0 && !isTouching) {
|
|
63
193
|
const baseValue = selectedIndex * itemHeightRef.current;
|
|
64
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
|
|
194
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
|
|
65
195
|
setCurrentIndex(selectedIndex);
|
|
66
196
|
}
|
|
67
197
|
}, [selectedIndex, range]);
|
|
@@ -78,16 +208,17 @@ function PickerGroupBasic(props) {
|
|
|
78
208
|
isCenterTimerId.current = setTimeout(() => {
|
|
79
209
|
if (!scrollViewRef.current) return;
|
|
80
210
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
81
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
211
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
82
212
|
setIsTouching(false);
|
|
83
213
|
const baseValue = newIndex * itemHeightRef.current;
|
|
84
214
|
const randomOffset = Math.random() * 0.001; // 随机数为了在一个项内滚动时强制刷新
|
|
85
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
|
|
215
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
|
|
86
216
|
updateIndex(newIndex, columnId);
|
|
87
217
|
onColumnChange === null || onColumnChange === void 0 ? void 0 : onColumnChange({
|
|
88
218
|
columnId,
|
|
89
219
|
index: newIndex
|
|
90
220
|
});
|
|
221
|
+
isCenterTimerId.current = null;
|
|
91
222
|
}, 100);
|
|
92
223
|
};
|
|
93
224
|
// 滚动处理 - 在滚动时计算索引然后更新选中项样式
|
|
@@ -98,7 +229,7 @@ function PickerGroupBasic(props) {
|
|
|
98
229
|
isCenterTimerId.current = null;
|
|
99
230
|
}
|
|
100
231
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
101
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
232
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
102
233
|
if (newIndex !== currentIndex) {
|
|
103
234
|
setCurrentIndex(newIndex);
|
|
104
235
|
}
|
|
@@ -138,9 +269,11 @@ function PickerGroupBasic(props) {
|
|
|
138
269
|
get children() {
|
|
139
270
|
return [createComponent(View, {
|
|
140
271
|
className: "taro-picker__mask"
|
|
141
|
-
}), createComponent(View, {
|
|
272
|
+
}), createComponent(View, mergeProps({
|
|
142
273
|
className: "taro-picker__indicator"
|
|
143
|
-
}
|
|
274
|
+
}, indicatorStyle ? {
|
|
275
|
+
style: indicatorStyle
|
|
276
|
+
} : {})), createComponent(ScrollView, {
|
|
144
277
|
ref: scrollViewRef,
|
|
145
278
|
scrollY: true,
|
|
146
279
|
showScrollbar: false,
|
|
@@ -168,25 +301,37 @@ function PickerGroupTime(props) {
|
|
|
168
301
|
selectedIndex = 0,
|
|
169
302
|
colors = {}
|
|
170
303
|
} = props;
|
|
304
|
+
const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
|
|
171
305
|
const [targetScrollTop, setTargetScrollTop] = React.useState(0);
|
|
172
306
|
const scrollViewRef = React.useRef(null);
|
|
173
307
|
const itemRefs = React.useRef([]);
|
|
174
308
|
const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
|
|
175
309
|
const [isTouching, setIsTouching] = React.useState(false);
|
|
310
|
+
const lengthScaleRatioRef = React.useRef(1);
|
|
311
|
+
const useMeasuredScaleRef = React.useRef(false);
|
|
176
312
|
const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
|
|
313
|
+
// 初始化时计算 lengthScaleRatio 并判定缩放模式
|
|
177
314
|
React.useEffect(() => {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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;
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
}, []);
|
|
327
|
+
React.useEffect(() => {
|
|
328
|
+
itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
181
329
|
}, [range.length]); // 只在range长度变化时重新计算
|
|
182
|
-
const getSelectedIndex = scrollTop => {
|
|
183
|
-
return Math.round(scrollTop / itemHeightRef.current);
|
|
184
|
-
};
|
|
185
330
|
// 当selectedIndex变化时,调整滚动位置
|
|
186
331
|
React.useEffect(() => {
|
|
187
332
|
if (scrollViewRef.current && range.length > 0 && !isTouching) {
|
|
188
333
|
const baseValue = selectedIndex * itemHeightRef.current;
|
|
189
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
|
|
334
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
|
|
190
335
|
setCurrentIndex(selectedIndex);
|
|
191
336
|
}
|
|
192
337
|
}, [selectedIndex, range]);
|
|
@@ -203,7 +348,7 @@ function PickerGroupTime(props) {
|
|
|
203
348
|
isCenterTimerId.current = setTimeout(() => {
|
|
204
349
|
if (!scrollViewRef.current) return;
|
|
205
350
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
206
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
351
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
207
352
|
setIsTouching(false);
|
|
208
353
|
// 调用updateIndex执行限位逻辑,获取是否触发了限位
|
|
209
354
|
const isLimited = Boolean(updateIndex(newIndex, columnId, true));
|
|
@@ -211,8 +356,9 @@ function PickerGroupTime(props) {
|
|
|
211
356
|
if (!isLimited) {
|
|
212
357
|
const baseValue = newIndex * itemHeightRef.current;
|
|
213
358
|
const randomOffset = Math.random() * 0.001;
|
|
214
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
|
|
359
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
|
|
215
360
|
}
|
|
361
|
+
isCenterTimerId.current = null;
|
|
216
362
|
}, 100);
|
|
217
363
|
};
|
|
218
364
|
// 滚动处理
|
|
@@ -223,7 +369,7 @@ function PickerGroupTime(props) {
|
|
|
223
369
|
isCenterTimerId.current = null;
|
|
224
370
|
}
|
|
225
371
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
226
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
372
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
227
373
|
if (newIndex !== currentIndex) {
|
|
228
374
|
setCurrentIndex(newIndex);
|
|
229
375
|
}
|
|
@@ -263,9 +409,11 @@ function PickerGroupTime(props) {
|
|
|
263
409
|
get children() {
|
|
264
410
|
return [createComponent(View, {
|
|
265
411
|
className: "taro-picker__mask"
|
|
266
|
-
}), createComponent(View, {
|
|
412
|
+
}), createComponent(View, mergeProps({
|
|
267
413
|
className: "taro-picker__indicator"
|
|
268
|
-
}
|
|
414
|
+
}, indicatorStyle ? {
|
|
415
|
+
style: indicatorStyle
|
|
416
|
+
} : {})), createComponent(ScrollView, {
|
|
269
417
|
ref: scrollViewRef,
|
|
270
418
|
scrollY: true,
|
|
271
419
|
showScrollbar: false,
|
|
@@ -292,24 +440,36 @@ function PickerGroupDate(props) {
|
|
|
292
440
|
selectedIndex = 0,
|
|
293
441
|
colors = {}
|
|
294
442
|
} = props;
|
|
443
|
+
const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
|
|
295
444
|
const [targetScrollTop, setTargetScrollTop] = React.useState(0);
|
|
296
445
|
const scrollViewRef = React.useRef(null);
|
|
297
446
|
const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
|
|
298
447
|
const [isTouching, setIsTouching] = React.useState(false);
|
|
448
|
+
const lengthScaleRatioRef = React.useRef(1);
|
|
449
|
+
const useMeasuredScaleRef = React.useRef(false);
|
|
299
450
|
const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
|
|
451
|
+
// 初始化时计算 lengthScaleRatio 并判定缩放模式
|
|
300
452
|
React.useEffect(() => {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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;
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
}, []);
|
|
465
|
+
React.useEffect(() => {
|
|
466
|
+
itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
304
467
|
}, [range.length]); // 只在range长度变化时重新计算
|
|
305
|
-
const getSelectedIndex = scrollTop => {
|
|
306
|
-
return Math.round(scrollTop / itemHeightRef.current);
|
|
307
|
-
};
|
|
308
468
|
// 当selectedIndex变化时,调整滚动位置
|
|
309
469
|
React.useEffect(() => {
|
|
310
470
|
if (scrollViewRef.current && range.length > 0 && !isTouching) {
|
|
311
471
|
const baseValue = selectedIndex * itemHeightRef.current;
|
|
312
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
|
|
472
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
|
|
313
473
|
setCurrentIndex(selectedIndex);
|
|
314
474
|
}
|
|
315
475
|
}, [selectedIndex, range]);
|
|
@@ -326,11 +486,11 @@ function PickerGroupDate(props) {
|
|
|
326
486
|
isCenterTimerId.current = setTimeout(() => {
|
|
327
487
|
if (!scrollViewRef.current) return;
|
|
328
488
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
329
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
489
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
330
490
|
setIsTouching(false);
|
|
331
491
|
const baseValue = newIndex * itemHeightRef.current;
|
|
332
492
|
const randomOffset = Math.random() * 0.001; // 随机数为了在一个项内滚动时强制刷新
|
|
333
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
|
|
493
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
|
|
334
494
|
// 更新日期值
|
|
335
495
|
if (updateDay) {
|
|
336
496
|
// 解析文本中的数字(移除年、月、日等后缀)
|
|
@@ -338,6 +498,7 @@ function PickerGroupDate(props) {
|
|
|
338
498
|
const numericValue = parseInt(valueText.replace(/[^0-9]/g, ''));
|
|
339
499
|
updateDay(isNaN(numericValue) ? 0 : numericValue, parseInt(columnId));
|
|
340
500
|
}
|
|
501
|
+
isCenterTimerId.current = null;
|
|
341
502
|
}, 100);
|
|
342
503
|
};
|
|
343
504
|
// 滚动处理
|
|
@@ -348,7 +509,7 @@ function PickerGroupDate(props) {
|
|
|
348
509
|
isCenterTimerId.current = null;
|
|
349
510
|
}
|
|
350
511
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
351
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
512
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
352
513
|
if (newIndex !== currentIndex) {
|
|
353
514
|
setCurrentIndex(newIndex);
|
|
354
515
|
}
|
|
@@ -386,9 +547,11 @@ function PickerGroupDate(props) {
|
|
|
386
547
|
get children() {
|
|
387
548
|
return [createComponent(View, {
|
|
388
549
|
className: "taro-picker__mask"
|
|
389
|
-
}), createComponent(View, {
|
|
550
|
+
}), createComponent(View, mergeProps({
|
|
390
551
|
className: "taro-picker__indicator"
|
|
391
|
-
}
|
|
552
|
+
}, indicatorStyle ? {
|
|
553
|
+
style: indicatorStyle
|
|
554
|
+
} : {})), createComponent(ScrollView, {
|
|
392
555
|
ref: scrollViewRef,
|
|
393
556
|
scrollY: true,
|
|
394
557
|
showScrollbar: false,
|
|
@@ -417,25 +580,37 @@ function PickerGroupRegion(props) {
|
|
|
417
580
|
// 使用selectedIndex参数,默认为0
|
|
418
581
|
colors = {}
|
|
419
582
|
} = props;
|
|
583
|
+
const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
|
|
420
584
|
const scrollViewRef = React.useRef(null);
|
|
421
585
|
const [targetScrollTop, setTargetScrollTop] = React.useState(0);
|
|
422
586
|
const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
|
|
423
587
|
const [isTouching, setIsTouching] = React.useState(false);
|
|
588
|
+
const lengthScaleRatioRef = React.useRef(1);
|
|
589
|
+
const useMeasuredScaleRef = React.useRef(false);
|
|
424
590
|
const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
|
|
425
591
|
const isUserBeginScrollRef = React.useRef(false);
|
|
592
|
+
// 初始化时计算 lengthScaleRatio 并判定缩放模式
|
|
426
593
|
React.useEffect(() => {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
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;
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
}, []);
|
|
606
|
+
React.useEffect(() => {
|
|
607
|
+
itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
430
608
|
}, [range.length]); // 只在range长度变化时重新计算
|
|
431
|
-
const getSelectedIndex = scrollTop => {
|
|
432
|
-
return Math.round(scrollTop / itemHeightRef.current);
|
|
433
|
-
};
|
|
434
609
|
// 当selectedIndex变化时,调整滚动位置
|
|
435
610
|
React.useEffect(() => {
|
|
436
611
|
if (scrollViewRef.current && range.length > 0 && !isTouching) {
|
|
437
612
|
const baseValue = selectedIndex * itemHeightRef.current;
|
|
438
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
|
|
613
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
|
|
439
614
|
setCurrentIndex(selectedIndex);
|
|
440
615
|
}
|
|
441
616
|
}, [selectedIndex, range]);
|
|
@@ -451,11 +626,11 @@ function PickerGroupRegion(props) {
|
|
|
451
626
|
isCenterTimerId.current = setTimeout(() => {
|
|
452
627
|
if (!scrollViewRef.current) return;
|
|
453
628
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
454
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
629
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
455
630
|
setIsTouching(false);
|
|
456
631
|
const baseValue = newIndex * itemHeightRef.current;
|
|
457
632
|
const randomOffset = Math.random() * 0.001; // 随机数为了在一个项内滚动时强制刷新
|
|
458
|
-
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
|
|
633
|
+
setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
|
|
459
634
|
updateIndex(newIndex, columnId, false, isUserBeginScrollRef.current);
|
|
460
635
|
}, 100);
|
|
461
636
|
};
|
|
@@ -467,7 +642,7 @@ function PickerGroupRegion(props) {
|
|
|
467
642
|
isCenterTimerId.current = null;
|
|
468
643
|
}
|
|
469
644
|
const scrollTop = scrollViewRef.current.scrollTop;
|
|
470
|
-
const newIndex = getSelectedIndex(scrollTop);
|
|
645
|
+
const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
|
|
471
646
|
if (newIndex !== currentIndex) {
|
|
472
647
|
setCurrentIndex(newIndex);
|
|
473
648
|
}
|
|
@@ -506,9 +681,11 @@ function PickerGroupRegion(props) {
|
|
|
506
681
|
get children() {
|
|
507
682
|
return [createComponent(View, {
|
|
508
683
|
className: "taro-picker__mask"
|
|
509
|
-
}), createComponent(View, {
|
|
684
|
+
}), createComponent(View, mergeProps({
|
|
510
685
|
className: "taro-picker__indicator"
|
|
511
|
-
}
|
|
686
|
+
}, indicatorStyle ? {
|
|
687
|
+
style: indicatorStyle
|
|
688
|
+
} : {})), createComponent(ScrollView, {
|
|
512
689
|
ref: scrollViewRef,
|
|
513
690
|
scrollY: true,
|
|
514
691
|
showScrollbar: false,
|