Skip to content

Commit a48aedb

Browse files
committed
feat(Swiper): support cardScale API
1 parent 820ec18 commit a48aedb

File tree

11 files changed

+685
-598
lines changed

11 files changed

+685
-598
lines changed

src/swiper/__tests__/__snapshots__/index.test.jsx.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ exports[`Swiper > :props > :navigation 1`] = `
200200
exports[`Swiper > :props > :theme 1`] = `
201201
<div
202202
class="t-swiper"
203+
theme="dark"
203204
>
204205
<div
205206
class="t-swiper__wrap t-swiper--inside"

src/swiper/_example/card.vue

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,33 @@
11
<template>
22
<div class="tdesign-demo-block--swiper">
3-
<t-swiper type="card" :height="280">
4-
<t-swiper-item>
5-
<div class="demo-item">1</div>
6-
</t-swiper-item>
7-
<t-swiper-item>
8-
<div class="demo-item">2</div>
9-
</t-swiper-item>
10-
<t-swiper-item>
11-
<div class="demo-item">3</div>
12-
</t-swiper-item>
13-
<t-swiper-item>
14-
<div class="demo-item">4</div>
15-
</t-swiper-item>
16-
<t-swiper-item>
17-
<div class="demo-item">5</div>
18-
</t-swiper-item>
19-
<t-swiper-item>
20-
<div class="demo-item">6</div>
21-
</t-swiper-item>
22-
</t-swiper>
3+
<t-space direction="vertical" :size="50" style="width: 100%">
4+
<t-space direction="vertical" style="width: 100%">
5+
<t-tag theme="primary" variant="outline">卡片缩放比例</t-tag>
6+
7+
<t-slider v-model="cardScale" :min="0" :max="1" :step="0.01" :marks="marks" />
8+
</t-space>
9+
10+
<t-swiper type="card" :height="280" :autoplay="false" :card-scale="cardScale">
11+
<t-swiper-item v-for="i in 6" :key="i">
12+
<div class="demo-item">{{ i }}</div>
13+
</t-swiper-item>
14+
</t-swiper>
15+
</t-space>
2316
</div>
2417
</template>
18+
19+
<script>
20+
export default {
21+
data() {
22+
const DEFAULT_SCALE = 210 / 332;
23+
24+
return {
25+
cardScale: DEFAULT_SCALE,
26+
DEFAULT_SCALE,
27+
marks: {
28+
[DEFAULT_SCALE]: 'Default',
29+
},
30+
};
31+
},
32+
};
33+
</script>

