@tuya-miniapp/smart-ui 2.6.4-beta-8 → 2.6.4-beta-10
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/common/utils.d.ts +0 -1
- package/dist/common/utils.js +0 -7
- package/dist/datetime-picker/index.js +2 -2
- package/dist/image/index.js +1 -1
- package/dist/picker/index.css +1 -1
- package/dist/picker/index.js +11 -4
- package/dist/picker/index.wxml +4 -3
- package/dist/picker/index.wxs +1 -1
- package/dist/picker/index.wxss +1 -1
- package/dist/picker/shared.d.ts +11 -0
- package/dist/picker/shared.js +11 -0
- package/dist/picker-column/index.css +1 -1
- package/dist/picker-column/index.js +192 -77
- package/dist/picker-column/index.wxml +15 -36
- package/dist/picker-column/index.wxs +510 -399
- package/dist/picker-column/index.wxss +1 -1
- package/dist/wxs/utils.wxs +42 -1
- package/lib/common/utils.d.ts +0 -1
- package/lib/common/utils.js +1 -9
- package/lib/datetime-picker/index.js +3 -3
- package/lib/image/index.js +1 -1
- package/lib/picker/index.css +1 -1
- package/lib/picker/index.js +13 -4
- package/lib/picker/index.wxml +4 -3
- package/lib/picker/index.wxs +1 -1
- package/lib/picker/index.wxss +1 -1
- package/lib/picker/shared.d.ts +11 -0
- package/lib/picker/shared.js +11 -0
- package/lib/picker-column/index.css +1 -1
- package/lib/picker-column/index.js +192 -83
- package/lib/picker-column/index.wxml +15 -36
- package/lib/picker-column/index.wxs +510 -399
- package/lib/picker-column/index.wxss +1 -1
- package/lib/wxs/utils.wxs +42 -1
- package/package.json +1 -1
- package/dist/wxs/strToStyleObject.wxs +0 -10
- package/lib/wxs/strToStyleObject.wxs +0 -10
|
@@ -3,148 +3,210 @@ var style = require('../wxs/style.wxs');
|
|
|
3
3
|
var addUnit = require('../wxs/add-unit.wxs');
|
|
4
4
|
var wxUtils = require('../wxs/utils.wxs');
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const setStyle = (ownerInstance, style, selector) => {
|
|
9
|
-
const dom = queryComponent(ownerInstance, selector);
|
|
6
|
+
function setStyle(ownerInstance, style, selector) {
|
|
7
|
+
var dom = wxUtils.queryComponent(ownerInstance, selector);
|
|
10
8
|
if (!dom) {
|
|
11
9
|
console.log(selector, '--selector 无法获取');
|
|
12
10
|
return
|
|
13
11
|
}
|
|
14
12
|
dom.setStyle(style);
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
function range(num, min, max) {
|
|
18
|
-
return Math.min(Math.max(num, min), max);
|
|
19
13
|
}
|
|
20
14
|
|
|
21
|
-
function
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
for (let i = index; i < count; i++) {
|
|
25
|
-
if (!isDisabled(options[i])) return i;
|
|
26
|
-
}
|
|
27
|
-
for (let i = index - 1; i >= 0; i--) {
|
|
28
|
-
if (!isDisabled(options[i])) return i;
|
|
29
|
-
}
|
|
15
|
+
function optionText(options, optionIndex, valueKey) {
|
|
16
|
+
var option = options[optionIndex];
|
|
17
|
+
return wxUtils.isObj(option) && option[valueKey] != null ? option[valueKey] : option;
|
|
30
18
|
}
|
|
31
19
|
|
|
32
|
-
function
|
|
33
|
-
return
|
|
20
|
+
function rootStyle(data) {
|
|
21
|
+
return style({
|
|
22
|
+
height: addUnit(data.itemHeight * data.visibleItemCount),
|
|
23
|
+
});
|
|
34
24
|
}
|
|
35
25
|
|
|
36
|
-
|
|
37
|
-
const resultArray = [];
|
|
38
|
-
for (let i = start; i < end; i++) {
|
|
39
|
-
resultArray.push(i);
|
|
40
|
-
}
|
|
41
|
-
return resultArray;
|
|
42
|
-
}
|
|
26
|
+
var state = {}
|
|
43
27
|
|
|
44
|
-
|
|
45
|
-
const instance = ownerInstance?.selectComponent(selector);
|
|
46
|
-
return instance;
|
|
47
|
-
};
|
|
28
|
+
var preStateObj = {}
|
|
48
29
|
|
|
49
|
-
function
|
|
50
|
-
|
|
30
|
+
function updateState(instanceId, key, value) {
|
|
31
|
+
if (!key) return;
|
|
32
|
+
state[instanceId] = state[instanceId] || {}
|
|
33
|
+
state[instanceId][key] = value
|
|
51
34
|
}
|
|
52
35
|
|
|
53
|
-
function
|
|
54
|
-
|
|
55
|
-
|
|
36
|
+
function clearCurrState(instanceId) {
|
|
37
|
+
delete state[instanceId]
|
|
38
|
+
delete preStateObj[instanceId]
|
|
39
|
+
delete Cache[instanceId]
|
|
56
40
|
}
|
|
57
41
|
|
|
58
|
-
function
|
|
59
|
-
return
|
|
42
|
+
function getCurrState(instanceId) {
|
|
43
|
+
return state[instanceId]
|
|
60
44
|
}
|
|
61
45
|
|
|
62
|
-
function
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
46
|
+
function updatePreState(instanceId, state) {
|
|
47
|
+
var preStateStr = JSON.stringify(state)
|
|
48
|
+
preStateObj[instanceId] = preStateStr;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function getPreState(instanceId) {
|
|
52
|
+
return preStateObj[instanceId]
|
|
66
53
|
}
|
|
67
54
|
|
|
68
55
|
function wrapperStyle(data) {
|
|
69
|
-
var
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
56
|
+
var perAngle = 360 / (data.visibleItemCount * 4 - 2)
|
|
57
|
+
var rotate = perAngle * data.animationIndex;
|
|
58
|
+
var optionsVIndexList = data.optionsVIndexList;
|
|
59
|
+
var cssVar = optionsVIndexList.reduce(function(previousValue, currentValue, currentIndex) {
|
|
60
|
+
if (currentValue === '' || currentValue === undefined) return previousValue;
|
|
61
|
+
var index = data.loop ? Math.abs(currentValue % data.options.length) : currentValue;
|
|
62
|
+
var text = optionText(data.options, index, data.valueKey);
|
|
63
|
+
if(text === undefined) return previousValue;
|
|
64
|
+
previousValue['--picker-item-content_' + currentIndex] = '"' + text + '"';
|
|
65
|
+
return previousValue;
|
|
66
|
+
}, {});
|
|
67
|
+
|
|
68
|
+
var styleObj = {
|
|
80
69
|
'text-indent': data.unit ? '-8rpx' : '0',
|
|
70
|
+
transition: !data.changeAnimation ? 'none' : 'transform ' + data.animationTime + 'ms cubic-bezier(0.2, 0.9, 0.25, 1)',
|
|
81
71
|
'line-height': addUnit(data.itemHeight),
|
|
82
|
-
|
|
72
|
+
transform: 'rotateX(' + rotate + 'deg)'
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
return style(Object.assign(styleObj, cssVar));
|
|
83
76
|
}
|
|
84
77
|
|
|
85
|
-
function wrapperItemStyle(data) {
|
|
86
|
-
var heightStyleStr = "height: " + data.itemHeight + 'px;'
|
|
87
|
-
var maxSideShow = data.visibleItemCount + 2;
|
|
88
|
-
var offsetIndex = data.animationIndex - data.index;
|
|
89
|
-
if (Math.abs(offsetIndex) > maxSideShow) heightStyleStr
|
|
90
|
-
const finOffsetIndex = offsetIndex > 0 ? Math.min(offsetIndex, maxSideShow) : Math.max(offsetIndex, -maxSideShow);
|
|
91
|
-
var scale = 1 - Math.abs(finOffsetIndex * 0.15);
|
|
92
|
-
var rotateX = rotateX = Math.abs(finOffsetIndex * 10);
|
|
93
|
-
var direction = offsetIndex > 0 ? 1 : -1;
|
|
94
|
-
var translateYIndex = Math.abs(finOffsetIndex);
|
|
95
|
-
var translateYOffset = translateYIndex * translateYIndex * direction * state.itemHeight * 0.1
|
|
96
|
-
const transStyle = style({
|
|
97
|
-
transform: `rotateX(${rotateX}deg) scale(${scale}) translateY(${translateYOffset}px) translateZ(0)`,
|
|
98
|
-
});
|
|
99
|
-
return transStyle + ';' + heightStyleStr
|
|
100
|
-
}
|
|
101
78
|
|
|
102
|
-
function
|
|
103
|
-
var
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
79
|
+
function adjustIndex(index, options, loop) {
|
|
80
|
+
var count = options.length;
|
|
81
|
+
if (loop) {
|
|
82
|
+
for (var i = 0; i < count; i++) {
|
|
83
|
+
var targetIndex = index + i;
|
|
84
|
+
var optionIndex = Math.abs(((targetIndex + 1) % count) - 1);
|
|
85
|
+
if (
|
|
86
|
+
!isDisabled(options[optionIndex]) &&
|
|
87
|
+
options[optionIndex] !== undefined
|
|
88
|
+
) {
|
|
89
|
+
return targetIndex;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return 0;
|
|
93
|
+
}
|
|
94
|
+
var activeIndex = wxUtils.range(index, 0, count);
|
|
95
|
+
for (var i = activeIndex; i < count; i++) {
|
|
96
|
+
if (!isDisabled(options[i]) && options[i] !== undefined) return i;
|
|
97
|
+
}
|
|
98
|
+
for (var i = activeIndex - 1; i >= 0; i--) {
|
|
99
|
+
if (!isDisabled(options[i]) && options[i] !== undefined) return i;
|
|
100
|
+
}
|
|
107
101
|
}
|
|
108
102
|
|
|
109
|
-
function
|
|
110
|
-
|
|
111
|
-
var activeClass = 'active-class';
|
|
112
|
-
var isActive = Math.abs(data.index - data.animationIndex) < 0.5;
|
|
113
|
-
const currOption = data.options[data.index];
|
|
114
|
-
return staticClass + ' ' + wxUtils.bem('picker-column__item', { disabled: currOption && currOption.disabled, selected: isActive }) + ' ' + (isActive ? activeClass : '');
|
|
103
|
+
function isDisabled(option) {
|
|
104
|
+
return typeof option === 'object' && option.disabled;
|
|
115
105
|
}
|
|
116
106
|
|
|
117
|
-
|
|
107
|
+
/**
|
|
108
|
+
* 计算有数据的列表的中心索引值(首位相连的环形数组)
|
|
109
|
+
* @param {Array} arr - 输入数组
|
|
110
|
+
* @returns {number} 中心索引值
|
|
111
|
+
*/
|
|
112
|
+
function calculateCenterIndex(arr) {
|
|
118
113
|
|
|
119
|
-
var
|
|
114
|
+
var noDataStartIndex = -1;
|
|
115
|
+
var noDataEndIndex = -1;
|
|
116
|
+
|
|
117
|
+
var newNoDataStartIndex = -1;
|
|
118
|
+
|
|
119
|
+
arr.forEach(function(item, index) {
|
|
120
|
+
if (item === '' && noDataStartIndex === -1) {
|
|
121
|
+
noDataStartIndex = index;
|
|
122
|
+
}
|
|
123
|
+
if (item !== '' && noDataEndIndex === -1 && noDataStartIndex !== -1) {
|
|
124
|
+
noDataEndIndex = index - 1;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if(item === '' && newNoDataStartIndex === -1 && noDataStartIndex !== -1 && noDataEndIndex !== -1) {
|
|
128
|
+
newNoDataStartIndex = index;
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
if (noDataStartIndex === 0 && noDataEndIndex === arr.length - 1) {
|
|
133
|
+
return (noDataEndIndex + arr.length) / 2
|
|
134
|
+
} else if(noDataStartIndex === 0 || noDataEndIndex === 0) {
|
|
135
|
+
return (newNoDataStartIndex - noDataEndIndex) / 2 + noDataEndIndex
|
|
136
|
+
} else {
|
|
137
|
+
var startCount = noDataStartIndex;
|
|
138
|
+
var endCount = arr.length - 1 - noDataEndIndex;
|
|
139
|
+
var mid = Math.abs(startCount - endCount);
|
|
140
|
+
return startCount > endCount ? noDataStartIndex - Math.floor(mid/2) -1 - endCount : noDataEndIndex + Math.floor(mid/2) + startCount + 1;
|
|
141
|
+
}
|
|
120
142
|
|
|
121
|
-
function updateState(instanceId, key, value) {
|
|
122
|
-
if (!key) return;
|
|
123
|
-
state[instanceId] = state[instanceId] || {}
|
|
124
|
-
state[instanceId][key] = value
|
|
125
143
|
}
|
|
126
144
|
|
|
127
|
-
|
|
128
|
-
|
|
145
|
+
|
|
146
|
+
function wrapperItemStyle(data) {
|
|
147
|
+
var heightStyleStr = "height: " + data.itemHeight + 'px;'
|
|
148
|
+
var perAngle = 360 / (data.visibleItemCount * 4 - 2)
|
|
149
|
+
var transformStyleStr = style({
|
|
150
|
+
transform: 'rotateX(' + (360 - data.index * perAngle) + 'deg) translateZ(' + (data.itemHeight * data.visibleItemCount / 2) + 'px) translateX(-50%) scale(0.88);', // scale(0.88)
|
|
151
|
+
top: 'calc(50% - ' + (data.itemHeight / 2) + 'px)',
|
|
152
|
+
});
|
|
153
|
+
var textStyle = wrapperItemTextStyle(data);
|
|
154
|
+
return transformStyleStr.replace(';;', ';') + ';' + heightStyleStr + textStyle;
|
|
129
155
|
}
|
|
130
156
|
|
|
131
|
-
function
|
|
132
|
-
|
|
133
|
-
|
|
157
|
+
function wrapperItemClass(data) {
|
|
158
|
+
var optionsVIndexList = getVisibleOptions(data.animationIndex, data.instanceId) || data.optionsVIndexList;
|
|
159
|
+
var animationIndex = data.animationIndex;
|
|
160
|
+
var intAnimationIndex = Math.round(animationIndex);
|
|
161
|
+
var activeIndex = (intAnimationIndex + 1) % data.options.length - 1;
|
|
162
|
+
if(activeIndex < 0) {
|
|
163
|
+
activeIndex += data.options.length;
|
|
164
|
+
}
|
|
165
|
+
var optionIndex = optionsVIndexList[data.index];
|
|
166
|
+
var option = data.options[optionIndex];
|
|
167
|
+
var isActive = typeof optionIndex === 'number' && activeIndex === optionIndex;
|
|
168
|
+
var activeClass = 'active-class';
|
|
169
|
+
return wxUtils.bem('picker-column__item', { disabled: wxUtils.isObj(option) && option.disabled, selected: isActive }) + ' ' + (isActive ? activeClass : '');
|
|
134
170
|
}
|
|
135
171
|
|
|
136
|
-
function
|
|
137
|
-
|
|
172
|
+
function wrapperItemTextStyle(data) {
|
|
173
|
+
var optionsVIndexList = getVisibleOptions(data.animationIndex, data.instanceId) || data.optionsVIndexList;
|
|
174
|
+
var animationIndex = data.animationIndex;
|
|
175
|
+
var intAnimationIndex = Math.round(animationIndex);
|
|
176
|
+
var activeIndex = (intAnimationIndex + 1) % data.options.length - 1;
|
|
177
|
+
if(activeIndex < 0) {
|
|
178
|
+
activeIndex += data.options.length;
|
|
179
|
+
}
|
|
180
|
+
var optionIndex = optionsVIndexList[data.index];
|
|
181
|
+
var fontStyle = data.fontStyle;
|
|
182
|
+
var activeStyle = data.activeStyle;
|
|
183
|
+
var isActive = typeof optionIndex === 'number' && activeIndex === optionIndex;
|
|
184
|
+
return (fontStyle ? fontStyle.replace(';', '') + ';' : '') + (isActive ? activeStyle.replace(';;', ';') + ';' : '')
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function getNewAnimationIndex(animationIndex, activeIndex, length, loop) {
|
|
188
|
+
var curOptionsNewIndex = Math.floor((animationIndex + 1) / length) * length + activeIndex;
|
|
189
|
+
var preOptionsNewIndex = curOptionsNewIndex - length;
|
|
190
|
+
var afterOptionsNewIndex = curOptionsNewIndex + length;
|
|
191
|
+
var newAnimationIndex = !loop ?
|
|
192
|
+
activeIndex :
|
|
193
|
+
Math.abs(preOptionsNewIndex - animationIndex) > Math.abs(curOptionsNewIndex - animationIndex)
|
|
194
|
+
? Math.abs(curOptionsNewIndex - animationIndex) > Math.abs(afterOptionsNewIndex - animationIndex)
|
|
195
|
+
? afterOptionsNewIndex : curOptionsNewIndex
|
|
196
|
+
: Math.abs(preOptionsNewIndex - animationIndex) > Math.abs(afterOptionsNewIndex - animationIndex)
|
|
197
|
+
? afterOptionsNewIndex
|
|
198
|
+
: preOptionsNewIndex;
|
|
199
|
+
return newAnimationIndex;
|
|
138
200
|
}
|
|
139
201
|
|
|
140
202
|
function getDomState(ownerInstance) {
|
|
141
|
-
|
|
142
|
-
|
|
203
|
+
var dom = wxUtils.queryComponent(ownerInstance, '.smart-picker-column');
|
|
204
|
+
var state = dom.getDataset();
|
|
143
205
|
return state
|
|
144
206
|
}
|
|
145
207
|
|
|
146
208
|
function initDomState(instanceId, ownerInstance) {
|
|
147
|
-
|
|
209
|
+
var state = getDomState(ownerInstance);
|
|
148
210
|
updateState(instanceId, 'options', state.options)
|
|
149
211
|
updateState(instanceId, 'valueKey', state.valuekey)
|
|
150
212
|
updateState(instanceId, 'itemHeight', state.itemheight)
|
|
@@ -152,344 +214,395 @@ function initDomState(instanceId, ownerInstance) {
|
|
|
152
214
|
updateState(instanceId, 'activeIndex', state.activeindex)
|
|
153
215
|
updateState(instanceId, 'loop', state.loop)
|
|
154
216
|
updateState(instanceId, 'animationTime', state.animationtime)
|
|
217
|
+
updateState(instanceId, 'changeAnimation', state.changeanimation)
|
|
155
218
|
}
|
|
156
219
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
220
|
+
|
|
221
|
+
function updateValue(instanceId, key) {
|
|
222
|
+
return function(newOptions, oldOptions, ownerInstance) {
|
|
223
|
+
if (!instanceId) return;
|
|
224
|
+
updateState(instanceId, key, newOptions)
|
|
225
|
+
initDomState(instanceId, ownerInstance)
|
|
226
|
+
updateListView(instanceId, ownerInstance)
|
|
227
|
+
}
|
|
162
228
|
}
|
|
163
229
|
|
|
164
|
-
function
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if
|
|
230
|
+
function updateListView(instanceId, ownerInstance) {
|
|
231
|
+
var state = getCurrState(instanceId);
|
|
232
|
+
var domState = getDomState(ownerInstance);
|
|
233
|
+
if (domState.isdestroy) {
|
|
234
|
+
clearCurrState(instanceId)
|
|
235
|
+
return
|
|
236
|
+
}
|
|
237
|
+
if(getPreState(instanceId) === JSON.stringify(domState) || !state.itemHeight || !state.visibleItemCount || !wxUtils.isArray(state.options) || state.animationTime === undefined) {
|
|
168
238
|
return
|
|
169
239
|
}
|
|
170
240
|
updatePreState(instanceId, domState)
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
})
|
|
181
|
-
const offset = state.itemHeight * (sideCount - currActiveIndex);
|
|
182
|
-
updateState(instanceId, 'offset', offset)
|
|
183
|
-
updateState(instanceId,'offsetActiveIndex', currActiveIndex);
|
|
184
|
-
setStyle(ownerInstance, {
|
|
185
|
-
transform: 'translateY(' + addUnit(offset) + ')',
|
|
186
|
-
...textVarStyle,
|
|
187
|
-
}, '.smart-picker-column__offset');
|
|
188
|
-
|
|
189
|
-
setTimeout(() => {
|
|
190
|
-
updateItemStyle(instanceId, ownerInstance);
|
|
191
|
-
}, 10)
|
|
192
|
-
}
|
|
193
|
-
/** 更新聚焦点位样式 */
|
|
194
|
-
const updateItemStyle = (instanceId, ownerInstance, time) => {
|
|
195
|
-
const state = getCurrState(instanceId);
|
|
196
|
-
const currActiveIndex = state.offsetActiveIndex;
|
|
197
|
-
state.viewIndexList.slice(0, 20).map((item, index) => {
|
|
198
|
-
const viewOptionsActiveIndex = item;
|
|
199
|
-
const maxSideShow = state.sideCount + 2;
|
|
200
|
-
const offsetIndex = currActiveIndex - viewOptionsActiveIndex;
|
|
201
|
-
if(Math.abs(offsetIndex) > maxSideShow) return;
|
|
202
|
-
const finOffsetIndex = offsetIndex > 0 ? Math.min(offsetIndex, maxSideShow) : Math.max(offsetIndex, -maxSideShow);
|
|
203
|
-
const scale = 1 - Math.abs(finOffsetIndex * 0.15);
|
|
204
|
-
const rotateX = Math.abs(finOffsetIndex * 10);
|
|
205
|
-
const direction = offsetIndex > 0 ? 1 : -1;
|
|
206
|
-
const translateYIndex = Math.abs(finOffsetIndex);
|
|
207
|
-
const translateYOffset = translateYIndex * translateYIndex * direction * state.itemHeight * 0.1
|
|
208
|
-
const className = `.smart-picker-column__item_${index}`;
|
|
209
|
-
setStyle(ownerInstance, {
|
|
210
|
-
transform: `rotateX(${rotateX}deg) scale(${scale}) translateY(${translateYOffset}px) translateZ(0)`,
|
|
211
|
-
transition: !time ? 'none' : 'transform ' + time + 'ms',
|
|
212
|
-
}, className);
|
|
213
|
-
})
|
|
241
|
+
var activeIndex = state.activeIndex;
|
|
242
|
+
var length = state.options.length || 1;
|
|
243
|
+
var animationIndex = state.animationIndex || 0;
|
|
244
|
+
var newAnimationIndex = getNewAnimationIndex(animationIndex, activeIndex, length, state.loop);
|
|
245
|
+
var isSame = newAnimationIndex === animationIndex;
|
|
246
|
+
updateState(instanceId, 'animationIndex', newAnimationIndex)
|
|
247
|
+
updateVisibleOptions(state.animationIndex, instanceId);
|
|
248
|
+
updateWrapperStyle(instanceId, ownerInstance, {
|
|
249
|
+
transition: (!state.changeAnimation || isSame) ? 'none' : 'transform ' + state.animationTime + 'ms cubic-bezier(0.2, 0.9, 0.25, 1)'
|
|
250
|
+
});
|
|
214
251
|
}
|
|
215
252
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
253
|
+
function touchStart(instanceId) {
|
|
254
|
+
return function(event) {
|
|
255
|
+
var state = getCurrState(instanceId);
|
|
256
|
+
if (state.endTimer) {
|
|
257
|
+
cancelAnimationFrame(state.endTimer);
|
|
258
|
+
clearTimeout(state.endTimer);
|
|
259
|
+
updateState(instanceId, 'endTimer', null);
|
|
260
|
+
} else {
|
|
261
|
+
updateState(instanceId, 'recentVelocity', 0);
|
|
262
|
+
}
|
|
263
|
+
if(state.tapTimer) {
|
|
264
|
+
clearTimeout(state.tapTimer);
|
|
265
|
+
updateState(instanceId, 'tapTimer', null);
|
|
266
|
+
}
|
|
267
|
+
var pageY = event.touches[0].pageY;
|
|
268
|
+
updateState(instanceId, 'startY', pageY);
|
|
269
|
+
updateState(instanceId, 'moving', false);
|
|
270
|
+
updateState(instanceId, 'startOffset', state.animationIndex * state.itemHeight);
|
|
271
|
+
updateState(instanceId, 'preOffsetting', state.animationIndex * state.itemHeight);
|
|
272
|
+
updateState(instanceId, 'preOffsetList', []);
|
|
222
273
|
}
|
|
223
|
-
const part2Times = Math.floor(partNum / 2);
|
|
224
|
-
const part2Percent = partNum % 2;
|
|
225
|
-
const onePartOffset = part2Percent + part2Times;
|
|
226
|
-
const twoPartOffset = part2Times;
|
|
227
|
-
return { onePartOffset , twoPartOffset }
|
|
228
274
|
}
|
|
229
275
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
276
|
+
function touchMove(instanceId) {
|
|
277
|
+
return function(event, ownerInstance) {
|
|
278
|
+
var state = getCurrState(instanceId);
|
|
279
|
+
var pageY = event.touches[0].pageY;
|
|
280
|
+
var offsetY = pageY - state.startY;
|
|
281
|
+
var offsetting = -state.startOffset + offsetY;
|
|
282
|
+
var newOffsetList = state.preOffsetList.slice();
|
|
283
|
+
newOffsetList.push(offsetting);
|
|
284
|
+
var animationIndex = -offsetting / state.itemHeight;
|
|
285
|
+
var intPreIndex = Math.round(state.animationIndex);
|
|
286
|
+
var intCurIndex = Math.round(animationIndex);
|
|
287
|
+
var offsetCompare = offsetting - state.preOffsetting;
|
|
288
|
+
var direction =
|
|
289
|
+
offsetCompare < 0 ? 'down' : offsetCompare > 0 ? 'up' : state.movingDirection;
|
|
290
|
+
updateVisibleOptions(animationIndex, instanceId);
|
|
291
|
+
var isOverOptions = state.loop ? false : animationIndex < 0 || animationIndex > state.options.length - 1;
|
|
292
|
+
var activeIndex = Math.round(animationIndex);
|
|
293
|
+
var isDisabled = wxUtils.isObj(state.options[activeIndex]) && state.options[activeIndex].disabled;
|
|
294
|
+
if (
|
|
295
|
+
intPreIndex !== intCurIndex
|
|
296
|
+
&& !isOverOptions
|
|
297
|
+
&& !isDisabled
|
|
298
|
+
) {
|
|
299
|
+
ownerInstance.callMethod('animationIndexChange', animationIndex);
|
|
300
|
+
ownerInstance.callMethod('vibrateShort');
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (!state.moving) {
|
|
304
|
+
ownerInstance.callMethod('animationStart');
|
|
305
|
+
}
|
|
306
|
+
updateState(instanceId, 'moving', true);
|
|
307
|
+
updateState(instanceId, 'animationIndex', animationIndex);
|
|
308
|
+
updateState(instanceId, 'preOffsetting', offsetting);
|
|
309
|
+
updateState(instanceId, 'preOffsetList', newOffsetList);
|
|
310
|
+
updateState(instanceId, 'movingDirection', direction);
|
|
311
|
+
|
|
312
|
+
updateWrapperStyle(instanceId, ownerInstance);
|
|
245
313
|
}
|
|
246
|
-
return [...firstList, ...scendList];
|
|
247
314
|
}
|
|
248
315
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
316
|
+
function touchEnd(instanceId) {
|
|
317
|
+
return function(event, ownerInstance) {
|
|
318
|
+
var state = getCurrState(instanceId);
|
|
319
|
+
if (!state.moving) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
var preOffsetList = state.preOffsetList;
|
|
323
|
+
// 计算最后几帧的平均速度,用于惯性滚动
|
|
324
|
+
var recentVelocity = 0;
|
|
325
|
+
/** -1: 向下, 1: 向上, 0: 无滚动 */
|
|
326
|
+
var scrollDirection = 0;
|
|
327
|
+
|
|
328
|
+
if (preOffsetList.length >= 2) {
|
|
329
|
+
// 计算速度,优先使用最后几帧的数据
|
|
330
|
+
var recentOffset = 0;
|
|
331
|
+
var recentTime = 0;
|
|
332
|
+
|
|
333
|
+
if (preOffsetList.length >= 3) {
|
|
334
|
+
// 有3个或以上数据点,使用最后3个点计算速度
|
|
335
|
+
recentOffset =
|
|
336
|
+
preOffsetList[preOffsetList.length - 1] - preOffsetList[preOffsetList.length - 3];
|
|
337
|
+
recentTime = 2; // 2帧间隔
|
|
338
|
+
} else if (preOffsetList.length === 2) {
|
|
339
|
+
// 只有2个数据点,使用这2个点计算速度
|
|
340
|
+
recentOffset = preOffsetList[1] - preOffsetList[0];
|
|
341
|
+
recentTime = 1; // 1帧间隔
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// 计算速度 (px/ms)
|
|
345
|
+
recentVelocity = state.recentVelocity + Math.abs(recentOffset) / (recentTime * 16);
|
|
346
|
+
updateState(instanceId, 'recentVelocity', recentVelocity);
|
|
347
|
+
// 确定滚动方向
|
|
348
|
+
if (recentOffset > 0) {
|
|
349
|
+
scrollDirection = 1; // 向上滚动
|
|
350
|
+
} else if (recentOffset < 0) {
|
|
351
|
+
scrollDirection = -1; // 向下滚动
|
|
352
|
+
}
|
|
353
|
+
}
|
|
259
354
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
355
|
+
// 惯性滚动参数配置
|
|
356
|
+
var minVelocity = 0.1; // 最小速度阈值,低于此值停止滚动
|
|
357
|
+
var maxInertiaDistance = state.itemHeight * Math.max(Math.floor(state.options.length/4), 6); // 最大惯性滚动距离
|
|
358
|
+
// 计算惯性滚动距离
|
|
359
|
+
var inertiaDistance = 0;
|
|
360
|
+
if (recentVelocity > minVelocity) {
|
|
361
|
+
// 使用物理公式计算惯性距离:distance = velocity^2 / (2 * friction)
|
|
362
|
+
// 这里简化处理,直接使用速度乘以一个系数
|
|
363
|
+
inertiaDistance = recentVelocity * 150; // 200ms的惯性时间
|
|
364
|
+
|
|
365
|
+
// 限制最大滚动距离
|
|
366
|
+
if (inertiaDistance > maxInertiaDistance) {
|
|
367
|
+
inertiaDistance = maxInertiaDistance;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// 根据滚动方向确定正负值
|
|
371
|
+
inertiaDistance *= scrollDirection;
|
|
372
|
+
}
|
|
265
373
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
374
|
+
// 计算最终目标位置 和 index
|
|
375
|
+
var targetOffset =
|
|
376
|
+
Math.round((state.preOffsetting + inertiaDistance) / state.itemHeight) *
|
|
377
|
+
state.itemHeight;
|
|
378
|
+
var currTargetActiveIndex = -targetOffset / state.itemHeight;
|
|
379
|
+
currTargetActiveIndex = adjustIndex(Math.round(currTargetActiveIndex), state.options, state.loop);
|
|
380
|
+
targetOffset = -currTargetActiveIndex * state.itemHeight;
|
|
381
|
+
var animationOffset = Math.abs(targetOffset - state.preOffsetting);
|
|
382
|
+
var isOverOptions = state.loop ? false : state.animationIndex < 0 || state.animationIndex > state.options.length - 1;
|
|
383
|
+
var totalDistance = targetOffset - state.preOffsetting;
|
|
384
|
+
// 如果动画时间大于150ms,并且滚动距离大于itemHeight,则需要进行动态更新列表
|
|
385
|
+
if (state.animationTime > 200 && animationOffset > state.itemHeight && !isOverOptions) {
|
|
386
|
+
var countOffsetIndex = Math.abs(Math.round(currTargetActiveIndex - state.animationIndex));
|
|
387
|
+
var maxVibrateShort = Math.floor(state.animationTime / 30);
|
|
388
|
+
|
|
389
|
+
// 基于时间的减速动画参数
|
|
390
|
+
var startOffset = state.preOffsetting;
|
|
391
|
+
var startTime = Date.now();
|
|
392
|
+
|
|
393
|
+
// 使用 requestAnimationFrame 实现动画
|
|
394
|
+
var animate = function() {
|
|
395
|
+
var elapsedTime = Date.now() - startTime;
|
|
396
|
+
var progress = Math.min(elapsedTime / state.animationTime, 1); // 进度 0-1
|
|
397
|
+
|
|
398
|
+
// 使用缓动函数实现减速效果:easeOutCubic
|
|
399
|
+
// f(t) = 1 - (1-t)^3,开始快,结束慢
|
|
400
|
+
var easedProgress = 1 - Math.pow(1 - progress, 3);
|
|
401
|
+
|
|
402
|
+
// 计算当前偏移量
|
|
403
|
+
var currentOffset = startOffset + totalDistance * easedProgress;
|
|
404
|
+
|
|
405
|
+
if (progress >= 1) {
|
|
406
|
+
// 动画完成,设置为精确的目标位置
|
|
407
|
+
updateVisibleOptions(currTargetActiveIndex, instanceId);
|
|
408
|
+
updateWrapperStyle(instanceId, ownerInstance);
|
|
409
|
+
updateState(instanceId, 'endTimer', null);
|
|
410
|
+
updateState(instanceId, 'moving', false);
|
|
411
|
+
updateState(instanceId, 'animationIndex', currTargetActiveIndex);
|
|
412
|
+
ownerInstance.callMethod('activeIndexChange', currTargetActiveIndex, true);
|
|
413
|
+
setTimeout(function() {
|
|
414
|
+
ownerInstance.callMethod('animationEnd');
|
|
415
|
+
}, 0);
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
var currIndex = -currentOffset / state.itemHeight;
|
|
420
|
+
updateVisibleOptions(currIndex, instanceId);
|
|
421
|
+
updateState(instanceId, 'animationIndex', currIndex);
|
|
422
|
+
ownerInstance.callMethod('animationIndexChange', currIndex);
|
|
423
|
+
updateWrapperStyle(instanceId, ownerInstance);
|
|
424
|
+
|
|
425
|
+
// 继续下一帧动画
|
|
426
|
+
var animationId = requestAnimationFrame(animate);
|
|
427
|
+
updateState(instanceId, 'endTimer', animationId);
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
// 启动动画
|
|
431
|
+
var animationId = requestAnimationFrame(animate);
|
|
432
|
+
ownerInstance.callMethod('vibrateShort', Math.min(countOffsetIndex, maxVibrateShort), state.animationTime);
|
|
433
|
+
updateState(instanceId, 'endTimer', animationId);
|
|
434
|
+
} else {
|
|
435
|
+
updateVisibleOptions(currTargetActiveIndex, instanceId);
|
|
436
|
+
updateState(instanceId, 'animationIndex', currTargetActiveIndex);
|
|
437
|
+
updateWrapperStyle(instanceId, ownerInstance, {
|
|
438
|
+
transition: 'transform ' + 200 + 'ms cubic-bezier(0.2, 0.9, 0.25, 1)'
|
|
439
|
+
});
|
|
440
|
+
setTimeout(function() {
|
|
441
|
+
updateState(instanceId, 'moving', false);
|
|
442
|
+
ownerInstance.callMethod('animationEnd');
|
|
443
|
+
ownerInstance.callMethod('activeIndexChange', currTargetActiveIndex, true);
|
|
444
|
+
}, 150);
|
|
445
|
+
}
|
|
275
446
|
}
|
|
276
|
-
const currList = getCurrList(instanceId, state.options, state.offsetActiveIndex, ownerInstance)
|
|
277
|
-
updateRenderPartOffset(instanceId, ownerInstance);
|
|
278
|
-
const textVarStyle = getCSSVarText(instanceId, currList)
|
|
279
|
-
setStyle(ownerInstance, {
|
|
280
|
-
...style,
|
|
281
|
-
...textVarStyle,
|
|
282
|
-
}, '.smart-picker-column__offset');
|
|
283
|
-
updateItemStyle(instanceId, ownerInstance, time);
|
|
284
447
|
}
|
|
285
448
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
449
|
+
var Cache = {}
|
|
450
|
+
|
|
451
|
+
function getVisibleOptions(currentIndex, instanceId) {
|
|
452
|
+
var state = getCurrState(instanceId);
|
|
453
|
+
if(!state) return
|
|
454
|
+
var animationIndex = Math.round(
|
|
455
|
+
currentIndex !== undefined ? currentIndex : state.animationIndex
|
|
456
|
+
);
|
|
457
|
+
var newCheckData = {
|
|
458
|
+
visibleItemCount: state.visibleItemCount,
|
|
459
|
+
animationIndex: animationIndex,
|
|
460
|
+
loop: state.loop,
|
|
461
|
+
optionsLength: state.options.length,
|
|
462
|
+
}
|
|
463
|
+
if (!Cache[instanceId]) {
|
|
464
|
+
Cache[instanceId] = {}
|
|
465
|
+
}
|
|
466
|
+
if (JSON.stringify(newCheckData) === Cache[instanceId].check) {
|
|
467
|
+
return Cache[instanceId].result;
|
|
468
|
+
}
|
|
469
|
+
Cache[instanceId].check = JSON.stringify(newCheckData);
|
|
470
|
+
var vOptionLength = state.visibleItemCount * 4 - 2;
|
|
471
|
+
var rotateAngle = 360 / vOptionLength;
|
|
472
|
+
var newArr = wxUtils.createArray(vOptionLength, '');
|
|
473
|
+
var partCount = Math.floor(state.visibleItemCount / 2) + 3;
|
|
474
|
+
var newValueArr = wxUtils.createArray(partCount * 2 + 1, '');
|
|
475
|
+
if (state.loop) {
|
|
476
|
+
// 循环模式:根据 options 首尾填充 newValueArr 数组
|
|
477
|
+
var optionsLength = state.options.length;
|
|
478
|
+
if (optionsLength === 0) {
|
|
479
|
+
// 如果没有选项,填充空值
|
|
480
|
+
wxUtils.fillArray(newValueArr, '');
|
|
481
|
+
} else {
|
|
482
|
+
newValueArr.forEach(function(item, index) {
|
|
483
|
+
// 计算相对于中心的偏移量
|
|
484
|
+
var offset = index - partCount;
|
|
485
|
+
// 计算目标索引,支持循环
|
|
486
|
+
var targetAnimationIndex = animationIndex + offset;
|
|
487
|
+
var targetIndex = (targetAnimationIndex + 1) % optionsLength - 1;
|
|
488
|
+
if(targetIndex < 0) {
|
|
489
|
+
targetIndex += optionsLength;
|
|
490
|
+
}
|
|
294
491
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
492
|
+
newValueArr[index] = targetIndex;
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
} else {
|
|
496
|
+
if (animationIndex < 0) {
|
|
497
|
+
animationIndex = 0;
|
|
498
|
+
}
|
|
499
|
+
if (animationIndex > state.options.length - 1) {
|
|
500
|
+
animationIndex = state.options.length - 1;
|
|
501
|
+
}
|
|
502
|
+
newValueArr.forEach(function(item, index) {
|
|
503
|
+
var valueIndex =
|
|
504
|
+
animationIndex - partCount + index >= 0 ? animationIndex - partCount + index : undefined;
|
|
505
|
+
if (valueIndex === undefined) {
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
newValueArr[index] = valueIndex;
|
|
509
|
+
});
|
|
301
510
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
511
|
+
var rotate = (animationIndex * rotateAngle) % 360;
|
|
512
|
+
if(rotate < 0) {
|
|
513
|
+
rotate += 360;
|
|
514
|
+
}
|
|
515
|
+
var rotateIndex = Math.round(rotate / rotateAngle);
|
|
308
516
|
|
|
517
|
+
// 环形结构填充:以rotateIndex为中心,向两边扩展填充newValueArr
|
|
518
|
+
var centerIndex = rotateIndex; // 中心位置
|
|
519
|
+
var halfLength = Math.floor(newValueArr.length / 2); // newValueArr的一半长度
|
|
309
520
|
|
|
310
|
-
//
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
const { pageY } = e.touches[0];
|
|
315
|
-
const offsetY = pageY - startPo.y;
|
|
316
|
-
const offset = state.offset + offsetY;
|
|
317
|
-
const newOffsetList = [...state.offsetList, offset];
|
|
318
|
-
const currActiveIndex = -offset / state.itemHeight + state.sideCount;
|
|
319
|
-
const preIndexLast = Math.abs(state.offsetActiveIndex % 1);
|
|
320
|
-
const curIndexLast = Math.abs(currActiveIndex % 1);
|
|
321
|
-
const offsetCompare = offset - state.offsetting;
|
|
322
|
-
const direction = offsetCompare < 0 ? 'down' : offsetCompare > 0 ? 'up' : state.movingDirection || 'down';
|
|
323
|
-
updateState(instanceId, 'offsetActiveIndex', currActiveIndex);
|
|
324
|
-
updateState(instanceId, 'offsetting', offset);
|
|
325
|
-
updateState(instanceId, 'offsetList', newOffsetList);
|
|
326
|
-
updateState(instanceId, 'movingDirection', direction);
|
|
327
|
-
updateOptionsStyle(instanceId, ownerInstance, {
|
|
328
|
-
transform: 'translateY(' + addUnit(offset) + ')',
|
|
329
|
-
transition: 'none',
|
|
330
|
-
});
|
|
331
|
-
if((direction === 'down' && preIndexLast <= 0.5 && curIndexLast > 0.5) || (direction === 'up' && preIndexLast >= 0.5 && curIndexLast < 0.5)) {
|
|
332
|
-
ownerInstance.callMethod('animationIndexChange', currActiveIndex);
|
|
333
|
-
ownerInstance.callMethod('vibrateShort');
|
|
521
|
+
// 从中心位置开始,向两边填充
|
|
522
|
+
for (var i = 0; i < newValueArr.length; i++) {
|
|
523
|
+
var targetIndex = (centerIndex - halfLength + i + vOptionLength) % vOptionLength; // 确保索引在0-17范围内
|
|
524
|
+
newArr[targetIndex] = newValueArr[i];
|
|
334
525
|
}
|
|
526
|
+
|
|
527
|
+
Cache[instanceId].result = newArr;
|
|
528
|
+
return newArr
|
|
335
529
|
}
|
|
336
530
|
|
|
531
|
+
function updateVisibleOptions(currentIndex, instanceId) {
|
|
532
|
+
var newArr = getVisibleOptions(currentIndex, instanceId);
|
|
533
|
+
updateState(instanceId, 'optionsVIndexList', newArr);
|
|
534
|
+
return newArr
|
|
535
|
+
}
|
|
337
536
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
537
|
+
function getWrapperCSSVar(instanceId) {
|
|
538
|
+
var state = getCurrState(instanceId);
|
|
539
|
+
var optionsVIndexList = state.optionsVIndexList;
|
|
540
|
+
return optionsVIndexList.reduce(function(previousValue, currentValue, currentIndex) {
|
|
541
|
+
if (currentValue === '' || currentValue === undefined) {
|
|
542
|
+
previousValue['--picker-item-content_' + currentIndex] = '""';
|
|
543
|
+
} else {
|
|
544
|
+
var index = state.loop ? Math.abs(currentValue % state.options.length) : currentValue;
|
|
545
|
+
var text = optionText(state.options, index, state.valueKey);
|
|
546
|
+
previousValue['--picker-item-content_' + currentIndex] = '"' + (text === undefined ? '' : text) + '"';
|
|
547
|
+
}
|
|
548
|
+
return previousValue;
|
|
549
|
+
}, {});
|
|
550
|
+
}
|
|
342
551
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
552
|
+
function updateWrapperStyle(instanceId, ownerInstance, style) {
|
|
553
|
+
style = style || {};
|
|
554
|
+
var state = getCurrState(instanceId);
|
|
555
|
+
var perAngle = 360 / (state.visibleItemCount * 4 - 2)
|
|
556
|
+
var rotate = perAngle * state.animationIndex;
|
|
557
|
+
var cssVar = getWrapperCSSVar(instanceId);
|
|
558
|
+
var styleObj = {
|
|
559
|
+
transition: state.moving ? 'none' : 'transform ' + state.animationTime + 'ms cubic-bezier(0.2, 0.9, 0.25, 1)',
|
|
560
|
+
transform: 'rotateX(' + rotate + 'deg)'
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
const newStyleObject = Object.assign(Object.assign(styleObj, style), cssVar);
|
|
349
564
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
// 计算速度 (px/ms)
|
|
366
|
-
recentVelocity = Math.abs(recentOffset) / (recentTime * 16);
|
|
367
|
-
|
|
368
|
-
// 确定滚动方向
|
|
369
|
-
if (recentOffset > 0) {
|
|
370
|
-
scrollDirection = 1; // 向上滚动
|
|
371
|
-
} else if (recentOffset < 0) {
|
|
372
|
-
scrollDirection = -1; // 向下滚动
|
|
565
|
+
setStyle(ownerInstance, newStyleObject, '.smart-picker-column__offset');
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
function tapItem(instanceId) {
|
|
569
|
+
return function(e, ownerInstance) {
|
|
570
|
+
var state = getCurrState(instanceId);
|
|
571
|
+
var rotateIndex = e.currentTarget.dataset.index;
|
|
572
|
+
var currOptionsActiveIndex = state.optionsVIndexList[rotateIndex];
|
|
573
|
+
var activeRotateIndex = calculateCenterIndex(state.optionsVIndexList);
|
|
574
|
+
var option = state.options[currOptionsActiveIndex];
|
|
575
|
+
if (option === undefined || (option && typeof option === 'object' && option.disabled)) return;
|
|
576
|
+
if (state.startTimer) {
|
|
577
|
+
clearTimeout(state.startTimer);
|
|
578
|
+
updateState(instanceId, 'startTimer', null);
|
|
373
579
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
// 计算惯性滚动距离
|
|
381
|
-
let inertiaDistance = 0;
|
|
382
|
-
if (recentVelocity > minVelocity) {
|
|
383
|
-
// 使用物理公式计算惯性距离:distance = velocity^2 / (2 * friction)
|
|
384
|
-
// 这里简化处理,直接使用速度乘以一个系数
|
|
385
|
-
inertiaDistance = recentVelocity * 200; // 200ms的惯性时间
|
|
386
|
-
|
|
387
|
-
// 限制最大滚动距离
|
|
388
|
-
if (inertiaDistance > maxInertiaDistance) {
|
|
389
|
-
inertiaDistance = maxInertiaDistance;
|
|
580
|
+
if (rotateIndex === activeRotateIndex) return;
|
|
581
|
+
ownerInstance.callMethod('animationStart');
|
|
582
|
+
if (state.tapTimer) {
|
|
583
|
+
clearTimeout(state.tapTimer);
|
|
584
|
+
updateState(instanceId, 'tapTimer', null);
|
|
390
585
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
let targetOffset = Math.round((state.offsetting + inertiaDistance) / state.itemHeight) * state.itemHeight;
|
|
398
|
-
let currTargetActiveIndex = -targetOffset / state.itemHeight + state.sideCount;
|
|
399
|
-
currTargetActiveIndex = adjustIndex(currTargetActiveIndex, state.options);
|
|
400
|
-
targetOffset = -(currTargetActiveIndex - state.sideCount) * state.itemHeight;
|
|
401
|
-
|
|
402
|
-
const isNeedTransition = Math.abs(targetOffset - state.offsetting) > 1;
|
|
403
|
-
const time = isNeedTransition ? state.animationTime : 0;
|
|
404
|
-
const animationOffset = Math.abs(targetOffset - state.offsetting);
|
|
405
|
-
const offsetCount = Math.floor(Math.abs(currTargetActiveIndex - state.offsetActiveIndex));
|
|
406
|
-
if (time > 150 && animationOffset > state.itemHeight) {
|
|
407
|
-
const midTime = 16;
|
|
408
|
-
const count = Math.floor((time - 150) / midTime);
|
|
409
|
-
const midOffset = (targetOffset - state.offsetting)/ count;
|
|
410
|
-
let startCount = 0
|
|
411
|
-
const endTimer = setInterval(() => {
|
|
412
|
-
startCount++;
|
|
413
|
-
const currOffset = state.offsetting + midOffset;
|
|
414
|
-
const currIndex = -currOffset / state.itemHeight + state.sideCount;
|
|
415
|
-
if (startCount >= count) {
|
|
416
|
-
// 动画结束,设置最终状态
|
|
417
|
-
updateState(instanceId, 'offsetActiveIndex', currTargetActiveIndex);
|
|
418
|
-
clearInterval(endTimer);
|
|
419
|
-
updateState(instanceId, 'offsetting', targetOffset);
|
|
420
|
-
updateState(instanceId, 'offset', targetOffset);
|
|
421
|
-
updateState(instanceId, 'moving', false);
|
|
422
|
-
updateOptionsStyle(instanceId, ownerInstance, {
|
|
423
|
-
transform: 'translateY(' + addUnit(Math.round(targetOffset)) + ')',
|
|
424
|
-
transition: 'transform ' + (time ? time + 100 : time) + 'ms',
|
|
425
|
-
});
|
|
426
|
-
if(currTargetActiveIndex !== state.activeIndex) {
|
|
427
|
-
ownerInstance.callMethod('activeIndexChange', currTargetActiveIndex);
|
|
428
|
-
} else {
|
|
429
|
-
ownerInstance.callMethod('animationIndexChange', currTargetActiveIndex);
|
|
430
|
-
}
|
|
431
|
-
return
|
|
432
|
-
};
|
|
433
|
-
updateState(instanceId, 'offsetActiveIndex', currIndex);
|
|
434
|
-
updateState(instanceId, 'offsetting', currOffset);
|
|
435
|
-
updateOptionsStyle(instanceId, ownerInstance, {
|
|
436
|
-
transform: 'translateY(' + addUnit(Math.round(targetOffset)) + ')',
|
|
437
|
-
transition: 'transform ' + (time ? time + 100 : time) + 'ms',
|
|
438
|
-
});
|
|
439
|
-
}, midTime);
|
|
440
|
-
updateState(instanceId, 'endTimer', endTimer);
|
|
441
|
-
ownerInstance.callMethod('vibrateShort', offsetCount);
|
|
442
|
-
} else {
|
|
443
|
-
Math.abs(currTargetActiveIndex - state.offsetActiveIndex) >= 1 && ownerInstance.callMethod('vibrateShort');
|
|
444
|
-
updateState(instanceId, 'offsetActiveIndex', currTargetActiveIndex);
|
|
445
|
-
updateState(instanceId, 'offsetting', targetOffset);
|
|
446
|
-
updateState(instanceId, 'offset', targetOffset);
|
|
447
|
-
updateState(instanceId, 'moving', false);
|
|
448
|
-
updateOptionsStyle(instanceId, ownerInstance, {
|
|
449
|
-
transform: 'translateY(' + addUnit(Math.round(targetOffset)) + ')',
|
|
450
|
-
transition: 'transform ' + (time ? time + 100 : time) + 'ms',
|
|
586
|
+
var currTargetActiveIndex = getNewAnimationIndex(state.animationIndex, currOptionsActiveIndex, state.options.length || 1, state.loop);
|
|
587
|
+
var offsetCount = Math.abs(currTargetActiveIndex - state.animationIndex);
|
|
588
|
+
updateVisibleOptions(currTargetActiveIndex, instanceId);
|
|
589
|
+
updateState(instanceId, 'animationIndex', currTargetActiveIndex);
|
|
590
|
+
updateWrapperStyle(instanceId, ownerInstance, {
|
|
591
|
+
transition: 'transform ' + 300 + 'ms cubic-bezier(0.2, 0.9, 0.25, 1)'
|
|
451
592
|
});
|
|
452
|
-
|
|
593
|
+
ownerInstance.callMethod('animationIndexChange', currTargetActiveIndex);
|
|
594
|
+
ownerInstance.callMethod('vibrateShort', offsetCount, 200);
|
|
595
|
+
var tapTimer = setTimeout(function() {
|
|
453
596
|
ownerInstance.callMethod('activeIndexChange', currTargetActiveIndex);
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
597
|
+
updateState(instanceId, 'tapTimer', null);
|
|
598
|
+
setTimeout(function() {
|
|
599
|
+
ownerInstance.callMethod('animationEnd');
|
|
600
|
+
}, 0);
|
|
601
|
+
}, 200);
|
|
602
|
+
updateState(instanceId, 'tapTimer', tapTimer);
|
|
458
603
|
}
|
|
459
604
|
}
|
|
460
605
|
|
|
461
|
-
const tapItem = (instanceId) => (e, ownerInstance) => {
|
|
462
|
-
const state = getCurrState(instanceId);
|
|
463
|
-
const currTargetActiveIndex = e.currentTarget.dataset.index;
|
|
464
|
-
const option = state.options[currTargetActiveIndex];
|
|
465
|
-
if (option === undefined || option && typeof option === 'object' && option.disabled) return;
|
|
466
|
-
const targetOffset = -(currTargetActiveIndex - state.sideCount) * state.itemHeight;
|
|
467
|
-
if (state.startTimer) {
|
|
468
|
-
clearTimeout(state.startTimer);
|
|
469
|
-
updateState(instanceId, 'startTimer', null);
|
|
470
|
-
}
|
|
471
|
-
if (currTargetActiveIndex === state.offsetActiveIndex) return;
|
|
472
|
-
const offsetCount = Math.abs(currTargetActiveIndex - state.offsetActiveIndex);
|
|
473
|
-
if (state.tapTimer) {
|
|
474
|
-
clearTimeout(state.tapTimer);
|
|
475
|
-
updateState(instanceId, 'tapTimer', null);
|
|
476
|
-
}
|
|
477
|
-
updateState(instanceId, 'offsetActiveIndex', currTargetActiveIndex);
|
|
478
|
-
updateState(instanceId, 'offsetting', targetOffset);
|
|
479
|
-
updateState(instanceId, 'offset', targetOffset);
|
|
480
|
-
updateOptionsStyle(instanceId, ownerInstance, {
|
|
481
|
-
transform: 'translateY(' + addUnit(Math.round(targetOffset)) + ')',
|
|
482
|
-
transition: 'transform 200ms',
|
|
483
|
-
}, 200);
|
|
484
|
-
ownerInstance.callMethod('vibrateShort', offsetCount, 150);
|
|
485
|
-
const tapTimer = setTimeout(() => {
|
|
486
|
-
ownerInstance.callMethod('activeIndexChange', currTargetActiveIndex);
|
|
487
|
-
updateState(instanceId, 'tapTimer', null);
|
|
488
|
-
}, 150);
|
|
489
|
-
updateState(instanceId, 'tapTimer', tapTimer);
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
|
|
493
606
|
module.exports = {
|
|
494
607
|
optionText: optionText,
|
|
495
608
|
rootStyle: rootStyle,
|
|
@@ -500,7 +613,5 @@ module.exports = {
|
|
|
500
613
|
touchStart: touchStart,
|
|
501
614
|
touchMove: touchMove,
|
|
502
615
|
touchEnd: touchEnd,
|
|
503
|
-
sliceArray: sliceArray,
|
|
504
|
-
wrapperItemTextStyle: wrapperItemTextStyle,
|
|
505
616
|
tapItem: tapItem,
|
|
506
617
|
};
|