feat(ImagePreview): add image loading tip (#4378)

This commit is contained in:
neverland 2019-09-05 17:48:08 +08:00 committed by GitHub
parent b9c1dca67c
commit 3f8ffccb36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 138 additions and 94 deletions

View File

@ -4,6 +4,8 @@ import { preventDefault } from '../utils/dom/event';
import { PopupMixin } from '../mixins/popup'; import { PopupMixin } from '../mixins/popup';
import { TouchMixin } from '../mixins/touch'; import { TouchMixin } from '../mixins/touch';
import { CloseOnPopstateMixin } from '../mixins/close-on-popstate'; import { CloseOnPopstateMixin } from '../mixins/close-on-popstate';
import Image from '../image';
import Loading from '../loading';
import Swipe from '../swipe'; import Swipe from '../swipe';
import SwipeItem from '../swipe-item'; import SwipeItem from '../swipe-item';
@ -19,11 +21,7 @@ function getDistance(touches) {
} }
export default createComponent({ export default createComponent({
mixins: [ mixins: [PopupMixin, TouchMixin, CloseOnPopstateMixin],
PopupMixin,
TouchMixin,
CloseOnPopstateMixin
],
props: { props: {
className: null, className: null,
@ -253,23 +251,24 @@ export default createComponent({
this.scale = scale; this.scale = scale;
this.moveX = 0; this.moveX = 0;
this.moveY = 0; this.moveY = 0;
},
genIndex() {
if (this.showIndex) {
return (
<div class={bem('index')}>
{this.slots('index') || `${this.active + 1}/${this.images.length}`}
</div>
);
} }
}, },
render() { genImages() {
if (!this.value) { const imageSlots = {
return; loading: () => <Loading type="spinner" />
} };
const { active, images } = this; return (
const Index = this.showIndex && (
<div class={bem('index')}>
{this.slots('index') || `${active + 1}/${images.length}`}
</div>
);
const Images = (
<Swipe <Swipe
ref="swipe" ref="swipe"
loop={this.loop} loop={this.loop}
@ -279,29 +278,31 @@ export default createComponent({
showIndicators={this.showIndicators} showIndicators={this.showIndicators}
onChange={this.setActive} onChange={this.setActive}
> >
{images.map((image, index) => { {this.images.map((image, index) => (
const props = {
class: bem('image'),
style: index === active ? this.imageStyle : null,
on: {
touchstart: this.onImageTouchStart,
touchmove: this.onImageTouchMove,
touchend: this.onImageTouchEnd,
touchcancel: this.onImageTouchEnd
}
};
return (
<SwipeItem> <SwipeItem>
{this.lazyLoad ? ( <Image
<img vLazy={image} {...props} /> src={image}
) : ( fit="contain"
<img src={image} {...props} /> class={bem('image')}
)} lazyLoad={this.lazyLoad}
scopedSlots={imageSlots}
style={index === this.active ? this.imageStyle : null}
nativeOnTouchstart={this.onImageTouchStart}
nativeOnTouchmove={this.onImageTouchMove}
nativeOnTouchend={this.onImageTouchEnd}
nativeOnTouchcancel={this.onImageTouchEnd}
/>
</SwipeItem> </SwipeItem>
); ))}
})}
</Swipe> </Swipe>
); );
}
},
render() {
if (!this.value) {
return;
}
return ( return (
<transition name="van-fade"> <transition name="van-fade">
@ -312,8 +313,8 @@ export default createComponent({
onTouchend={this.onWrapperTouchEnd} onTouchend={this.onWrapperTouchEnd}
onTouchcancel={this.onWrapperTouchEnd} onTouchcancel={this.onWrapperTouchEnd}
> >
{Images} {this.genImages()}
{Index} {this.genIndex()}
</div> </div>
</transition> </transition>
); );

View File

@ -94,6 +94,7 @@ export default {
showImagePreview(position, timer) { showImagePreview(position, timer) {
const instance = ImagePreview({ const instance = ImagePreview({
images, images,
lazyLoad: true,
swipeDuration: 300, swipeDuration: 300,
asyncClose: !!timer, asyncClose: !!timer,
closeOnPopstate: true, closeOnPopstate: true,

View File

@ -13,9 +13,10 @@
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
max-width: 100%;
max-height: 100%; .van-image__loading {
margin: auto; background-color: transparent;
}
} }
&__index { &__index {

View File

@ -13,9 +13,27 @@ exports[`lazy-load prop 1`] = `
<div class="van-image-preview" name="van-fade"> <div class="van-image-preview" name="van-fade">
<div class="van-swipe"> <div class="van-swipe">
<div class="van-swipe__track" style="width: 0px; transition-duration: 0ms; transform: translateX(0px);"> <div class="van-swipe__track" style="width: 0px; transition-duration: 0ms; transform: translateX(0px);">
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);"><img class="van-image-preview__image" style="transition: .3s all;"></div> <div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);">
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);"><img class="van-image-preview__image"></div> <div class="van-image van-image-preview__image" style="transition: .3s all;"><img class="van-image__img" style="object-fit: contain;">
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);"><img class="van-image-preview__image"></div> <div class="van-image__loading">
<div class="van-loading van-loading--spinner"><span class="van-loading__spinner van-loading__spinner--spinner" style="color: rgb(201, 201, 201);"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span></div>
</div>
</div>
</div>
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);">
<div class="van-image van-image-preview__image"><img class="van-image__img" style="object-fit: contain;">
<div class="van-image__loading">
<div class="van-loading van-loading--spinner"><span class="van-loading__spinner van-loading__spinner--spinner" style="color: rgb(201, 201, 201);"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span></div>
</div>
</div>
</div>
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);">
<div class="van-image van-image-preview__image"><img class="van-image__img" style="object-fit: contain;">
<div class="van-image__loading">
<div class="van-loading van-loading--spinner"><span class="van-loading__spinner van-loading__spinner--spinner" style="color: rgb(201, 201, 201);"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span></div>
</div>
</div>
</div>
</div> </div>
</div> </div>
<div class="van-image-preview__index">1/3</div> <div class="van-image-preview__index">1/3</div>
@ -26,22 +44,66 @@ exports[`render image 1`] = `
<div class="van-image-preview" name="van-fade"> <div class="van-image-preview" name="van-fade">
<div class="van-swipe"> <div class="van-swipe">
<div class="van-swipe__track" style="width: 0px; transition-duration: 500ms; transform: translateX(0px);"> <div class="van-swipe__track" style="width: 0px; transition-duration: 500ms; transform: translateX(0px);">
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);"><img src="https://img.yzcdn.cn/1.png" class="van-image-preview__image" style="transition: .3s all;"></div> <div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);">
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);"><img src="https://img.yzcdn.cn/2.png" class="van-image-preview__image"></div> <div class="van-image van-image-preview__image" style="transition: .3s all;"><img src="https://img.yzcdn.cn/1.png" class="van-image__img" style="object-fit: contain;">
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);"><img src="https://img.yzcdn.cn/3.png" class="van-image-preview__image"></div> <div class="van-image__loading">
<div class="van-loading van-loading--spinner"><span class="van-loading__spinner van-loading__spinner--spinner" style="color: rgb(201, 201, 201);"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span></div>
</div>
</div>
</div>
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);">
<div class="van-image van-image-preview__image"><img src="https://img.yzcdn.cn/2.png" class="van-image__img" style="object-fit: contain;">
<div class="van-image__loading">
<div class="van-loading van-loading--spinner"><span class="van-loading__spinner van-loading__spinner--spinner" style="color: rgb(201, 201, 201);"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span></div>
</div>
</div>
</div>
<div class="van-swipe-item" style="width: 0px; height: 100%; transform: translateX(0px);">
<div class="van-image van-image-preview__image"><img src="https://img.yzcdn.cn/3.png" class="van-image__img" style="object-fit: contain;">
<div class="van-image__loading">
<div class="van-loading van-loading--spinner"><span class="van-loading__spinner van-loading__spinner--spinner" style="color: rgb(201, 201, 201);"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span></div>
</div>
</div>
</div>
</div> </div>
</div> </div>
<div class="van-image-preview__index">1/3</div> <div class="van-image-preview__index">1/3</div>
</div> </div>
`; `;
exports[`set show-index prop to false 1`] = `
<div class="van-image-preview" name="van-fade">
<div class="van-swipe">
<div class="van-swipe__track" style="width: 0px; transition-duration: 0ms; transform: translateX(0px);"></div>
</div>
</div>
`;
exports[`zoom 1`] = ` exports[`zoom 1`] = `
<div class="van-image-preview" name="van-fade"> <div class="van-image-preview" name="van-fade">
<div class="van-swipe"> <div class="van-swipe">
<div class="van-swipe__track" style="transition-duration: 500ms; width: 0px; transform: translateX(0px);"> <div class="van-swipe__track" style="transition-duration: 500ms; width: 0px; transform: translateX(0px);">
<div class="van-swipe-item" style="width: 100px; height: 100%; transform: translateX(0px);"><img src="https://img.yzcdn.cn/1.png" class="van-image-preview__image" style="transform: scale3d(2, 2, 1) translate(0px, NaNpx);"></div> <div class="van-swipe-item" style="width: 100px; height: 100%; transform: translateX(0px);">
<div class="van-swipe-item" style="width: 100px; height: 100%; transform: translateX(0px);"><img src="https://img.yzcdn.cn/2.png" class="van-image-preview__image"></div> <div class="van-image van-image-preview__image" style="transform: scale3d(2, 2, 1) translate(0px, NaNpx);"><img src="https://img.yzcdn.cn/1.png" class="van-image__img" style="object-fit: contain;">
<div class="van-swipe-item" style="width: 100px; height: 100%; transform: translateX(0px);"><img src="https://img.yzcdn.cn/3.png" class="van-image-preview__image"></div> <div class="van-image__loading">
<div class="van-loading van-loading--spinner"><span class="van-loading__spinner van-loading__spinner--spinner" style="color: rgb(201, 201, 201);"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span></div>
</div>
</div>
</div>
<div class="van-swipe-item" style="width: 100px; height: 100%; transform: translateX(0px);">
<div class="van-image van-image-preview__image"><img src="https://img.yzcdn.cn/2.png" class="van-image__img" style="object-fit: contain;">
<div class="van-image__loading">
<div class="van-loading van-loading--spinner"><span class="van-loading__spinner van-loading__spinner--spinner" style="color: rgb(201, 201, 201);"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span></div>
</div>
</div>
</div>
<div class="van-swipe-item" style="width: 100px; height: 100%; transform: translateX(0px);">
<div class="van-image van-image-preview__image"><img src="https://img.yzcdn.cn/3.png" class="van-image__img" style="object-fit: contain;">
<div class="van-image__loading">
<div class="van-loading van-loading--spinner"><span class="van-loading__spinner van-loading__spinner--spinner" style="color: rgb(201, 201, 201);"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span></div>
</div>
</div>
</div>
</div> </div>
</div> </div>
<div class="van-image-preview__index">1/3</div> <div class="van-image-preview__index">1/3</div>

View File

@ -136,6 +136,17 @@ test('zoom', async () => {
Element.prototype.getBoundingClientRect = getBoundingClientRect; Element.prototype.getBoundingClientRect = getBoundingClientRect;
}); });
test('set show-index prop to false', () => {
const wrapper = mount(ImagePreviewVue, {
propsData: {
value: true,
showIndex: false
}
});
expect(wrapper).toMatchSnapshot();
});
test('index slot', () => { test('index slot', () => {
const wrapper = mount({ const wrapper = mount({
template: ` template: `

View File

@ -1,37 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`click to preview image 1`] = `
<div
class="van-image-preview"
name="van-fade"
>
<div
class="van-swipe"
>
<div
class="van-swipe__track"
style="width: 0px; transition-duration: 0ms; transform: translateX(0px);"
>
<div
class="van-swipe-item"
style="width: 0px; height: 100%; transform: translateX(0px);"
>
<img
class="van-image-preview__image"
src="https://img.yzcdn.cn/vant/cat.jpeg"
style="transition: .3s all;"
/>
</div>
</div>
</div>
<div
class="van-image-preview__index"
>
1/1
</div>
</div>
`;
exports[`delete preview image 1`] = ` exports[`delete preview image 1`] = `
<div class="van-uploader"> <div class="van-uploader">
<div class="van-uploader__wrapper"> <div class="van-uploader__wrapper">

View File

@ -341,7 +341,7 @@ it('click to preview image', () => {
wrapper.find('.van-image').trigger('click'); wrapper.find('.van-image').trigger('click');
const imagePreviewNode2 = document.querySelector('.van-image-preview'); const imagePreviewNode2 = document.querySelector('.van-image-preview');
expect(imagePreviewNode2).toMatchSnapshot(); expect(imagePreviewNode2.querySelectorAll('.van-image-preview__image').length).toEqual(1);
}); });
it('click-preview event', () => { it('click-preview event', () => {