Skip to content

Commit 2827c67

Browse files
fix(picker): fix custom height problem (#1576)
* fix(picker): fix custom height problem deleted unexpected reset of itemHeight in initScrollParams(), changed the positioning of the indicator to a dynamic value based on --td-picker-item-height; Added a demo of using custom height fix #1207 * chore: update common * chore: update snapshot * fix(picker): auto mediate indicator * chore: update common --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent c5d5d2d commit 2827c67

File tree

5 files changed

+132
-10
lines changed

5 files changed

+132
-10
lines changed

src/picker/__test__/__snapshots__/demo.test.jsx.snap

+41
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,47 @@ exports[`Picker > Picker mobileVue demo works fine 1`] = `
13711371
</teleport-stub>
13721372
13731373
1374+
<div
1375+
class="t-cell t-cell--middle"
1376+
>
1377+
<div
1378+
class="t-cell__left"
1379+
>
1380+
<!---->
1381+
<!---->
1382+
</div>
1383+
<div
1384+
class="t-cell__title"
1385+
>
1386+
自定义高度选择器
1387+
<!---->
1388+
<!---->
1389+
</div>
1390+
<!---->
1391+
<div
1392+
class="t-cell__right"
1393+
>
1394+
<div
1395+
class="t-cell__right-icon"
1396+
>
1397+
<svg
1398+
class="t-icon t-icon-chevron-right"
1399+
fill="none"
1400+
height="1em"
1401+
viewBox="0 0 24 24"
1402+
width="1em"
1403+
>
1404+
<path
1405+
d="M8.09 17.5l5.5-5.5-5.5-5.5L9.5 5.09 16.41 12 9.5 18.91 8.09 17.5z"
1406+
fill="currentColor"
1407+
/>
1408+
</svg>
1409+
</div>
1410+
</div>
1411+
</div>
1412+
<!--v-if-->
1413+
1414+
13741415
</div>
13751416
</div>
13761417
</div>

src/picker/demos/customHeight.vue

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<script setup lang="ts">
2+
import { reactive } from 'vue';
3+
import { PickerValue } from 'tdesign-mobile-vue';
4+
5+
const cityOptions = () => {
6+
return [
7+
{
8+
label: '北京市',
9+
value: '北京市',
10+
},
11+
{
12+
label: '上海市',
13+
value: '上海市',
14+
},
15+
{
16+
label: '广州市',
17+
value: '广州市',
18+
},
19+
{
20+
label: '深圳市',
21+
value: '深圳市',
22+
},
23+
{
24+
label: '杭州市',
25+
value: '杭州市',
26+
},
27+
{
28+
label: '成都市',
29+
value: '成都市',
30+
},
31+
{
32+
label: '长沙市',
33+
value: '长沙市',
34+
},
35+
];
36+
};
37+
38+
const cityState = reactive({
39+
show: false,
40+
city: [],
41+
});
42+
43+
const onConfirm = (val: string[], context: number[]) => {
44+
console.log(val);
45+
console.log('context', context);
46+
cityState.show = false;
47+
};
48+
49+
const onPick = (value: PickerValue[], context: any) => {
50+
console.log('value', value);
51+
console.log('context', context);
52+
};
53+
</script>
54+
55+
<template>
56+
<t-cell arrow title="自定义高度选择器" :note="cityState.city.join(' ')" @click="cityState.show = true" />
57+
<t-popup v-if="cityState.show" v-model="cityState.show" class="picker-custom-height-demo" placement="bottom">
58+
<t-picker
59+
v-model="cityState.city"
60+
:columns="cityOptions"
61+
@confirm="onConfirm"
62+
@cancel="cityState.show = false"
63+
@pick="onPick"
64+
/>
65+
</t-popup>
66+
</template>
67+
68+
<style lang="less">
69+
.picker-custom-height-demo {
70+
--td-picker-item-height: 80px;
71+
--td-picker-group-height: 400px;
72+
}
73+
</style>

src/picker/demos/mobile.vue

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<tdesign-demo-block title="02 组件样式">
1010
<!-- <CasCadeDemo /> -->
1111
<titleDemo />
12+
<CustomHeightDemo />
1213
</tdesign-demo-block>
1314
</div>
1415
</template>
@@ -17,4 +18,5 @@ import BaseDemo from './base.vue';
1718
// import CasCadeDemo from './cascade.vue';
1819
import titleDemo from './title.vue';
1920
import AreaDemo from './area.vue';
21+
import CustomHeightDemo from './customHeight.vue';
2022
</script>

src/picker/picker.class.ts

+15-9
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ class Picker {
7373

7474
onChange: (index: number) => void;
7575

76+
itemGroupHeight: number;
77+
78+
indicatorOffset: number;
79+
7680
constructor(options: PickerOptions) {
7781
if (!options.el) throw new Error('options el needed!');
7882
this.holder = options.el;
@@ -105,13 +109,14 @@ class Picker {
105109
*/
106110
initScrollParams(): void {
107111
this.list = this.holder as HTMLUListElement;
112+
this.itemGroupHeight = this.holder.parentElement?.offsetHeight || DEFAULT_HOLDER_HEIGHT;
108113
this.elementItems = [...this.holder.querySelectorAll('li')];
109114
this.itemHeight = this.holder.querySelector('li')?.offsetHeight || DEFAULT_ITEM_HEIGHT;
110115
this.height = this.holder.offsetHeight || DEFAULT_HOLDER_HEIGHT;
116+
this.indicatorOffset = this.itemGroupHeight / 2 - this.itemHeight / 2;
111117
let curIndex = this.options.defaultIndex || 0;
112118
this.itemClassName = `${prefix}-picker-item__item`;
113119
this.itemSelectedClassName = `${prefix}-picker-item__item--active`;
114-
this.itemHeight = DEFAULT_ITEM_HEIGHT;
115120
this.startY = 0;
116121
this.isPicking = false;
117122
this.lastMoveTime = 0;
@@ -127,13 +132,14 @@ class Picker {
127132
return curIndex;
128133
},
129134
});
130-
const startOffsetY = (-this.curIndex + 2) * this.itemHeight;
135+
136+
const startOffsetY = this.indicatorOffset - this.curIndex * this.itemHeight;
131137
const itemLen = this.elementItems.length;
132138
this.setOffsetY(startOffsetY);
133139
this.offsetYOfStart = startOffsetY;
134-
this.offsetYOfEnd = -this.itemHeight * (itemLen - 3);
135-
this.offsetYOfStartBound = this.itemHeight * 2 + OFFSET_OF_BOUND;
136-
this.offsetYOfEndBound = -(this.itemHeight * (itemLen - 3) + OFFSET_OF_BOUND);
140+
this.offsetYOfEnd = this.indicatorOffset - (itemLen - 1) * this.itemHeight;
141+
this.offsetYOfStartBound = this.indicatorOffset + OFFSET_OF_BOUND;
142+
this.offsetYOfEndBound = this.indicatorOffset - (itemLen - 1) * this.itemHeight - OFFSET_OF_BOUND;
137143
}
138144

139145
bindEvent(): void {
@@ -159,7 +165,7 @@ class Picker {
159165
const endY = event.changedTouches[0].pageY;
160166
const dragRange = endY - this.startY;
161167
this.updateInertiaParams(event, false);
162-
const moveOffsetY = (-this.curIndex + 2) * this.itemHeight + dragRange;
168+
const moveOffsetY = this.indicatorOffset - this.curIndex * this.itemHeight + dragRange;
163169
this.setOffsetY(moveOffsetY);
164170
}
165171

@@ -263,7 +269,7 @@ class Picker {
263269
};
264270
this.curIndex = index;
265271
this.setSelectedClassName();
266-
const moveOffsetY = (-index + 2) * this.itemHeight;
272+
const moveOffsetY = this.indicatorOffset - index * this.itemHeight;
267273
if (this.list) {
268274
this.list.style.transform = `translate(0,${moveOffsetY}px) translateZ(0)`;
269275
this.list.style.transitionDuration = `${realOptions.duration}ms`;
@@ -347,11 +353,11 @@ class Picker {
347353
if (this.list) {
348354
this.list.style.transition = `${ANIMATION_DURATION}ms ease-out`;
349355
}
350-
curIndex = 2 - Math.round(this.offsetY / this.itemHeight);
356+
curIndex = -Math.round((this.offsetY - this.indicatorOffset) / this.itemHeight);
351357
if (curIndex < 0) curIndex = 0;
352358
if (curIndex > this.elementItems.length - 1) curIndex = this.elementItems.length - 1;
353359
}
354-
const offsetY = (-curIndex + 2) * this.itemHeight;
360+
const offsetY = this.indicatorOffset - curIndex * this.itemHeight;
355361
this.setOffsetY(offsetY);
356362
if (curIndex !== this.curIndex) {
357363
// 防止事件重复触发

0 commit comments

Comments
 (0)