[new feature] Swipe: add immediate option of swipeTo method (#3821)

This commit is contained in:
neverland 2019-07-11 16:09:20 +08:00 committed by GitHub
parent 734c3259d8
commit 3c9dc4edfe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 52 additions and 14 deletions

View File

@ -1,5 +1,5 @@
import { createNamespace, isDef } from '../utils'; import { createNamespace, isDef } from '../utils';
import { raf } from '../utils/dom/raf'; import { raf, doubleRaf } from '../utils/dom/raf';
import Cell from '../cell'; import Cell from '../cell';
import { cellProps } from '../cell/shared'; import { cellProps } from '../cell/shared';
import { ChildrenMixin } from '../mixins/relation'; import { ChildrenMixin } from '../mixins/relation';
@ -76,10 +76,8 @@ export default createComponent({
wrapper.style.height = expanded ? 0 : contentHeight; wrapper.style.height = expanded ? 0 : contentHeight;
// use double raf to ensure animation can start in mobile safari // use double raf to ensure animation can start in mobile safari
raf(() => { doubleRaf(() => {
raf(() => { wrapper.style.height = expanded ? contentHeight : 0;
wrapper.style.height = expanded ? contentHeight : 0;
});
}); });
} else { } else {
this.onTransitionEnd(); this.onTransitionEnd();

View File

@ -156,7 +156,13 @@ Use ref to get swipe instance and call instance methods
| Name | Attribute | Return value | Description | | Name | Attribute | Return value | Description |
|------|------|------|------| |------|------|------|------|
| swipeTo | index: target index | void | Swipe to target index | | swipeTo | index: target index, options: Options | void | Swipe to target index |
### swipeTo Options
| Name | Description | Type |
|------|------|------|
| immediate | Whether to skip animation | `boolean` |
### Swipe Slots ### Swipe Slots

View File

@ -162,7 +162,13 @@ export default {
| 方法名 | 参数 | 返回值 | 介绍 | | 方法名 | 参数 | 返回值 | 介绍 |
|------|------|------|------| |------|------|------|------|
| swipeTo | index: 目标位置的索引 | void | 滚动到目标位置 | | swipeTo | index: 目标位置的索引, options: 选项 | void | 滚动到目标位置 |
### swipeTo Options 格式
| 名称 | 说明 | 类型 |
|------|------|------|
| immediate | 是否跳过动画 | `boolean` |
### Swipe Slots ### Swipe Slots

View File

@ -2,6 +2,7 @@ import { createNamespace } from '../utils';
import { preventDefault } from '../utils/dom/event'; import { preventDefault } from '../utils/dom/event';
import { TouchMixin } from '../mixins/touch'; import { TouchMixin } from '../mixins/touch';
import { BindEventMixin } from '../mixins/bind-event'; import { BindEventMixin } from '../mixins/bind-event';
import { doubleRaf } from '../utils/dom/raf';
import { range } from '../utils/format/number'; import { range } from '../utils/format/number';
const [createComponent, bem] = createNamespace('swipe'); const [createComponent, bem] = createNamespace('swipe');
@ -108,6 +109,7 @@ export default createComponent({
trackStyle() { trackStyle() {
const mainAxis = this.vertical ? 'height' : 'width'; const mainAxis = this.vertical ? 'height' : 'width';
const crossAxis = this.vertical ? 'width' : 'height'; const crossAxis = this.vertical ? 'width' : 'height';
return { return {
[mainAxis]: `${this.trackSize}px`, [mainAxis]: `${this.trackSize}px`,
[crossAxis]: this[crossAxis] ? `${this[crossAxis]}px` : '', [crossAxis]: this[crossAxis] ? `${this[crossAxis]}px` : '',
@ -246,24 +248,32 @@ export default createComponent({
} }
}, },
swipeTo(index) { swipeTo(index, options = {}) {
this.swiping = true; this.swiping = true;
this.resetTouchStatus(); this.resetTouchStatus();
this.correctPosition(); this.correctPosition();
setTimeout(() => { doubleRaf(() => {
this.swiping = false;
this.move({ this.move({
pace: (index % this.count) - this.active, pace: (index % this.count) - this.active,
emitChange: true emitChange: true
}); });
}, 30);
if (options.immediate) {
doubleRaf(() => {
this.swiping = false;
});
} else {
this.swiping = false;
}
});
}, },
correctPosition() { correctPosition() {
if (this.active <= -1) { if (this.active <= -1) {
this.move({ pace: this.count }); this.move({ pace: this.count });
} }
if (this.active >= this.count) { if (this.active >= this.count) {
this.move({ pace: -this.count }); this.move({ pace: -this.count });
} }
@ -283,14 +293,14 @@ export default createComponent({
this.resetTouchStatus(); this.resetTouchStatus();
this.correctPosition(); this.correctPosition();
setTimeout(() => { doubleRaf(() => {
this.swiping = false; this.swiping = false;
this.move({ this.move({
pace: 1, pace: 1,
emitChange: true emitChange: true
}); });
this.autoPlay(); this.autoPlay();
}, 30); });
}, autoplay); }, autoplay);
} }
}, },

View File

@ -48,7 +48,18 @@ test('swipeTo', async () => {
const { swipe } = wrapper.vm.$refs; const { swipe } = wrapper.vm.$refs;
swipe.swipeTo(2); swipe.swipeTo(2);
await later(30); await later(50);
expect(swipe.active).toEqual(2);
});
test('swipeTo immediate', async () => {
const wrapper = mount(Component);
const { swipe } = wrapper.vm.$refs;
swipe.swipeTo(2, {
immediate: true
});
await later(100);
expect(swipe.active).toEqual(2); expect(swipe.active).toEqual(2);
}); });

View File

@ -28,6 +28,13 @@ export function raf(fn: FrameRequestCallback): number {
return iRaf.call(root, fn); return iRaf.call(root, fn);
} }
// double raf for animation
export function doubleRaf(fn: FrameRequestCallback): void {
raf(() => {
raf(fn);
});
}
export function cancelRaf(id: number) { export function cancelRaf(id: number) {
iCancel.call(root, id); iCancel.call(root, id);
} }