src/swiper/_usage/props.json

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,6 @@
4747
"defaultValue": true,
4848
"options": []
4949
},
50-
{
51-
"name": "theme",
52-
"type": "enum",
53-
"defaultValue": "light",
54-
"options": [
55-
{
56-
"label": "light",
57-
"value": "light"
58-
},
59-
{
60-
"label": "dark",
61-
"value": "dark"
62-
}
63-
]
64-
},
6550
{
6651
"name": "trigger",
6752
"type": "enum",

src/swiper/props.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ export default {
2222
type: Boolean,
2323
default: true,
2424
},
25+
/** 卡片模式下非当前展示轮播图的缩放比例 */
26+
cardScale: {
27+
type: Number,
28+
default: 210 / 332,
29+
},
2530
/** 当前轮播在哪一项(下标) */
2631
current: {
2732
type: Number,
@@ -69,15 +74,6 @@ export default {
6974
type: Boolean,
7075
default: true,
7176
},
72-
/** 深色模式和浅色模式 */
73-
theme: {
74-
type: String as PropType<TdSwiperProps['theme']>,
75-
default: 'light' as TdSwiperProps['theme'],
76-
validator(val: TdSwiperProps['theme']): boolean {
77-
if (!val) return true;
78-
return ['light', 'dark'].includes(val);
79-
},
80-
},
8177
/** 触发切换的方式:悬浮、点击等 */
8278
trigger: {
8379
type: String as PropType<TdSwiperProps['trigger']>,

src/swiper/swiper-item.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
import { VNode } from 'vue';
2-
import props from './props';
32
import { getClassPrefixMixins } from '../config-provider/config-receiver';
43
import mixins from '../utils/mixins';
4+
import props from './props';
55

66
const classPrefixMixins = getClassPrefixMixins('swiper');
77

8+
const CARD_SCALE = 210 / 332; // 缩放比例
9+
const ITEM_WIDTH = 0.415; // 依据设计稿使用t-swiper__card控制每个swiper的宽度为41.5%
10+
811
const swiperItemProps = {
912
index: {
1013
type: Number,
1114
},
1215
currentIndex: {
1316
type: Number,
1417
},
18+
cardScale: {
19+
type: Number,
20+
default: CARD_SCALE,
21+
},
1522
isSwitching: {
1623
type: Boolean,
1724
default: false,
@@ -24,8 +31,6 @@ const swiperItemProps = {
2431
default: 0,
2532
},
2633
};
27-
const CARD_SCALE = 210 / 332; // 缩放比例
28-
const itemWidth = 0.415; // 依据设计稿使用t-swiper__card控制每个swiper的宽度为41.5%
2934

3035
export default mixins(classPrefixMixins).extend({
3136
name: 'TSwiperItem',
@@ -62,12 +67,14 @@ export default mixins(classPrefixMixins).extend({
6267
const translateIndex = !this.active && this.swiperItemLength > 2 ? this.disposeIndex : this.index;
6368
const inStage = Math.abs(translateIndex - this.currentIndex) <= 1;
6469
if (inStage) {
65-
return (wrapWidth * ((translateIndex - this.currentIndex) * (1 - itemWidth * CARD_SCALE) - itemWidth + 1)) / 2;
70+
return (
71+
(wrapWidth * ((translateIndex - this.currentIndex) * (1 - ITEM_WIDTH * this.cardScale) - ITEM_WIDTH + 1)) / 2
72+
);
6673
}
6774
if (translateIndex < this.currentIndex) {
68-
return (-itemWidth * (1 + CARD_SCALE) * wrapWidth) / 2;
75+
return (-ITEM_WIDTH * (1 + this.cardScale) * wrapWidth) / 2;
6976
}
70-
return ((2 + itemWidth * (CARD_SCALE - 1)) * wrapWidth) / 2;
77+
return ((2 + ITEM_WIDTH * (this.cardScale - 1)) * wrapWidth) / 2;
7178
},
7279
zIndex(): number {
7380
if (this.type !== 'card') return 0;
@@ -94,7 +101,7 @@ export default mixins(classPrefixMixins).extend({
94101
const translateIndex = !this.active && this.swiperItemLength > 2 ? this.disposeIndex : this.index;
95102
const isActivity = translateIndex === this.currentIndex;
96103
return {
97-
transform: `translateX(${this.translateX}px) scale(${isActivity ? 1 : CARD_SCALE})`,
104+
transform: `translateX(${this.translateX}px) scale(${isActivity ? 1 : this.cardScale})`,
98105
transition: `transform ${this.duration / 1000}s ease`,
99106
zIndex: this.zIndex,
100107
};

src/swiper/swiper.en-US.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
:: BASE_DOC ::
22

33
## API
4+
45
### Swiper Props
56

67
name | type | default | description | required
78
-- | -- | -- | -- | --
8-
animation | String | slide | optionsslide/fade | N
9+
animation | String | slide | options: slide/fade | N
910
autoplay | Boolean | true | \- | N
11+
cardScale | Number | 210/332 | \- | N
1012
current | Number | 0 | `v-model` is supported | N
1113
defaultCurrent | Number | 0 | uncontrolled property | N
12-
direction | String | horizontal | optionshorizontal/vertical | N
14+
direction | String | horizontal | options: horizontal/vertical | N
1315
duration | Number | 300 | \- | N
1416
height | Number | - | \- | N
1517
interval | Number | 5000 | \- | N
1618
loop | Boolean | true | \- | N
17-
navigation | Object / Slot / Function | - | Typescript`SwiperNavigation \| TNode`[see more ts definition](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
19+
navigation | Object / Slot / Function | - | Typescript: `SwiperNavigation \| TNode`[see more ts definition](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
1820
stopOnHover | Boolean | true | \- | N
19-
theme | String | light | options:light/dark | N
20-
trigger | String | hover | options:hover/click | N
21-
type | String | default | options:default/card | N
22-
onChange | Function | | Typescript:`(current: number, context: { source: SwiperChangeSource }) => void`<br/>[see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/swiper/type.ts)。<br/>`type SwiperChangeSource = 'autoplay' \| 'click' \| 'hover'`<br/> | N
21+
trigger | String | hover | options: hover/click | N
22+
type | String | default | options: default/card | N
23+
onChange | Function | | Typescript: `(current: number, context: { source: SwiperChangeSource }) => void`<br/>[see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/swiper/type.ts)。<br/>`type SwiperChangeSource = 'autoplay' \| 'click' \| 'hover'`<br/> | N
2324

2425
### Swiper Events
2526

@@ -31,7 +32,7 @@ change | `(current: number, context: { source: SwiperChangeSource })` | [see mor
3132

3233
name | type | default | description | required
3334
-- | -- | -- | -- | --
34-
placement | String | inside | optionsinside/outside | N
35-
showSlideBtn | String | always | optionsalways/hover/never | N
36-
size | String | medium | optionssmall/medium/large | N
37-
type | String | - | Typescript`SwiperNavigationType` `type SwiperNavigationType = 'dots' \| 'dots-bar' \| 'bars' \| 'fraction'`[see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/swiper/type.ts) | N
35+
placement | String | inside | options: inside/outside | N
36+
showSlideBtn | String | always | options: always/hover/never | N
37+
size | String | medium | options: small/medium/large | N
38+
type | String | - | Typescript: `SwiperNavigationType` `type SwiperNavigationType = 'dots' \| 'dots-bar' \| 'bars' \| 'fraction'`[see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/swiper/type.ts) | N

src/swiper/swiper.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
:: BASE_DOC ::
22

33
## API
4+
45
### Swiper Props
56

6-
名称 | 类型 | 默认值 | 说明 | 必传
7+
名称 | 类型 | 默认值 | 描述 | 必传
78
-- | -- | -- | -- | --
89
animation | String | slide | 轮播切换动画效果类型:滑动、淡入淡出等。可选项:slide/fade | N
910
autoplay | Boolean | true | 是否自动播放 | N
11+
cardScale | Number | 210/332 | 卡片模式下非当前展示轮播图的缩放比例 | N
1012
current | Number | 0 | 当前轮播在哪一项(下标)。支持语法糖 `v-model` | N
1113
defaultCurrent | Number | 0 | 当前轮播在哪一项(下标)。非受控属性 | N
1214
direction | String | horizontal | 轮播滑动方向,包括横向滑动和纵向滑动两个方向。可选项:horizontal/vertical | N
@@ -16,7 +18,6 @@ interval | Number | 5000 | 轮播间隔时间 | N
1618
loop | Boolean | true | 是否循环播放 | N
1719
navigation | Object / Slot / Function | - | 导航器全部配置。TS 类型:`SwiperNavigation \| TNode`[通用类型定义](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
1820
stopOnHover | Boolean | true | 是否悬浮时停止轮播 | N
19-
theme | String | light | 深色模式和浅色模式。可选项:light/dark | N
2021
trigger | String | hover | 触发切换的方式:悬浮、点击等。可选项:hover/click | N
2122
type | String | default | 样式类型:默认样式、卡片样式。可选项:default/card | N
2223
onChange | Function | | TS 类型:`(current: number, context: { source: SwiperChangeSource }) => void`<br/>轮播切换时触发。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/swiper/type.ts)。<br/>`type SwiperChangeSource = 'autoplay' \| 'click' \| 'hover'`<br/> | N
@@ -29,7 +30,7 @@ change | `(current: number, context: { source: SwiperChangeSource })` | 轮播
2930

3031
### SwiperNavigation
3132

32-
名称 | 类型 | 默认值 | 说明 | 必传
33+
名称 | 类型 | 默认值 | 描述 | 必传
3334
-- | -- | -- | -- | --
3435
placement | String | inside | 导航器位置,位于主体的内侧或是外侧。可选项:inside/outside | N
3536
showSlideBtn | String | always | 何时显示导航器的翻页按钮:始终显示、悬浮显示、永不显示。可选项:always/hover/never | N

src/swiper/swiper.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ import Vue, { VNode, VNodeComponentOptions, VueConstructor } from 'vue';
22
import { ChevronLeftIcon as TdChevronLeftIcon, ChevronRightIcon as TdChevronRightIcon } from 'tdesign-icons-vue';
33
import { kebabCase } from 'lodash-es';
44

5-
import props from './props';
6-
import { TdSwiperProps, SwiperNavigation, SwiperChangeSource } from './type';
7-
import TSwiperItem from './swiper-item';
5+
import { getClassPrefixMixins, getGlobalIconMixins } from '../config-provider/config-receiver';
86
import { isVNode } from '../hooks/render-tnode';
9-
import { renderTNodeJSX } from '../utils/render-tnode';
107
import { emitEvent } from '../utils/event';
11-
import { getClassPrefixMixins, getGlobalIconMixins } from '../config-provider/config-receiver';
128
import mixins from '../utils/mixins';
9+
import { renderTNodeJSX } from '../utils/render-tnode';
10+
import props from './props';
11+
import TSwiperItem from './swiper-item';
12+
13+
import type { SwiperChangeSource, SwiperNavigation, TdSwiperProps } from './type';
1314

1415
const classPrefixMixins = getClassPrefixMixins('swiper');
1516

@@ -105,6 +106,7 @@ export default mixins(Vue as VueConstructor<SwiperVue>, classPrefixMixins, getGl
105106
index={index}
106107
currentIndex={this.currentIndex}
107108
isSwitching={this.isSwitching}
109+
cardScale={this.cardScale}
108110
getWrapAttribute={this.getWrapAttribute}
109111
swiperItemLength={this.swiperItemLength}
110112
props={{ ...this.$props, ...swiperItem.propsData }}
@@ -225,7 +227,8 @@ export default mixins(Vue as VueConstructor<SwiperVue>, classPrefixMixins, getGl
225227
return this.swiperTo(this.currentIndex - 1, context);
226228
},
227229
getWrapAttribute(attr: string) {
228-
return (this.$refs.swiperWrap as Element)?.parentNode?.[attr];
230+
const parent = (this.$refs.swiperWrap as Element)?.parentNode as HTMLElement;
231+
return parent?.[attr as keyof HTMLElement];
229232
},
230233
renderPagination() {
231234
const fractionIndex = this.currentIndex + 1 > this.swiperItemLength ? 1 : this.currentIndex + 1;

src/swiper/type.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ export interface TdSwiperProps {
1717
* @default true
1818
*/
1919
autoplay?: boolean;
20+
/**
21+
* 卡片模式下非当前展示轮播图的缩放比例
22+
* @default 210/332
23+
*/
24+
cardScale?: number;
2025
/**
2126
* 当前轮播在哪一项(下标)
2227
* @default 0
@@ -60,11 +65,6 @@ export interface TdSwiperProps {
6065
* @default true
6166
*/
6267
stopOnHover?: boolean;
63-
/**
64-
* 深色模式和浅色模式
65-
* @default light
66-
*/
67-
theme?: 'light' | 'dark';
6868
/**
6969
* 触发切换的方式:悬浮、点击等
7070
* @default hover

0 commit comments

Comments
 (0)