@tuya-miniapp/smart-ui 2.6.4-beta-8 → 2.6.4-beta-9

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.
@@ -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
- let startPo = { y: 0 }; // 记录当前拖动元素的开始的位置
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 adjustIndex(index, options) {
22
- const count = options.length;
23
- index = range(index, 0, count);
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 isDisabled(option) {
33
- return typeof option === 'object' && option.disabled;
20
+ function rootStyle(data) {
21
+ return style({
22
+ height: addUnit(data.itemHeight * data.visibleItemCount),
23
+ });
34
24
  }
35
25
 
36
- function generateRangeArray(start, end) {
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
- const queryComponent = function (ownerInstance, selector) {
45
- const instance = ownerInstance?.selectComponent(selector);
46
- return instance;
47
- };
28
+ var preStateObj = {}
48
29
 
49
- function sliceArray(list, start, end) {
50
- return list.slice(start, end);
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 isObj(x) {
54
- var type = typeof x;
55
- return x !== null && (type === 'object' || type === 'function');
36
+ function clearCurrState(instanceId) {
37
+ delete state[instanceId]
38
+ delete preStateObj[instanceId]
39
+ delete Cache[instanceId]
56
40
  }
57
41
 
58
- function optionText(option, valueKey) {
59
- return isObj(option) && option[valueKey] != null ? option[valueKey] : option;
42
+ function getCurrState(instanceId) {
43
+ return state[instanceId]
60
44
  }
61
45
 
62
- function rootStyle(data) {
63
- return style({
64
- height: addUnit(data.itemHeight * data.visibleItemCount),
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 offset =
70
- data.offset + (data.itemHeight * (data.visibleItemCount - 1)) / 2;
71
- offset = addUnit(offset);
72
- if (data.animate) {
73
- return style({
74
- 'text-indent': data.unit ? '-8rpx' : '0',
75
- transition: 'transform ' + data.duration + 'ms ease-out',
76
- 'line-height': addUnit(data.itemHeight),
77
- });
78
- }
79
- return style({
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 wrapperItemTextStyle(data) {
103
- var fontStyle = data.fontStyle;
104
- var activeStyle = data.activeStyle;
105
- var isActive = Math.abs(data.index - data.animationIndex) < 0.5;
106
- return fontStyle ? fontStyle + ';' : '' + (isActive ? activeStyle + ';' : '')
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 wrapperItemClass(data) {
110
- var staticClass = 'smart-ellipsis';
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
- var state = {}
107
+ /**
108
+ * 计算有数据的列表的中心索引值(首位相连的环形数组)
109
+ * @param {Array} arr - 输入数组
110
+ * @returns {number} 中心索引值
111
+ */
112
+ function calculateCenterIndex(arr) {
118
113
 
119
- var preStateObj = {}
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
- function getCurrState(instanceId) {
128
- return state[instanceId]
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 updatePreState(instanceId, state) {
132
- const preStateStr = JSON.stringify(state)
133
- preStateObj[instanceId] = preStateStr;
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 getPreState(instanceId) {
137
- return preStateObj[instanceId]
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
- const dom = queryComponent(ownerInstance, '.smart-picker-column');
142
- const state = dom.getDataset();
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
- const state = getDomState(ownerInstance);
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
- const updateValue = (instanceId, key) => (newOptions, oldOptions, ownerInstance) => {
158
- if (!instanceId) return;
159
- initDomState(instanceId, ownerInstance)
160
- updateState(instanceId, key, newOptions)
161
- updateOffset(instanceId, ownerInstance)
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 updateOffset(instanceId, ownerInstance) {
165
- const state = getCurrState(instanceId);
166
- const domState = getDomState(ownerInstance);
167
- if(getPreState(instanceId) === JSON.stringify(domState) || !state.itemHeight || !state.visibleItemCount || !Array.isArray(state.options) || state.animationTime === undefined) {
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
- const sideCount = Math.floor(state.visibleItemCount / 2)
172
- const optionLength = state.options.length;
173
- updateState(instanceId, 'sideCount', sideCount);
174
- const currActiveIndex = state.activeIndex < 0 ? 0 : state.activeIndex >= optionLength ? optionLength - 1 : state.activeIndex;
175
- const currList = getCurrList(instanceId, state.options, currActiveIndex, ownerInstance)
176
- updateRenderPartOffset(instanceId, ownerInstance)
177
- const textVarStyle = {}
178
- currList.forEach((item, index) => {
179
- textVarStyle['--picker-item-content_' + index] = "'" + optionText(item, state.valueKey) + "'"
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
- const getTwoPartOffset = (activeIndex) => {
217
- const currActiveIndex = activeIndex < 0 ? 0 : activeIndex
218
- let partNum = Math.floor((currActiveIndex) / 10);
219
- const lastNum = activeIndex - partNum * 10;
220
- if (lastNum < 5 && partNum > 0) {
221
- partNum -= 1;
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
- const getCurrList = (instanceId, options, activeIndex, ownerInstance) => {
231
- const { onePartOffset, twoPartOffset } = getTwoPartOffset(activeIndex);
232
- const isReverse = onePartOffset > twoPartOffset;
233
- updateState(instanceId, 'onePartOffset', onePartOffset)
234
- updateState(instanceId, 'twoPartOffset', twoPartOffset)
235
- const startPart = twoPartOffset + onePartOffset;
236
- const viewIndexList = !isReverse ? generateRangeArray(startPart * 10, startPart * 10 + 20) : [...generateRangeArray(startPart * 10 + 10, startPart * 10 + 20), ...generateRangeArray(startPart * 10, startPart * 10 + 10)]
237
- updateState(instanceId,'viewIndexList', viewIndexList)
238
- // ownerInstance.callMethod('viewOptionsChange', viewIndexList);
239
- if (!isReverse) return options.slice(startPart * 10, startPart * 10 + 20);
240
- let firstList = options.slice(startPart * 10 + 10, startPart * 10 + 20);
241
- const scendList = options.slice(startPart * 10, startPart * 10 + 10);
242
- if (firstList.length < 10) {
243
- // firstList = [...firstList, ...options.slice(0, 10 - firstList.length)];
244
- firstList = [...firstList, ...new Array(10 - firstList.length).fill('')];
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
- const updateRenderPartOffset = (instanceId, ownerInstance, direction) => {
250
- const state = getCurrState(instanceId);
251
- const offsetDistance = 20 * state.itemHeight;
252
- setStyle(ownerInstance, {
253
- transform: 'translateY(' + addUnit(offsetDistance * state.onePartOffset) + ')',
254
- }, '.smart-picker-column__visual__item_1');
255
- setStyle(ownerInstance, {
256
- transform: 'translateY(' + addUnit(offsetDistance * state.twoPartOffset) + ')',
257
- }, '.smart-picker-column__visual__item_2');
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
- const checkNeedUpdateItemStyle = (instanceId, currActiveIndex) => {
261
- const state = getCurrState(instanceId);
262
- const { onePartOffset, twoPartOffset } = getTwoPartOffset(currActiveIndex);
263
- return onePartOffset !== state.onePartOffset || twoPartOffset !== state.twoPartOffset;
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
- const updateOptionsStyle = (instanceId, ownerInstance, style, time) => {
267
- const state = getCurrState(instanceId);
268
- const needUpdateListOption = checkNeedUpdateItemStyle(instanceId, state.offsetActiveIndex);
269
- if (!needUpdateListOption) {
270
- setStyle(ownerInstance, {
271
- ...style,
272
- }, '.smart-picker-column__offset');
273
- updateItemStyle(instanceId, ownerInstance, time);
274
- return
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
- const getCSSVarText = (instanceId, currList) => {
287
- const state = getCurrState(instanceId);
288
- const textVarStyle = {}
289
- currList.forEach((item, index) => {
290
- textVarStyle['--picker-item-content_' + index] = "'" + optionText(item, state.valueKey) + "'"
291
- })
292
- return textVarStyle;
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
- const touchStart = (instanceId) => (e, ownerInstance) => {
296
- const state = getCurrState(instanceId);
297
- if(state.endTimer) {
298
- clearInterval(state.endTimer);
299
- updateState(instanceId, 'endTimer', null);
300
- updateState(instanceId, 'offset', state.offsetting);
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
- const { pageY } = e.touches[0];
303
- startPo.y = pageY;
304
- updateState(instanceId, 'offsetList', []);
305
- updateState(instanceId, 'moving', false);
306
- updateState(instanceId, 'offsetting', state.offset);
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
- // 滚动期间:1.更新滚动位置 2.更新聚焦点位样式 3.更新列表渲染起始位置 4.更新列表文字CSS 变量
311
- const touchMove = (instanceId) => (e, ownerInstance) => {
312
- const state = getCurrState(instanceId);
313
- updateState(instanceId, 'moving', true);
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
- const touchEnd = (instanceId) => function (e, ownerInstance) {
339
- const state = getCurrState(instanceId);
340
- if(!state.moving) return;
341
- const preOffsetList = state.offsetList;
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
- const maxUpOptionsDistance = state.loop ? state.itemHeight * 500 : state.sideCount * state.itemHeight;
344
- const maxDownOptionsDistance = state.loop ? -state.itemHeight * 500 : -Math.max((state.options.length - state.sideCount - 1) * state.itemHeight, 0);
345
- // 计算最后几帧的平均速度,用于惯性滚动
346
- let recentVelocity = 0;
347
- /** -1: 向下, 1: 向上, 0: 无滚动 */
348
- let scrollDirection = 0;
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
- if (preOffsetList.length >= 2) {
351
- // 计算速度,优先使用最后几帧的数据
352
- let recentOffset = 0;
353
- let recentTime = 0;
354
-
355
- if (preOffsetList.length >= 3) {
356
- // 有3个或以上数据点,使用最后3个点计算速度
357
- recentOffset = preOffsetList[preOffsetList.length - 1] - preOffsetList[preOffsetList.length - 3];
358
- recentTime = 2; // 2帧间隔
359
- } else if (preOffsetList.length === 2) {
360
- // 只有2个数据点,使用这2个点计算速度
361
- recentOffset = preOffsetList[1] - preOffsetList[0];
362
- recentTime = 1; // 1帧间隔
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
- const minVelocity = 0.1; // 最小速度阈值,低于此值停止滚动
378
- const maxInertiaDistance = state.itemHeight * 8; // 最大惯性滚动距离
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
- inertiaDistance = inertiaDistance * scrollDirection;
394
- }
395
-
396
- // 计算最终目标位置 index
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
- if(currTargetActiveIndex !== state.activeIndex) {
593
+ ownerInstance.callMethod('animationIndexChange', currTargetActiveIndex);
594
+ ownerInstance.callMethod('vibrateShort', offsetCount, 200);
595
+ var tapTimer = setTimeout(function() {
453
596
  ownerInstance.callMethod('activeIndexChange', currTargetActiveIndex);
454
- } else {
455
- ownerInstance.callMethod('animationIndexChange', currTargetActiveIndex);
456
- }
457
- return
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
  };