@tuya-miniapp/smart-ui 2.1.10-beta-1 → 2.1.11-beta-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/common/utils.d.ts +1 -0
- package/dist/common/utils.js +6 -0
- package/dist/datetime-picker/demo/index.js +18 -0
- package/dist/datetime-picker/index.js +19 -6
- package/dist/datetime-picker/index.wxml +1 -0
- package/dist/icon/index.wxs +3 -1
- package/dist/picker/demo/index.js +1 -0
- package/dist/picker/index.wxml +1 -0
- package/dist/picker/shared.d.ts +4 -0
- package/dist/picker/shared.js +4 -0
- package/dist/picker-column/index.css +1 -1
- package/dist/picker-column/index.js +154 -44
- package/dist/picker-column/index.wxml +22 -11
- package/dist/picker-column/index.wxs +22 -5
- package/dist/picker-column/index.wxss +1 -1
- package/lib/common/utils.d.ts +1 -0
- package/lib/common/utils.js +8 -1
- package/lib/datetime-picker/demo/index.js +18 -0
- package/lib/datetime-picker/index.js +23 -8
- package/lib/datetime-picker/index.wxml +1 -0
- package/lib/icon/index.wxs +3 -1
- package/lib/picker/demo/index.js +1 -0
- package/lib/picker/index.wxml +1 -0
- package/lib/picker/shared.d.ts +4 -0
- package/lib/picker/shared.js +4 -0
- package/lib/picker-column/index.css +1 -1
- package/lib/picker-column/index.js +192 -44
- package/lib/picker-column/index.wxml +22 -11
- package/lib/picker-column/index.wxs +22 -5
- package/lib/picker-column/index.wxss +1 -1
- package/package.json +3 -3
package/dist/common/utils.d.ts
CHANGED
@@ -19,3 +19,4 @@ export declare const clamp: (num: any, min: any, max: any) => number;
|
|
19
19
|
export declare function getCurrentPage<T>(): T & WechatMiniprogram.OptionalInterface<WechatMiniprogram.Page.ILifetime> & WechatMiniprogram.Page.InstanceProperties & WechatMiniprogram.Page.InstanceMethods<WechatMiniprogram.IAnyObject> & WechatMiniprogram.Page.Data<WechatMiniprogram.IAnyObject> & WechatMiniprogram.IAnyObject;
|
20
20
|
export declare const isPC: boolean;
|
21
21
|
export declare const isWxWork: boolean;
|
22
|
+
export declare function replacePlaceholders(template: any, values: any): any;
|
package/dist/common/utils.js
CHANGED
@@ -84,3 +84,9 @@ export function getCurrentPage() {
|
|
84
84
|
export const isPC = ['mac', 'windows'].includes(getSystemInfoSync().platform);
|
85
85
|
// 是否企业微信
|
86
86
|
export const isWxWork = getSystemInfoSync().environment === 'wxwork';
|
87
|
+
export function replacePlaceholders(template, values) {
|
88
|
+
// 使用正则表达式匹配占位符
|
89
|
+
return template.replace(/{{(.*?)}}/g, (match, key) => {
|
90
|
+
return values[key] || match; // 如果在values中找到key对应的值,则替换;否则保留原样
|
91
|
+
});
|
92
|
+
}
|
@@ -11,6 +11,24 @@ SmartComponent({
|
|
11
11
|
currentDate3: new Date(2018, 0, 1),
|
12
12
|
currentDate4: '12:00',
|
13
13
|
loading: false,
|
14
|
+
formatterMap: {
|
15
|
+
year: '{{year}}年',
|
16
|
+
month: {
|
17
|
+
'01': 'January',
|
18
|
+
'02': 'February',
|
19
|
+
'03': 'March',
|
20
|
+
'04': 'April',
|
21
|
+
'05': 'May',
|
22
|
+
'06': 'June',
|
23
|
+
'07': 'July',
|
24
|
+
'08': 'August',
|
25
|
+
'09': 'September',
|
26
|
+
'10': 'October',
|
27
|
+
'11': 'November',
|
28
|
+
'12': 'December',
|
29
|
+
},
|
30
|
+
day: '{{day}}日'
|
31
|
+
},
|
14
32
|
formatter(type, value) {
|
15
33
|
if (type === 'year') {
|
16
34
|
return `${value}${I18n.t('year')}`;
|
@@ -1,13 +1,11 @@
|
|
1
1
|
import { SmartComponent } from '../common/component';
|
2
2
|
import { isDef } from '../common/validator';
|
3
3
|
import { pickerProps } from '../picker/shared';
|
4
|
+
import { range, replacePlaceholders } from '../common/utils';
|
4
5
|
const currentYear = new Date().getFullYear();
|
5
6
|
function isValidDate(date) {
|
6
7
|
return isDef(date) && !isNaN(new Date(date).getTime());
|
7
8
|
}
|
8
|
-
function range(num, min, max) {
|
9
|
-
return Math.min(Math.max(num, min), max);
|
10
|
-
}
|
11
9
|
function padZero(val) {
|
12
10
|
return `00${val}`.slice(-2);
|
13
11
|
}
|
@@ -73,6 +71,9 @@ SmartComponent({
|
|
73
71
|
type: Number,
|
74
72
|
value: 59,
|
75
73
|
observer: 'updateValue',
|
74
|
+
}, formatterMap: {
|
75
|
+
type: Object,
|
76
|
+
value: undefined,
|
76
77
|
} }),
|
77
78
|
data: {
|
78
79
|
innerValue: Date.now(),
|
@@ -98,10 +99,22 @@ SmartComponent({
|
|
98
99
|
}
|
99
100
|
return this.picker;
|
100
101
|
},
|
102
|
+
formatterFunc(type, value) {
|
103
|
+
var _a;
|
104
|
+
const { formatterMap, formatter = defaultFormatter } = this.data;
|
105
|
+
const mapDetail = formatterMap === null || formatterMap === void 0 ? void 0 : formatterMap[type];
|
106
|
+
if (typeof mapDetail === 'string') {
|
107
|
+
return replacePlaceholders(mapDetail, { [type]: value });
|
108
|
+
}
|
109
|
+
if (typeof mapDetail === 'object') {
|
110
|
+
return (_a = mapDetail[value]) !== null && _a !== void 0 ? _a : formatter(type, value);
|
111
|
+
}
|
112
|
+
return formatter(type, value);
|
113
|
+
},
|
101
114
|
updateColumns() {
|
102
|
-
const {
|
115
|
+
const { locale } = this.data;
|
103
116
|
const results = this.getOriginColumns().map(column => ({
|
104
|
-
values: column.values.map(value =>
|
117
|
+
values: column.values.map(value => this.formatterFunc(column.type, value)),
|
105
118
|
unit: locale === null || locale === void 0 ? void 0 : locale[column.type],
|
106
119
|
}));
|
107
120
|
return this.set({ columns: results });
|
@@ -264,7 +277,7 @@ SmartComponent({
|
|
264
277
|
updateColumnValue(value) {
|
265
278
|
let values = [];
|
266
279
|
const { type } = this.data;
|
267
|
-
const formatter = this.
|
280
|
+
const formatter = this.formatterFunc;
|
268
281
|
const picker = this.getPicker();
|
269
282
|
if (type === 'time') {
|
270
283
|
const pair = value.split(':');
|
@@ -10,6 +10,7 @@
|
|
10
10
|
visible-item-count="{{ visibleItemCount }}"
|
11
11
|
confirm-button-text="{{ confirmButtonText }}"
|
12
12
|
cancel-button-text="{{ cancelButtonText }}"
|
13
|
+
change-animation="{{ changeAnimation }}"
|
13
14
|
bind:change="onChange"
|
14
15
|
bind:confirm="onConfirm"
|
15
16
|
bind:cancel="onCancel"
|
package/dist/icon/index.wxs
CHANGED
@@ -14,7 +14,7 @@ function rootClass(data) {
|
|
14
14
|
var classes = ['custom-class'];
|
15
15
|
|
16
16
|
if (data.classPrefix !== 'smart-icon') {
|
17
|
-
classes.push('smart-icon--custom')
|
17
|
+
classes.push('smart-icon--custom');
|
18
18
|
}
|
19
19
|
|
20
20
|
if (data.classPrefix != null) {
|
@@ -54,6 +54,8 @@ function svgStyle(data) {
|
|
54
54
|
{
|
55
55
|
'-webkit-mask-image': imageBase64Src,
|
56
56
|
'-webkit-mask-size': 'contain',
|
57
|
+
'-webkit-mask-repeat': 'no-repeat',
|
58
|
+
'-webkit-mask-position': 'center',
|
57
59
|
'mask-image': imageBase64Src,
|
58
60
|
'mask-size': 'contain',
|
59
61
|
width: data.size,
|
package/dist/picker/index.wxml
CHANGED
@@ -23,6 +23,7 @@
|
|
23
23
|
active-style="{{ activeStyle }}"
|
24
24
|
options="{{ item.values }}"
|
25
25
|
unit="{{ item.unit || unit }}"
|
26
|
+
changeAnimation="{{ changeAnimation }}"
|
26
27
|
default-index="{{ item.defaultIndex || defaultIndex }}"
|
27
28
|
active-index="{{ item.activeIndex || activeIndex }}"
|
28
29
|
item-height="{{ itemHeight }}"
|
package/dist/picker/shared.d.ts
CHANGED
package/dist/picker/shared.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
@import '../common/index.css';.smart-picker-column{color:var(--picker-option-selected-text-color,var(--app-B6-N1,#000));font-size:var(--picker-option-font-size,16px);font-weight:var(--font-weight-bold,500);position:relative;
|
1
|
+
@import '../common/index.css';.smart-picker-column{color:var(--picker-option-selected-text-color,var(--app-B6-N1,#000));font-size:var(--picker-option-font-size,16px);font-weight:var(--font-weight-bold,500);text-align:center}.smart-picker-column,.smart-picker-column__offset{position:relative;width:100%}.smart-picker-column__visual{position:absolute;top:0;width:100%}.smart-picker-column__item{pointer-events:none}.smart-picker-column__item--selected{color:var(--picker-option-selected-text-color,var(--app-B6-N1,#000));font-weight:var(--font-weight-bold,500)}.smart-picker-column__item--disabled{opacity:var(--picker-option-disabled-opacity,.3)}.smart-picker-column__mask{background:transparent;display:flex;flex-direction:column;height:100%;position:absolute;top:0;width:100%;z-index:10}.smart-picker-column__mask__item{flex:1}.smart-picker-column__unit{align-items:center;display:flex;justify-content:center;position:absolute;top:50%;transform:translateY(-50%);width:100%}.smart-picker-column__unit_text{color:var(--picker-option-unit-text-color,var(--app-B6-N4,rgba(0,0,0,.4)));font-size:var(--picker-option-unit-font-size,12px)}.smart-picker-column__unit_hidden{opacity:0}.smart-picker-column__max-text{font-weight:var(--font-weight-bold,500);opacity:0}
|
@@ -1,7 +1,16 @@
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
8
|
+
});
|
9
|
+
};
|
1
10
|
import { SmartComponent } from '../common/component';
|
2
11
|
import { range } from '../common/utils';
|
3
12
|
import { isObj } from '../common/validator';
|
4
|
-
const DEFAULT_DURATION =
|
13
|
+
const DEFAULT_DURATION = 400;
|
5
14
|
SmartComponent({
|
6
15
|
classes: ['active-class'],
|
7
16
|
props: {
|
@@ -25,11 +34,15 @@ SmartComponent({
|
|
25
34
|
type: Number,
|
26
35
|
value: 0,
|
27
36
|
},
|
37
|
+
changeAnimation: {
|
38
|
+
type: Boolean,
|
39
|
+
value: true,
|
40
|
+
},
|
28
41
|
activeIndex: {
|
29
42
|
type: Number,
|
30
43
|
value: -1,
|
31
44
|
observer(index) {
|
32
|
-
this.setIndex(index, false,
|
45
|
+
this.setIndex(index, false, this.data.changeAnimation);
|
33
46
|
},
|
34
47
|
},
|
35
48
|
unit: {
|
@@ -48,57 +61,157 @@ SmartComponent({
|
|
48
61
|
renderStart: 0,
|
49
62
|
animate: false,
|
50
63
|
maxText: '',
|
64
|
+
timer: null,
|
65
|
+
// animationIndex: -1,
|
66
|
+
preOffsetList: [],
|
51
67
|
},
|
52
68
|
created() {
|
53
69
|
const { defaultIndex, activeIndex, options } = this.data;
|
54
70
|
this.updateUint(options);
|
55
|
-
this.setIndex(activeIndex !== -1 ? activeIndex : defaultIndex, false,
|
71
|
+
this.setIndex(activeIndex !== -1 ? activeIndex : defaultIndex, false, this.data.changeAnimation);
|
56
72
|
},
|
57
73
|
methods: {
|
58
74
|
getCount() {
|
59
75
|
return this.data.options.length;
|
60
76
|
},
|
61
77
|
onTouchStart(event) {
|
78
|
+
if (this.data.timer) {
|
79
|
+
clearTimeout(this.data.timer);
|
80
|
+
this.setData({
|
81
|
+
timer: null,
|
82
|
+
});
|
83
|
+
}
|
62
84
|
this.setData({
|
63
85
|
startY: event.touches[0].clientY,
|
64
86
|
startOffset: this.data.offset,
|
65
|
-
duration:
|
87
|
+
duration: 100,
|
88
|
+
timer: null,
|
89
|
+
preOffsetList: [this.data.offset],
|
66
90
|
});
|
67
91
|
},
|
68
92
|
onTouchMove(event) {
|
69
93
|
const { data } = this;
|
94
|
+
const { preOffsetList } = data;
|
70
95
|
const deltaY = event.touches[0].clientY - data.startY;
|
96
|
+
const offset = range(data.startOffset + deltaY, -(this.getCount() * data.itemHeight), data.itemHeight);
|
97
|
+
const direction = this.checkIsDown(offset);
|
98
|
+
// 上一次滚动的索引
|
99
|
+
const preIndex = range(Math.round(-preOffsetList[preOffsetList.length - 1] / data.itemHeight), 0, this.getCount() - 1);
|
100
|
+
// 最终定位索引
|
101
|
+
const index = range(Math.round(-offset / data.itemHeight), 0, this.getCount() - 1);
|
102
|
+
if ((direction === 'up' && index < data.renderStart + 8) ||
|
103
|
+
(direction === 'down' && index > data.renderStart + data.renderNum - 8)) {
|
104
|
+
this.updateVisibleOptions(index);
|
105
|
+
}
|
106
|
+
// 索引变化时 粗发震动反馈
|
107
|
+
if (index !== preIndex) {
|
108
|
+
// @ts-ignore
|
109
|
+
this.vibrateShort();
|
110
|
+
}
|
111
|
+
// const animationIndex = Math.abs(-offset / data.itemHeight);
|
71
112
|
this.setData({
|
72
|
-
offset
|
113
|
+
offset,
|
114
|
+
// animationIndex: animationIndex,
|
115
|
+
preOffsetList: [...data.preOffsetList, offset],
|
116
|
+
animate: false,
|
73
117
|
});
|
74
118
|
},
|
75
119
|
onTouchEnd() {
|
120
|
+
return __awaiter(this, void 0, void 0, function* () {
|
121
|
+
const { data } = this;
|
122
|
+
const { preOffsetList } = data;
|
123
|
+
let preOffset = Math.max(Math.abs(preOffsetList[preOffsetList.length - 3] - preOffsetList[preOffsetList.length - 4]), Math.abs(preOffsetList[preOffsetList.length - 2] - preOffsetList[preOffsetList.length - 3]), Math.abs(preOffsetList[preOffsetList.length - 1] - preOffsetList[preOffsetList.length - 2]));
|
124
|
+
if (isNaN(preOffset))
|
125
|
+
preOffset = 0;
|
126
|
+
preOffset = Math.min(preOffset, 40);
|
127
|
+
// 三次同样的距离 说明用户一直在顶部或者底部滑动 或在move途中已经是上下边缘了
|
128
|
+
const isSameTouch = (preOffsetList[preOffsetList.length - 1] === preOffsetList[preOffsetList.length - 2] &&
|
129
|
+
preOffsetList[preOffsetList.length - 2] === preOffsetList[preOffsetList.length - 3]) ||
|
130
|
+
preOffsetList[preOffsetList.length - 1] === -(this.getCount() * data.itemHeight) ||
|
131
|
+
preOffsetList[preOffsetList.length - 1] === data.itemHeight;
|
132
|
+
// 是否是向下滚动
|
133
|
+
const direction = this.checkIsDown();
|
134
|
+
// 当滚动速度比较慢时(<3) 不增加惯性滚动距离
|
135
|
+
const offset = Math.abs(preOffset) < 3 || isSameTouch || !direction
|
136
|
+
? data.offset
|
137
|
+
: data.offset + (direction === 'down' ? -preOffset : preOffset) * 10;
|
138
|
+
// 有数字的最大滚动距离
|
139
|
+
const countHeight = (this.getCount() - 1) * data.itemHeight;
|
140
|
+
// 动画最大滚动距离 上下各加一个 data.itemHeight 的滚动空间
|
141
|
+
const animationOffset = range(offset, -(this.getCount() * data.itemHeight), data.itemHeight);
|
142
|
+
// 最终定位滚动位置
|
143
|
+
const finOffset = animationOffset < -countHeight ? -countHeight : animationOffset > 0 ? 0 : animationOffset;
|
144
|
+
// 获取索引
|
145
|
+
const index = range(Math.round(-finOffset / data.itemHeight), 0, this.getCount() - 1);
|
146
|
+
// 获取索引的标准距离
|
147
|
+
const offsetData = -index * data.itemHeight;
|
148
|
+
// 增加惯性音效
|
149
|
+
if (Math.abs(offsetData - data.offset) > data.itemHeight && !isSameTouch) {
|
150
|
+
const countVibrate = Math.abs(offsetData - data.offset) / data.itemHeight;
|
151
|
+
// @ts-ignore
|
152
|
+
this.vibrateShort(Math.floor(countVibrate), 800);
|
153
|
+
}
|
154
|
+
// 最终定位索引
|
155
|
+
this.setData({
|
156
|
+
duration: isSameTouch ? 150 : 800,
|
157
|
+
// animationIndex: index,
|
158
|
+
offset: offsetData,
|
159
|
+
animate: true,
|
160
|
+
});
|
161
|
+
// 更新列表
|
162
|
+
if ((direction === 'up' && index < data.renderStart + 8) ||
|
163
|
+
(direction === 'down' && index > data.renderStart + data.renderNum - 8)) {
|
164
|
+
yield this.updateVisibleOptions(index);
|
165
|
+
}
|
166
|
+
// 更新索引
|
167
|
+
if (index !== data.currentIndex) {
|
168
|
+
this.setData({
|
169
|
+
timer: setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
170
|
+
this.setIndex(index, true, false);
|
171
|
+
// await this.setData({
|
172
|
+
// timer: null,
|
173
|
+
// currentIndex: index,
|
174
|
+
// // animationIndex: index,
|
175
|
+
// });
|
176
|
+
// this.$emit('change', index);
|
177
|
+
}), isSameTouch ? 150 : 800),
|
178
|
+
});
|
179
|
+
}
|
180
|
+
});
|
181
|
+
},
|
182
|
+
checkIsDown(curr) {
|
76
183
|
const { data } = this;
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
184
|
+
const { preOffsetList } = data;
|
185
|
+
const currOffset = curr === undefined ? preOffsetList[preOffsetList.length - 1] : curr;
|
186
|
+
const preOffset = curr === undefined
|
187
|
+
? preOffsetList[preOffsetList.length - 2]
|
188
|
+
: preOffsetList[preOffsetList.length - 1];
|
189
|
+
if (currOffset === undefined || preOffset === undefined || currOffset === preOffset)
|
190
|
+
return;
|
191
|
+
return currOffset < preOffset ? 'down' : 'up';
|
81
192
|
},
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
// 选项多于20个时,进行列表优化
|
88
|
-
renderNum = Math.max(visibleItemCount * 2, 20);
|
89
|
-
renderStart = Math.max(0, currentIndex - renderNum / 2);
|
90
|
-
const optionsV = options.slice(renderStart, renderStart + renderNum);
|
91
|
-
this.setData({ optionsV, renderStart, renderNum, animate: false });
|
92
|
-
}
|
93
|
-
else {
|
94
|
-
this.setData({ animate: false });
|
95
|
-
}
|
96
|
-
if (this.fireChange) {
|
97
|
-
this.$emit('change', currentIndex);
|
193
|
+
vibrateShort(count, time = 1000) {
|
194
|
+
if (!count) {
|
195
|
+
// @ts-ignore
|
196
|
+
ty.vibrateShort({ type: 'light' });
|
197
|
+
return;
|
98
198
|
}
|
199
|
+
let has = 0;
|
200
|
+
const timer = setInterval(() => {
|
201
|
+
if (has >= count) {
|
202
|
+
clearInterval(timer);
|
203
|
+
return;
|
204
|
+
}
|
205
|
+
has++;
|
206
|
+
this.vibrateShort();
|
207
|
+
}, time / count - 20);
|
99
208
|
},
|
100
209
|
onClickItem(event) {
|
101
210
|
const { index } = event.currentTarget.dataset;
|
211
|
+
if (index === this.data.currentIndex || index < 0 || index > this.data.options.length - 1) {
|
212
|
+
return;
|
213
|
+
}
|
214
|
+
this.vibrateShort(Math.abs(index - this.data.currentIndex), DEFAULT_DURATION);
|
102
215
|
this.setIndex(index, true, true);
|
103
216
|
},
|
104
217
|
updateUint(options) {
|
@@ -120,7 +233,7 @@ SmartComponent({
|
|
120
233
|
if (visibleItemCount < 20 && options.length > visibleItemCount) {
|
121
234
|
let renderNum = 0;
|
122
235
|
let renderStart = 0;
|
123
|
-
// 选项多于20个时,进行列表优化
|
236
|
+
// 选项多于 20 个时,进行列表优化
|
124
237
|
renderNum = Math.max(visibleItemCount * 2, 20);
|
125
238
|
renderStart = Math.max(0, targetIndex - renderNum / 2);
|
126
239
|
const renderEnd = Math.min(options.length, renderStart + renderNum);
|
@@ -159,35 +272,32 @@ SmartComponent({
|
|
159
272
|
const { data } = this;
|
160
273
|
return isObj(option) && data.valueKey in option ? option[data.valueKey] : option;
|
161
274
|
},
|
162
|
-
setIndex(index, userAction, animate) {
|
275
|
+
setIndex(index, userAction, animate, time = DEFAULT_DURATION) {
|
163
276
|
const { data } = this;
|
164
277
|
index = this.adjustIndex(index) || 0;
|
165
278
|
const offset = -index * data.itemHeight;
|
166
|
-
this.fireChange = false;
|
167
279
|
if (index !== data.currentIndex) {
|
168
280
|
// 需要动画的情况下,保持最大的截取
|
281
|
+
this.updateVisibleOptions(index);
|
169
282
|
if (animate) {
|
170
|
-
return this.
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
return;
|
182
|
-
}
|
183
|
-
this.fireChange = true;
|
184
|
-
});
|
283
|
+
return this.set({
|
284
|
+
currentIndex: index,
|
285
|
+
// animationIndex: index,
|
286
|
+
offset,
|
287
|
+
animate: true,
|
288
|
+
duration: time,
|
289
|
+
}).then(() => {
|
290
|
+
if (!userAction)
|
291
|
+
return;
|
292
|
+
console.log('change', index);
|
293
|
+
this.$emit('change', index);
|
185
294
|
});
|
186
295
|
}
|
187
296
|
return this.set({
|
188
297
|
optionsV: data.options,
|
189
298
|
offset,
|
190
299
|
currentIndex: index,
|
300
|
+
// animationIndex: index,
|
191
301
|
renderStart: 0,
|
192
302
|
animate: !!animate,
|
193
303
|
}).then(() => {
|
@@ -200,7 +310,7 @@ SmartComponent({
|
|
200
310
|
const { options } = this.data;
|
201
311
|
for (let i = 0; i < options.length; i++) {
|
202
312
|
if (this.getOptionText(options[i]) === value) {
|
203
|
-
return this.setIndex(i, false,
|
313
|
+
return this.setIndex(i, false, this.data.changeAnimation);
|
204
314
|
}
|
205
315
|
}
|
206
316
|
return Promise.resolve();
|
@@ -9,18 +9,29 @@
|
|
9
9
|
bind:touchend="onTouchEnd"
|
10
10
|
bind:touchcancel="onTouchEnd"
|
11
11
|
>
|
12
|
-
<view style="{{ computed.wrapperStyle({ offset, itemHeight, visibleItemCount, animate, duration, renderStart, unit }) }}"
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
<view class="smart-picker-column__offset" style="height: {{ itemHeight * options.length }}px;{{ computed.wrapperStyle({ offset, itemHeight, visibleItemCount, animate, duration, renderStart, unit }) }}" id="options">
|
13
|
+
<view class="smart-picker-column__visual" style="{{ computed.wrapperInterStyle({ offset, itemHeight, visibleItemCount, renderStart }) }}">
|
14
|
+
<view
|
15
|
+
wx:for="{{ optionsV }}"
|
16
|
+
wx:for-item="option"
|
17
|
+
wx:key="index"
|
18
|
+
data-index="{{ renderStart + index }}"
|
19
|
+
style="height: {{ itemHeight }}px;{{renderStart + index === currentIndex ? activeStyle : ''}}"
|
20
|
+
class="smart-ellipsis {{ utils.bem('picker-column__item', { disabled: option && option.disabled, selected: renderStart + index === currentIndex }) }} {{ renderStart + index === currentIndex ? 'active-class' : '' }}"
|
21
|
+
>
|
22
|
+
{{ computed.optionText(option, valueKey) }}
|
23
|
+
</view>
|
24
|
+
</view>
|
25
|
+
</view>
|
26
|
+
<view class="smart-picker-column__mask">
|
27
|
+
<view
|
28
|
+
wx:for="{{ visibleItemCount }}"
|
18
29
|
wx:key="index"
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
30
|
+
class="smart-picker-column__mask__item"
|
31
|
+
data-index="{{ currentIndex + index - 2 }}"
|
32
|
+
bind:tap="onClickItem"
|
33
|
+
>
|
34
|
+
</view>
|
24
35
|
</view>
|
25
36
|
<view wx:if="{{unit}}" class="smart-picker-column__unit" style="height: {{ itemHeight }}px">
|
26
37
|
<view class="smart-picker-column__unit_text smart-picker-column__unit_hidden" >{{unit}}</view>
|
@@ -20,15 +20,11 @@ function rootStyle(data) {
|
|
20
20
|
function wrapperStyle(data) {
|
21
21
|
var offset =
|
22
22
|
data.offset + (data.itemHeight * (data.visibleItemCount - 1)) / 2;
|
23
|
-
// 长列表优化
|
24
|
-
if (data.renderStart) {
|
25
|
-
offset += data.renderStart * data.itemHeight;
|
26
|
-
}
|
27
23
|
offset = addUnit(offset);
|
28
24
|
if (data.animate) {
|
29
25
|
return style({
|
30
26
|
'text-indent': data.unit ? '-8rpx' : '0',
|
31
|
-
transition: 'transform ' + data.duration + 'ms',
|
27
|
+
transition: 'transform ' + data.duration + 'ms ease-out',
|
32
28
|
'line-height': addUnit(data.itemHeight),
|
33
29
|
transform: 'translate3d(0, ' + offset + ', 0)',
|
34
30
|
});
|
@@ -40,8 +36,29 @@ function wrapperStyle(data) {
|
|
40
36
|
});
|
41
37
|
}
|
42
38
|
|
39
|
+
function wrapperInterStyle(data) {
|
40
|
+
var offset = data.renderStart * data.itemHeight;
|
41
|
+
offset = addUnit(offset);
|
42
|
+
return style({
|
43
|
+
'padding-top': offset,
|
44
|
+
});
|
45
|
+
}
|
46
|
+
|
47
|
+
// function wrapperItemStyle(data) {
|
48
|
+
// const { index, animationIndex: currentIndex } = data;
|
49
|
+
// const offsetIndex = currentIndex - index;
|
50
|
+
// const rotateX = offsetIndex * 25 > 0 ? Math.min(offsetIndex * 25, 25 * 2) : Math.max(offsetIndex * 25, -25 * 2)
|
51
|
+
// const scale = Math.min(Math.abs(offsetIndex * 0.05), 0.05 * 2)
|
52
|
+
// return style({
|
53
|
+
// transition: 'transform ' + data.duration + 'ms ease-out',
|
54
|
+
// transform: `rotateX(${rotateX}deg) scale(${1 - scale})`
|
55
|
+
// });
|
56
|
+
// }
|
57
|
+
|
43
58
|
module.exports = {
|
44
59
|
optionText: optionText,
|
45
60
|
rootStyle: rootStyle,
|
46
61
|
wrapperStyle: wrapperStyle,
|
62
|
+
wrapperInterStyle: wrapperInterStyle,
|
63
|
+
// wrapperItemStyle: wrapperItemStyle
|
47
64
|
};
|
@@ -1 +1 @@
|
|
1
|
-
@import '../common/index.wxss';.smart-picker-column{color:var(--picker-option-selected-text-color,var(--app-B6-N1,#000));font-size:var(--picker-option-font-size,16px);font-weight:var(--font-weight-bold,500);position:relative;
|
1
|
+
@import '../common/index.wxss';.smart-picker-column{color:var(--picker-option-selected-text-color,var(--app-B6-N1,#000));font-size:var(--picker-option-font-size,16px);font-weight:var(--font-weight-bold,500);text-align:center}.smart-picker-column,.smart-picker-column__offset{position:relative;width:100%}.smart-picker-column__visual{position:absolute;top:0;width:100%}.smart-picker-column__item{pointer-events:none}.smart-picker-column__item--selected{color:var(--picker-option-selected-text-color,var(--app-B6-N1,#000));font-weight:var(--font-weight-bold,500)}.smart-picker-column__item--disabled{opacity:var(--picker-option-disabled-opacity,.3)}.smart-picker-column__mask{background:transparent;display:flex;flex-direction:column;height:100%;position:absolute;top:0;width:100%;z-index:10}.smart-picker-column__mask__item{flex:1}.smart-picker-column__unit{align-items:center;display:flex;justify-content:center;position:absolute;top:50%;transform:translateY(-50%);width:100%}.smart-picker-column__unit_text{color:var(--picker-option-unit-text-color,var(--app-B6-N4,rgba(0,0,0,.4)));font-size:var(--picker-option-unit-font-size,12px)}.smart-picker-column__unit_hidden{opacity:0}.smart-picker-column__max-text{font-weight:var(--font-weight-bold,500);opacity:0}
|
package/lib/common/utils.d.ts
CHANGED
@@ -19,3 +19,4 @@ export declare const clamp: (num: any, min: any, max: any) => number;
|
|
19
19
|
export declare function getCurrentPage<T>(): T & WechatMiniprogram.OptionalInterface<WechatMiniprogram.Page.ILifetime> & WechatMiniprogram.Page.InstanceProperties & WechatMiniprogram.Page.InstanceMethods<WechatMiniprogram.IAnyObject> & WechatMiniprogram.Page.Data<WechatMiniprogram.IAnyObject> & WechatMiniprogram.IAnyObject;
|
20
20
|
export declare const isPC: boolean;
|
21
21
|
export declare const isWxWork: boolean;
|
22
|
+
export declare function replacePlaceholders(template: any, values: any): any;
|
package/lib/common/utils.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.isWxWork = exports.isPC = exports.getCurrentPage = exports.clamp = exports.addNumber = exports.toPromise = exports.groupSetData = exports.getAllRect = exports.getRect = exports.pickExclude = exports.requestAnimationFrame = exports.addUnit = exports.nextTick = exports.range = exports.getSystemInfoSync = exports.isDef = void 0;
|
3
|
+
exports.replacePlaceholders = exports.isWxWork = exports.isPC = exports.getCurrentPage = exports.clamp = exports.addNumber = exports.toPromise = exports.groupSetData = exports.getAllRect = exports.getRect = exports.pickExclude = exports.requestAnimationFrame = exports.addUnit = exports.nextTick = exports.range = exports.getSystemInfoSync = exports.isDef = void 0;
|
4
4
|
var validator_1 = require("./validator");
|
5
5
|
var version_1 = require("./version");
|
6
6
|
var validator_2 = require("./validator");
|
@@ -107,3 +107,10 @@ exports.getCurrentPage = getCurrentPage;
|
|
107
107
|
exports.isPC = ['mac', 'windows'].includes((0, version_1.getSystemInfoSync)().platform);
|
108
108
|
// 是否企业微信
|
109
109
|
exports.isWxWork = (0, version_1.getSystemInfoSync)().environment === 'wxwork';
|
110
|
+
function replacePlaceholders(template, values) {
|
111
|
+
// 使用正则表达式匹配占位符
|
112
|
+
return template.replace(/{{(.*?)}}/g, function (match, key) {
|
113
|
+
return values[key] || match; // 如果在values中找到key对应的值,则替换;否则保留原样
|
114
|
+
});
|
115
|
+
}
|
116
|
+
exports.replacePlaceholders = replacePlaceholders;
|
@@ -16,6 +16,24 @@ var toast_1 = __importDefault(require("../../toast/toast"));
|
|
16
16
|
currentDate3: new Date(2018, 0, 1),
|
17
17
|
currentDate4: '12:00',
|
18
18
|
loading: false,
|
19
|
+
formatterMap: {
|
20
|
+
year: '{{year}}年',
|
21
|
+
month: {
|
22
|
+
'01': 'January',
|
23
|
+
'02': 'February',
|
24
|
+
'03': 'March',
|
25
|
+
'04': 'April',
|
26
|
+
'05': 'May',
|
27
|
+
'06': 'June',
|
28
|
+
'07': 'July',
|
29
|
+
'08': 'August',
|
30
|
+
'09': 'September',
|
31
|
+
'10': 'October',
|
32
|
+
'11': 'November',
|
33
|
+
'12': 'December',
|
34
|
+
},
|
35
|
+
day: '{{day}}日'
|
36
|
+
},
|
19
37
|
formatter: function (type, value) {
|
20
38
|
if (type === 'year') {
|
21
39
|
return "".concat(value).concat(I18n.t('year'));
|
@@ -23,13 +23,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
23
|
var component_1 = require("../common/component");
|
24
24
|
var validator_1 = require("../common/validator");
|
25
25
|
var shared_1 = require("../picker/shared");
|
26
|
+
var utils_1 = require("../common/utils");
|
26
27
|
var currentYear = new Date().getFullYear();
|
27
28
|
function isValidDate(date) {
|
28
29
|
return (0, validator_1.isDef)(date) && !isNaN(new Date(date).getTime());
|
29
30
|
}
|
30
|
-
function range(num, min, max) {
|
31
|
-
return Math.min(Math.max(num, min), max);
|
32
|
-
}
|
33
31
|
function padZero(val) {
|
34
32
|
return "00".concat(val).slice(-2);
|
35
33
|
}
|
@@ -97,6 +95,9 @@ var defaultFormatter = function (type, value) {
|
|
97
95
|
type: Number,
|
98
96
|
value: 59,
|
99
97
|
observer: 'updateValue',
|
98
|
+
}, formatterMap: {
|
99
|
+
type: Object,
|
100
|
+
value: undefined,
|
100
101
|
} }),
|
101
102
|
data: {
|
102
103
|
innerValue: Date.now(),
|
@@ -129,10 +130,24 @@ var defaultFormatter = function (type, value) {
|
|
129
130
|
}
|
130
131
|
return this.picker;
|
131
132
|
},
|
133
|
+
formatterFunc: function (type, value) {
|
134
|
+
var _a;
|
135
|
+
var _b;
|
136
|
+
var _c = this.data, formatterMap = _c.formatterMap, _d = _c.formatter, formatter = _d === void 0 ? defaultFormatter : _d;
|
137
|
+
var mapDetail = formatterMap === null || formatterMap === void 0 ? void 0 : formatterMap[type];
|
138
|
+
if (typeof mapDetail === 'string') {
|
139
|
+
return (0, utils_1.replacePlaceholders)(mapDetail, (_a = {}, _a[type] = value, _a));
|
140
|
+
}
|
141
|
+
if (typeof mapDetail === 'object') {
|
142
|
+
return (_b = mapDetail[value]) !== null && _b !== void 0 ? _b : formatter(type, value);
|
143
|
+
}
|
144
|
+
return formatter(type, value);
|
145
|
+
},
|
132
146
|
updateColumns: function () {
|
133
|
-
var
|
147
|
+
var _this = this;
|
148
|
+
var locale = this.data.locale;
|
134
149
|
var results = this.getOriginColumns().map(function (column) { return ({
|
135
|
-
values: column.values.map(function (value) { return
|
150
|
+
values: column.values.map(function (value) { return _this.formatterFunc(column.type, value); }),
|
136
151
|
unit: locale === null || locale === void 0 ? void 0 : locale[column.type],
|
137
152
|
}); });
|
138
153
|
return this.set({ columns: results });
|
@@ -210,8 +225,8 @@ var defaultFormatter = function (type, value) {
|
|
210
225
|
// time type
|
211
226
|
if (!isDateType) {
|
212
227
|
var _a = value.split(':'), hour = _a[0], minute = _a[1];
|
213
|
-
hour = padZero(range(hour, data.minHour, data.maxHour));
|
214
|
-
minute = padZero(range(minute, data.minMinute, data.maxMinute));
|
228
|
+
hour = padZero((0, utils_1.range)(hour, data.minHour, data.maxHour));
|
229
|
+
minute = padZero((0, utils_1.range)(minute, data.minMinute, data.maxMinute));
|
215
230
|
return "".concat(hour, ":").concat(minute);
|
216
231
|
}
|
217
232
|
// date type
|
@@ -299,7 +314,7 @@ var defaultFormatter = function (type, value) {
|
|
299
314
|
var _this = this;
|
300
315
|
var values = [];
|
301
316
|
var type = this.data.type;
|
302
|
-
var formatter = this.
|
317
|
+
var formatter = this.formatterFunc;
|
303
318
|
var picker = this.getPicker();
|
304
319
|
if (type === 'time') {
|
305
320
|
var pair = value.split(':');
|
@@ -10,6 +10,7 @@
|
|
10
10
|
visible-item-count="{{ visibleItemCount }}"
|
11
11
|
confirm-button-text="{{ confirmButtonText }}"
|
12
12
|
cancel-button-text="{{ cancelButtonText }}"
|
13
|
+
change-animation="{{ changeAnimation }}"
|
13
14
|
bind:change="onChange"
|
14
15
|
bind:confirm="onConfirm"
|
15
16
|
bind:cancel="onCancel"
|
package/lib/icon/index.wxs
CHANGED
@@ -14,7 +14,7 @@ function rootClass(data) {
|
|
14
14
|
var classes = ['custom-class'];
|
15
15
|
|
16
16
|
if (data.classPrefix !== 'smart-icon') {
|
17
|
-
classes.push('smart-icon--custom')
|
17
|
+
classes.push('smart-icon--custom');
|
18
18
|
}
|
19
19
|
|
20
20
|
if (data.classPrefix != null) {
|
@@ -54,6 +54,8 @@ function svgStyle(data) {
|
|
54
54
|
{
|
55
55
|
'-webkit-mask-image': imageBase64Src,
|
56
56
|
'-webkit-mask-size': 'contain',
|
57
|
+
'-webkit-mask-repeat': 'no-repeat',
|
58
|
+
'-webkit-mask-position': 'center',
|
57
59
|
'mask-image': imageBase64Src,
|
58
60
|
'mask-size': 'contain',
|
59
61
|
width: data.size,
|
package/lib/picker/demo/index.js
CHANGED
@@ -51,6 +51,7 @@ var toast_1 = __importDefault(require("../../toast/toast"));
|
|
51
51
|
methods: {
|
52
52
|
onChange1: function (event) {
|
53
53
|
var _a = event.detail, value = _a.value, index = _a.index;
|
54
|
+
console.log("Value: ".concat(value, ", Index\uFF1A").concat(index));
|
54
55
|
(0, toast_1.default)({
|
55
56
|
context: this,
|
56
57
|
message: "Value: ".concat(value, ", Index\uFF1A").concat(index),
|
package/lib/picker/index.wxml
CHANGED
@@ -23,6 +23,7 @@
|
|
23
23
|
active-style="{{ activeStyle }}"
|
24
24
|
options="{{ item.values }}"
|
25
25
|
unit="{{ item.unit || unit }}"
|
26
|
+
changeAnimation="{{ changeAnimation }}"
|
26
27
|
default-index="{{ item.defaultIndex || defaultIndex }}"
|
27
28
|
active-index="{{ item.activeIndex || activeIndex }}"
|
28
29
|
item-height="{{ itemHeight }}"
|
package/lib/picker/shared.d.ts
CHANGED
package/lib/picker/shared.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
@import '../common/index.css';.smart-picker-column{color:var(--picker-option-selected-text-color,var(--app-B6-N1,#000));font-size:var(--picker-option-font-size,16px);font-weight:var(--font-weight-bold,500);position:relative;
|
1
|
+
@import '../common/index.css';.smart-picker-column{color:var(--picker-option-selected-text-color,var(--app-B6-N1,#000));font-size:var(--picker-option-font-size,16px);font-weight:var(--font-weight-bold,500);text-align:center}.smart-picker-column,.smart-picker-column__offset{position:relative;width:100%}.smart-picker-column__visual{position:absolute;top:0;width:100%}.smart-picker-column__item{pointer-events:none}.smart-picker-column__item--selected{color:var(--picker-option-selected-text-color,var(--app-B6-N1,#000));font-weight:var(--font-weight-bold,500)}.smart-picker-column__item--disabled{opacity:var(--picker-option-disabled-opacity,.3)}.smart-picker-column__mask{background:transparent;display:flex;flex-direction:column;height:100%;position:absolute;top:0;width:100%;z-index:10}.smart-picker-column__mask__item{flex:1}.smart-picker-column__unit{align-items:center;display:flex;justify-content:center;position:absolute;top:50%;transform:translateY(-50%);width:100%}.smart-picker-column__unit_text{color:var(--picker-option-unit-text-color,var(--app-B6-N4,rgba(0,0,0,.4)));font-size:var(--picker-option-unit-font-size,12px)}.smart-picker-column__unit_hidden{opacity:0}.smart-picker-column__max-text{font-weight:var(--font-weight-bold,500);opacity:0}
|
@@ -1,9 +1,54 @@
|
|
1
1
|
"use strict";
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
|
+
});
|
10
|
+
};
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
15
|
+
function step(op) {
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
20
|
+
switch (op[0]) {
|
21
|
+
case 0: case 1: t = op; break;
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
25
|
+
default:
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
30
|
+
if (t[2]) _.ops.pop();
|
31
|
+
_.trys.pop(); continue;
|
32
|
+
}
|
33
|
+
op = body.call(thisArg, _);
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
36
|
+
}
|
37
|
+
};
|
38
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
39
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
40
|
+
if (ar || !(i in from)) {
|
41
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
42
|
+
ar[i] = from[i];
|
43
|
+
}
|
44
|
+
}
|
45
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
46
|
+
};
|
2
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
48
|
var component_1 = require("../common/component");
|
4
49
|
var utils_1 = require("../common/utils");
|
5
50
|
var validator_1 = require("../common/validator");
|
6
|
-
var DEFAULT_DURATION =
|
51
|
+
var DEFAULT_DURATION = 400;
|
7
52
|
(0, component_1.SmartComponent)({
|
8
53
|
classes: ['active-class'],
|
9
54
|
props: {
|
@@ -27,11 +72,15 @@ var DEFAULT_DURATION = 200;
|
|
27
72
|
type: Number,
|
28
73
|
value: 0,
|
29
74
|
},
|
75
|
+
changeAnimation: {
|
76
|
+
type: Boolean,
|
77
|
+
value: true,
|
78
|
+
},
|
30
79
|
activeIndex: {
|
31
80
|
type: Number,
|
32
81
|
value: -1,
|
33
82
|
observer: function (index) {
|
34
|
-
this.setIndex(index, false,
|
83
|
+
this.setIndex(index, false, this.data.changeAnimation);
|
35
84
|
},
|
36
85
|
},
|
37
86
|
unit: {
|
@@ -50,57 +99,158 @@ var DEFAULT_DURATION = 200;
|
|
50
99
|
renderStart: 0,
|
51
100
|
animate: false,
|
52
101
|
maxText: '',
|
102
|
+
timer: null,
|
103
|
+
// animationIndex: -1,
|
104
|
+
preOffsetList: [],
|
53
105
|
},
|
54
106
|
created: function () {
|
55
107
|
var _a = this.data, defaultIndex = _a.defaultIndex, activeIndex = _a.activeIndex, options = _a.options;
|
56
108
|
this.updateUint(options);
|
57
|
-
this.setIndex(activeIndex !== -1 ? activeIndex : defaultIndex, false,
|
109
|
+
this.setIndex(activeIndex !== -1 ? activeIndex : defaultIndex, false, this.data.changeAnimation);
|
58
110
|
},
|
59
111
|
methods: {
|
60
112
|
getCount: function () {
|
61
113
|
return this.data.options.length;
|
62
114
|
},
|
63
115
|
onTouchStart: function (event) {
|
116
|
+
if (this.data.timer) {
|
117
|
+
clearTimeout(this.data.timer);
|
118
|
+
this.setData({
|
119
|
+
timer: null,
|
120
|
+
});
|
121
|
+
}
|
64
122
|
this.setData({
|
65
123
|
startY: event.touches[0].clientY,
|
66
124
|
startOffset: this.data.offset,
|
67
|
-
duration:
|
125
|
+
duration: 100,
|
126
|
+
timer: null,
|
127
|
+
preOffsetList: [this.data.offset],
|
68
128
|
});
|
69
129
|
},
|
70
130
|
onTouchMove: function (event) {
|
71
131
|
var data = this.data;
|
132
|
+
var preOffsetList = data.preOffsetList;
|
72
133
|
var deltaY = event.touches[0].clientY - data.startY;
|
134
|
+
var offset = (0, utils_1.range)(data.startOffset + deltaY, -(this.getCount() * data.itemHeight), data.itemHeight);
|
135
|
+
var direction = this.checkIsDown(offset);
|
136
|
+
// 上一次滚动的索引
|
137
|
+
var preIndex = (0, utils_1.range)(Math.round(-preOffsetList[preOffsetList.length - 1] / data.itemHeight), 0, this.getCount() - 1);
|
138
|
+
// 最终定位索引
|
139
|
+
var index = (0, utils_1.range)(Math.round(-offset / data.itemHeight), 0, this.getCount() - 1);
|
140
|
+
if ((direction === 'up' && index < data.renderStart + 8) ||
|
141
|
+
(direction === 'down' && index > data.renderStart + data.renderNum - 8)) {
|
142
|
+
this.updateVisibleOptions(index);
|
143
|
+
}
|
144
|
+
// 索引变化时 粗发震动反馈
|
145
|
+
if (index !== preIndex) {
|
146
|
+
// @ts-ignore
|
147
|
+
this.vibrateShort();
|
148
|
+
}
|
149
|
+
// const animationIndex = Math.abs(-offset / data.itemHeight);
|
73
150
|
this.setData({
|
74
|
-
offset:
|
151
|
+
offset: offset,
|
152
|
+
// animationIndex: animationIndex,
|
153
|
+
preOffsetList: __spreadArray(__spreadArray([], data.preOffsetList, true), [offset], false),
|
154
|
+
animate: false,
|
75
155
|
});
|
76
156
|
},
|
77
157
|
onTouchEnd: function () {
|
158
|
+
return __awaiter(this, void 0, void 0, function () {
|
159
|
+
var data, preOffsetList, preOffset, isSameTouch, direction, offset, countHeight, animationOffset, finOffset, index, offsetData, countVibrate;
|
160
|
+
var _this = this;
|
161
|
+
return __generator(this, function (_a) {
|
162
|
+
switch (_a.label) {
|
163
|
+
case 0:
|
164
|
+
data = this.data;
|
165
|
+
preOffsetList = data.preOffsetList;
|
166
|
+
preOffset = Math.max(Math.abs(preOffsetList[preOffsetList.length - 3] - preOffsetList[preOffsetList.length - 4]), Math.abs(preOffsetList[preOffsetList.length - 2] - preOffsetList[preOffsetList.length - 3]), Math.abs(preOffsetList[preOffsetList.length - 1] - preOffsetList[preOffsetList.length - 2]));
|
167
|
+
if (isNaN(preOffset))
|
168
|
+
preOffset = 0;
|
169
|
+
preOffset = Math.min(preOffset, 40);
|
170
|
+
isSameTouch = (preOffsetList[preOffsetList.length - 1] === preOffsetList[preOffsetList.length - 2] &&
|
171
|
+
preOffsetList[preOffsetList.length - 2] === preOffsetList[preOffsetList.length - 3]) ||
|
172
|
+
preOffsetList[preOffsetList.length - 1] === -(this.getCount() * data.itemHeight) ||
|
173
|
+
preOffsetList[preOffsetList.length - 1] === data.itemHeight;
|
174
|
+
direction = this.checkIsDown();
|
175
|
+
offset = Math.abs(preOffset) < 3 || isSameTouch || !direction
|
176
|
+
? data.offset
|
177
|
+
: data.offset + (direction === 'down' ? -preOffset : preOffset) * 10;
|
178
|
+
countHeight = (this.getCount() - 1) * data.itemHeight;
|
179
|
+
animationOffset = (0, utils_1.range)(offset, -(this.getCount() * data.itemHeight), data.itemHeight);
|
180
|
+
finOffset = animationOffset < -countHeight ? -countHeight : animationOffset > 0 ? 0 : animationOffset;
|
181
|
+
index = (0, utils_1.range)(Math.round(-finOffset / data.itemHeight), 0, this.getCount() - 1);
|
182
|
+
offsetData = -index * data.itemHeight;
|
183
|
+
// 增加惯性音效
|
184
|
+
if (Math.abs(offsetData - data.offset) > data.itemHeight && !isSameTouch) {
|
185
|
+
countVibrate = Math.abs(offsetData - data.offset) / data.itemHeight;
|
186
|
+
// @ts-ignore
|
187
|
+
this.vibrateShort(Math.floor(countVibrate), 800);
|
188
|
+
}
|
189
|
+
// 最终定位索引
|
190
|
+
this.setData({
|
191
|
+
duration: isSameTouch ? 150 : 800,
|
192
|
+
// animationIndex: index,
|
193
|
+
offset: offsetData,
|
194
|
+
animate: true,
|
195
|
+
});
|
196
|
+
if (!((direction === 'up' && index < data.renderStart + 8) ||
|
197
|
+
(direction === 'down' && index > data.renderStart + data.renderNum - 8))) return [3 /*break*/, 2];
|
198
|
+
return [4 /*yield*/, this.updateVisibleOptions(index)];
|
199
|
+
case 1:
|
200
|
+
_a.sent();
|
201
|
+
_a.label = 2;
|
202
|
+
case 2:
|
203
|
+
// 更新索引
|
204
|
+
if (index !== data.currentIndex) {
|
205
|
+
this.setData({
|
206
|
+
timer: setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
|
207
|
+
return __generator(this, function (_a) {
|
208
|
+
this.setIndex(index, true, false);
|
209
|
+
return [2 /*return*/];
|
210
|
+
});
|
211
|
+
}); }, isSameTouch ? 150 : 800),
|
212
|
+
});
|
213
|
+
}
|
214
|
+
return [2 /*return*/];
|
215
|
+
}
|
216
|
+
});
|
217
|
+
});
|
218
|
+
},
|
219
|
+
checkIsDown: function (curr) {
|
78
220
|
var data = this.data;
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
221
|
+
var preOffsetList = data.preOffsetList;
|
222
|
+
var currOffset = curr === undefined ? preOffsetList[preOffsetList.length - 1] : curr;
|
223
|
+
var preOffset = curr === undefined
|
224
|
+
? preOffsetList[preOffsetList.length - 2]
|
225
|
+
: preOffsetList[preOffsetList.length - 1];
|
226
|
+
if (currOffset === undefined || preOffset === undefined || currOffset === preOffset)
|
227
|
+
return;
|
228
|
+
return currOffset < preOffset ? 'down' : 'up';
|
83
229
|
},
|
84
|
-
|
85
|
-
var
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
renderStart = Math.max(0, currentIndex - renderNum / 2);
|
92
|
-
var optionsV = options.slice(renderStart, renderStart + renderNum);
|
93
|
-
this.setData({ optionsV: optionsV, renderStart: renderStart, renderNum: renderNum, animate: false });
|
94
|
-
}
|
95
|
-
else {
|
96
|
-
this.setData({ animate: false });
|
97
|
-
}
|
98
|
-
if (this.fireChange) {
|
99
|
-
this.$emit('change', currentIndex);
|
230
|
+
vibrateShort: function (count, time) {
|
231
|
+
var _this = this;
|
232
|
+
if (time === void 0) { time = 1000; }
|
233
|
+
if (!count) {
|
234
|
+
// @ts-ignore
|
235
|
+
ty.vibrateShort({ type: 'light' });
|
236
|
+
return;
|
100
237
|
}
|
238
|
+
var has = 0;
|
239
|
+
var timer = setInterval(function () {
|
240
|
+
if (has >= count) {
|
241
|
+
clearInterval(timer);
|
242
|
+
return;
|
243
|
+
}
|
244
|
+
has++;
|
245
|
+
_this.vibrateShort();
|
246
|
+
}, time / count - 20);
|
101
247
|
},
|
102
248
|
onClickItem: function (event) {
|
103
249
|
var index = event.currentTarget.dataset.index;
|
250
|
+
if (index === this.data.currentIndex || index < 0 || index > this.data.options.length - 1) {
|
251
|
+
return;
|
252
|
+
}
|
253
|
+
this.vibrateShort(Math.abs(index - this.data.currentIndex), DEFAULT_DURATION);
|
104
254
|
this.setIndex(index, true, true);
|
105
255
|
},
|
106
256
|
updateUint: function (options) {
|
@@ -122,7 +272,7 @@ var DEFAULT_DURATION = 200;
|
|
122
272
|
if (visibleItemCount < 20 && options.length > visibleItemCount) {
|
123
273
|
var renderNum = 0;
|
124
274
|
var renderStart = 0;
|
125
|
-
// 选项多于20个时,进行列表优化
|
275
|
+
// 选项多于 20 个时,进行列表优化
|
126
276
|
renderNum = Math.max(visibleItemCount * 2, 20);
|
127
277
|
renderStart = Math.max(0, targetIndex - renderNum / 2);
|
128
278
|
var renderEnd = Math.min(options.length, renderStart + renderNum);
|
@@ -161,36 +311,34 @@ var DEFAULT_DURATION = 200;
|
|
161
311
|
var data = this.data;
|
162
312
|
return (0, validator_1.isObj)(option) && data.valueKey in option ? option[data.valueKey] : option;
|
163
313
|
},
|
164
|
-
setIndex: function (index, userAction, animate) {
|
314
|
+
setIndex: function (index, userAction, animate, time) {
|
165
315
|
var _this = this;
|
316
|
+
if (time === void 0) { time = DEFAULT_DURATION; }
|
166
317
|
var data = this.data;
|
167
318
|
index = this.adjustIndex(index) || 0;
|
168
319
|
var offset = -index * data.itemHeight;
|
169
|
-
this.fireChange = false;
|
170
320
|
if (index !== data.currentIndex) {
|
171
321
|
// 需要动画的情况下,保持最大的截取
|
322
|
+
this.updateVisibleOptions(index);
|
172
323
|
if (animate) {
|
173
|
-
return this.
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
return;
|
185
|
-
}
|
186
|
-
_this.fireChange = true;
|
187
|
-
});
|
324
|
+
return this.set({
|
325
|
+
currentIndex: index,
|
326
|
+
// animationIndex: index,
|
327
|
+
offset: offset,
|
328
|
+
animate: true,
|
329
|
+
duration: time,
|
330
|
+
}).then(function () {
|
331
|
+
if (!userAction)
|
332
|
+
return;
|
333
|
+
console.log('change', index);
|
334
|
+
_this.$emit('change', index);
|
188
335
|
});
|
189
336
|
}
|
190
337
|
return this.set({
|
191
338
|
optionsV: data.options,
|
192
339
|
offset: offset,
|
193
340
|
currentIndex: index,
|
341
|
+
// animationIndex: index,
|
194
342
|
renderStart: 0,
|
195
343
|
animate: !!animate,
|
196
344
|
}).then(function () {
|
@@ -203,7 +351,7 @@ var DEFAULT_DURATION = 200;
|
|
203
351
|
var options = this.data.options;
|
204
352
|
for (var i = 0; i < options.length; i++) {
|
205
353
|
if (this.getOptionText(options[i]) === value) {
|
206
|
-
return this.setIndex(i, false,
|
354
|
+
return this.setIndex(i, false, this.data.changeAnimation);
|
207
355
|
}
|
208
356
|
}
|
209
357
|
return Promise.resolve();
|
@@ -9,18 +9,29 @@
|
|
9
9
|
bind:touchend="onTouchEnd"
|
10
10
|
bind:touchcancel="onTouchEnd"
|
11
11
|
>
|
12
|
-
<view style="{{ computed.wrapperStyle({ offset, itemHeight, visibleItemCount, animate, duration, renderStart, unit }) }}"
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
<view class="smart-picker-column__offset" style="height: {{ itemHeight * options.length }}px;{{ computed.wrapperStyle({ offset, itemHeight, visibleItemCount, animate, duration, renderStart, unit }) }}" id="options">
|
13
|
+
<view class="smart-picker-column__visual" style="{{ computed.wrapperInterStyle({ offset, itemHeight, visibleItemCount, renderStart }) }}">
|
14
|
+
<view
|
15
|
+
wx:for="{{ optionsV }}"
|
16
|
+
wx:for-item="option"
|
17
|
+
wx:key="index"
|
18
|
+
data-index="{{ renderStart + index }}"
|
19
|
+
style="height: {{ itemHeight }}px;{{renderStart + index === currentIndex ? activeStyle : ''}}"
|
20
|
+
class="smart-ellipsis {{ utils.bem('picker-column__item', { disabled: option && option.disabled, selected: renderStart + index === currentIndex }) }} {{ renderStart + index === currentIndex ? 'active-class' : '' }}"
|
21
|
+
>
|
22
|
+
{{ computed.optionText(option, valueKey) }}
|
23
|
+
</view>
|
24
|
+
</view>
|
25
|
+
</view>
|
26
|
+
<view class="smart-picker-column__mask">
|
27
|
+
<view
|
28
|
+
wx:for="{{ visibleItemCount }}"
|
18
29
|
wx:key="index"
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
30
|
+
class="smart-picker-column__mask__item"
|
31
|
+
data-index="{{ currentIndex + index - 2 }}"
|
32
|
+
bind:tap="onClickItem"
|
33
|
+
>
|
34
|
+
</view>
|
24
35
|
</view>
|
25
36
|
<view wx:if="{{unit}}" class="smart-picker-column__unit" style="height: {{ itemHeight }}px">
|
26
37
|
<view class="smart-picker-column__unit_text smart-picker-column__unit_hidden" >{{unit}}</view>
|
@@ -20,15 +20,11 @@ function rootStyle(data) {
|
|
20
20
|
function wrapperStyle(data) {
|
21
21
|
var offset =
|
22
22
|
data.offset + (data.itemHeight * (data.visibleItemCount - 1)) / 2;
|
23
|
-
// 长列表优化
|
24
|
-
if (data.renderStart) {
|
25
|
-
offset += data.renderStart * data.itemHeight;
|
26
|
-
}
|
27
23
|
offset = addUnit(offset);
|
28
24
|
if (data.animate) {
|
29
25
|
return style({
|
30
26
|
'text-indent': data.unit ? '-8rpx' : '0',
|
31
|
-
transition: 'transform ' + data.duration + 'ms',
|
27
|
+
transition: 'transform ' + data.duration + 'ms ease-out',
|
32
28
|
'line-height': addUnit(data.itemHeight),
|
33
29
|
transform: 'translate3d(0, ' + offset + ', 0)',
|
34
30
|
});
|
@@ -40,8 +36,29 @@ function wrapperStyle(data) {
|
|
40
36
|
});
|
41
37
|
}
|
42
38
|
|
39
|
+
function wrapperInterStyle(data) {
|
40
|
+
var offset = data.renderStart * data.itemHeight;
|
41
|
+
offset = addUnit(offset);
|
42
|
+
return style({
|
43
|
+
'padding-top': offset,
|
44
|
+
});
|
45
|
+
}
|
46
|
+
|
47
|
+
// function wrapperItemStyle(data) {
|
48
|
+
// const { index, animationIndex: currentIndex } = data;
|
49
|
+
// const offsetIndex = currentIndex - index;
|
50
|
+
// const rotateX = offsetIndex * 25 > 0 ? Math.min(offsetIndex * 25, 25 * 2) : Math.max(offsetIndex * 25, -25 * 2)
|
51
|
+
// const scale = Math.min(Math.abs(offsetIndex * 0.05), 0.05 * 2)
|
52
|
+
// return style({
|
53
|
+
// transition: 'transform ' + data.duration + 'ms ease-out',
|
54
|
+
// transform: `rotateX(${rotateX}deg) scale(${1 - scale})`
|
55
|
+
// });
|
56
|
+
// }
|
57
|
+
|
43
58
|
module.exports = {
|
44
59
|
optionText: optionText,
|
45
60
|
rootStyle: rootStyle,
|
46
61
|
wrapperStyle: wrapperStyle,
|
62
|
+
wrapperInterStyle: wrapperInterStyle,
|
63
|
+
// wrapperItemStyle: wrapperItemStyle
|
47
64
|
};
|
@@ -1 +1 @@
|
|
1
|
-
@import '../common/index.wxss';.smart-picker-column{color:var(--picker-option-selected-text-color,var(--app-B6-N1,#000));font-size:var(--picker-option-font-size,16px);font-weight:var(--font-weight-bold,500);position:relative;
|
1
|
+
@import '../common/index.wxss';.smart-picker-column{color:var(--picker-option-selected-text-color,var(--app-B6-N1,#000));font-size:var(--picker-option-font-size,16px);font-weight:var(--font-weight-bold,500);text-align:center}.smart-picker-column,.smart-picker-column__offset{position:relative;width:100%}.smart-picker-column__visual{position:absolute;top:0;width:100%}.smart-picker-column__item{pointer-events:none}.smart-picker-column__item--selected{color:var(--picker-option-selected-text-color,var(--app-B6-N1,#000));font-weight:var(--font-weight-bold,500)}.smart-picker-column__item--disabled{opacity:var(--picker-option-disabled-opacity,.3)}.smart-picker-column__mask{background:transparent;display:flex;flex-direction:column;height:100%;position:absolute;top:0;width:100%;z-index:10}.smart-picker-column__mask__item{flex:1}.smart-picker-column__unit{align-items:center;display:flex;justify-content:center;position:absolute;top:50%;transform:translateY(-50%);width:100%}.smart-picker-column__unit_text{color:var(--picker-option-unit-text-color,var(--app-B6-N4,rgba(0,0,0,.4)));font-size:var(--picker-option-unit-font-size,12px)}.smart-picker-column__unit_hidden{opacity:0}.smart-picker-column__max-text{font-weight:var(--font-weight-bold,500);opacity:0}
|
package/package.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "@tuya-miniapp/smart-ui",
|
3
|
-
"version": "2.1.
|
3
|
+
"version": "2.1.11-beta-1",
|
4
4
|
"author": "MiniApp Team",
|
5
5
|
"license": "MIT",
|
6
6
|
"miniprogram": "lib",
|
7
7
|
"description": "轻量、可靠的智能小程序 UI 组件库",
|
8
8
|
"scripts": {
|
9
|
-
"prepublishOnly": "node ./build/
|
9
|
+
"prepublishOnly": "node ./build/prepublishOnly.js",
|
10
10
|
"dev": "NODE_OPTIONS=--no-experimental-fetch node build/dev.mjs",
|
11
11
|
"lint": "eslint ./packages --ext .js,.ts --fix",
|
12
12
|
"lint:style": "stylelint \"packages/**/*.less\" --fix",
|
@@ -78,7 +78,7 @@
|
|
78
78
|
"iOS >= 9"
|
79
79
|
],
|
80
80
|
"dependencies": {
|
81
|
-
"@ray-js/components-ty-slider": "^0.
|
81
|
+
"@ray-js/components-ty-slider": "^0.3.1",
|
82
82
|
"@tuya-miniapp/icons": "^2.1.7"
|
83
83
|
},
|
84
84
|
"maintainers": [
|