diff --git a/docs/demos/views/swipe.vue b/docs/demos/views/swipe.vue
index 9b5e43ea8..4de4c80e3 100644
--- a/docs/demos/views/swipe.vue
+++ b/docs/demos/views/swipe.vue
@@ -25,6 +25,15 @@
4
+
+
+
+ 1
+ 2
+ 3
+ 4
+
+
@@ -34,11 +43,13 @@ export default {
'zh-CN': {
title2: '图片懒加载',
title3: '监听 change 事件',
+ title4: '纵向滚动',
message: '当前 Swipe 索引:'
},
'en-US': {
title2: 'Image Lazyload',
title3: 'Change Event',
+ title4: 'Vertical Scrolling',
message: 'Current Swipe index:'
}
},
@@ -68,6 +79,7 @@ export default {
.van-swipe {
cursor: pointer;
+ height: 140px;
&-item {
color: #fff;
diff --git a/docs/markdown/en-US/swipe.md b/docs/markdown/en-US/swipe.md
index 394a182a5..2a49c2a08 100644
--- a/docs/markdown/en-US/swipe.md
+++ b/docs/markdown/en-US/swipe.md
@@ -66,6 +66,17 @@ export default {
}
```
+#### Vertical Scrolling
+
+```html
+
+ 1
+ 2
+ 3
+ 4
+
+```
+
### API
| Attribute | Description | Type | Default | Accepted Values |
@@ -75,6 +86,7 @@ export default {
| loop | Whether to enable loop | `Boolean` | `true` | - |
| show-indicators | Whether to show indocators | `Boolean` | `true` | - |
| initial-swipe | Index of initial swipe, start from 0 | `Number` | `0` | - |
+| vertical | Vertical Scrolling | `Boolean` | `false` | - |
### Event
diff --git a/docs/markdown/zh-CN/swipe.md b/docs/markdown/zh-CN/swipe.md
index 28b1a40a5..99c2ed738 100644
--- a/docs/markdown/zh-CN/swipe.md
+++ b/docs/markdown/zh-CN/swipe.md
@@ -66,6 +66,17 @@ export default {
}
```
+#### 纵向滚动
+
+```html
+
+ 1
+ 2
+ 3
+ 4
+
+```
+
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
@@ -75,6 +86,7 @@ export default {
| loop | 是否开启循环播放 | `Boolean` | `true` | - |
| show-indicators | 是否显示指示器 | `Boolean` | `true` | - |
| initial-swipe | 初始位置,从 0 开始算 | `Number` | `0` | - |
+| vertical | 纵向滚动 | `Boolean` | `false` | - |
### 事件
diff --git a/docs/src/doc.config.js b/docs/src/doc.config.js
index 3b3282a1e..4154a7e0b 100644
--- a/docs/src/doc.config.js
+++ b/docs/src/doc.config.js
@@ -138,7 +138,7 @@ module.exports = {
},
{
path: '/slider',
- title: 'Slider - 滑块'
+ title: 'Slider - 滑块'
},
{
path: '/stepper',
diff --git a/packages/swipe-item/index.vue b/packages/swipe-item/index.vue
index c85a99c3c..764e559ce 100644
--- a/packages/swipe-item/index.vue
+++ b/packages/swipe-item/index.vue
@@ -18,9 +18,11 @@ export default create({
computed: {
style() {
+ const { vertical, width, height } = this.$parent;
return {
- width: this.$parent.width + 'px',
- transform: `translate(${this.offset}px, 0)`
+ width: width + 'px',
+ height: vertical ? height + 'px' : '100%',
+ transform: `translate${vertical ? 'Y' : 'X'}(${this.offset}px)`
};
}
},
diff --git a/packages/swipe/index.vue b/packages/swipe/index.vue
index 48a37447f..d38c36330 100644
--- a/packages/swipe/index.vue
+++ b/packages/swipe/index.vue
@@ -17,9 +17,13 @@
-
+
@@ -35,6 +39,7 @@ export default create({
props: {
autoplay: Number,
+ vertical: Boolean,
loop: {
type: Boolean,
default: true
@@ -56,11 +61,13 @@ export default create({
data() {
return {
width: 0,
+ height: 0,
offset: 0,
startX: 0,
startY: 0,
active: 0,
deltaX: 0,
+ deltaY: 0,
swipes: [],
direction: '',
currentDuration: 0
@@ -97,16 +104,33 @@ export default create({
},
trackStyle() {
- return {
- paddingLeft: this.width + 'px',
- width: (this.count + 2) * this.width + 'px',
- transitionDuration: `${this.currentDuration}ms`,
- transform: `translate(${this.offset}px, 0)`
+ const sizeKey = this.vertical ? 'height' : 'width';
+
+ const style = {
+ [this.vertical ? 'paddingTop' : 'paddingLeft']: `${this[sizeKey]}px`,
+ [sizeKey]: `${(this.count + 2) * this[sizeKey]}px`,
+ transitionDuration: `${this.currentDuration}ms`
};
+
+ if (this.vertical) {
+ style.transform = `translate(0, ${this.offset}px)`;
+ } else {
+ style.transform = `translate(${this.offset}px, 0)`;
+ }
+
+ return style;
+ },
+
+ indicatorsClass() {
+ return this.vertical ? 'indicators--vertical' : 'indicators';
},
activeIndicator() {
return (this.active + this.count) % this.count;
+ },
+
+ size() {
+ return this.vertical ? this.height : this.width;
}
},
@@ -114,10 +138,10 @@ export default create({
initialize() {
// reset offset when children changes
clearTimeout(this.timer);
- this.width = this.$el.getBoundingClientRect().width;
+ ({ width: this.width, height: this.height } = this.$el.getBoundingClientRect());
this.active = this.initialSwipe;
this.currentDuration = 0;
- this.offset = this.count > 1 ? -this.width * (this.active + 1) : 0;
+ this.offset = this.count > 1 ? -this.size * (this.active + 1) : 0;
this.swipes.forEach(swipe => {
swipe.offset = 0;
});
@@ -139,25 +163,41 @@ export default create({
},
onTouchMove(event) {
+ const delta = this.vertical ? this.deltaY : this.deltaX;
+
this.touchMove(event);
- if (this.direction === 'horizontal') {
+ if (this.vertical && this.direction === 'vertical') {
+ event.preventDefault();
+ event.stopPropagation();
+ } else if (this.direction === 'horizontal') {
event.preventDefault();
event.stopPropagation();
- this.move(0, this.range(this.deltaX, [-this.width, this.width]));
}
+
+ this.move(0, this.range(delta, [-this.size, this.size]));
+ this.move(0, this.range(delta, [-this.size, this.size]));
},
onTouchEnd() {
- if (this.deltaX) {
- this.move(this.offsetX > 50 ? (this.deltaX > 0 ? -1 : 1) : 0);
+ const { deltaX, deltaY } = this;
+
+ if (deltaX) {
+ this.move(this.offsetX > 50 ? (deltaX > 0 ? -1 : 1) : 0);
this.currentDuration = this.duration;
}
+
+ if (deltaY) {
+ this.move(this.offsetY > 50 ? (deltaY > 0 ? -1 : 1) : 0);
+ this.currentDuration = this.duration;
+ }
+
this.autoPlay();
},
move(move = 0, offset = 0) {
- const { active, count, swipes, deltaX, width } = this;
+ const { active, count, swipes } = this;
+ const delta = this.vertical ? this.deltaY : this.deltaX;
if (
!this.loop &&
@@ -171,17 +211,17 @@ export default create({
if (active === -1) {
swipes[count - 1].offset = 0;
}
- swipes[0].offset = active === count - 1 && move > 0 ? count * width : 0;
+ swipes[0].offset = active === count - 1 && move > 0 ? count * this.size : 0;
this.active += move;
} else {
if (active === 0) {
- swipes[count - 1].offset = deltaX > 0 ? -count * width : 0;
+ swipes[count - 1].offset = delta > 0 ? -count * this.size : 0;
} else if (active === count - 1) {
- swipes[0].offset = deltaX < 0 ? count * width : 0;
+ swipes[0].offset = delta < 0 ? count * this.size : 0;
}
}
- this.offset = offset - (this.active + 1) * this.width;
+ this.offset = offset - (this.active + 1) * this.size;
},
autoPlay() {
diff --git a/packages/vant-css/src/swipe.css b/packages/vant-css/src/swipe.css
index b57830295..6d53c6853 100644
--- a/packages/vant-css/src/swipe.css
+++ b/packages/vant-css/src/swipe.css
@@ -17,11 +17,19 @@ $van-swipe-indicator: 6px;
}
&__indicators {
+ position: absolute;
left: 50%;
bottom: 10px;
- position: absolute;
height: $van-swipe-indicator;
transform: translate3d(-50%, 0, 0);
+
+ &--vertical {
+ position: absolute;
+ left: 10px;
+ top: 50%;
+ width: $van-swipe-indicator;
+ transform: translate3d(0, -50%, 0);
+ }
}
&__indicator {
@@ -35,7 +43,7 @@ $van-swipe-indicator: 6px;
&:not(:last-child) {
margin-right: $van-swipe-indicator;
}
-
+
&--active {
background-color: $orange;
}