<template>
<div class="ratio-fixed-image" :class="{loading : status === 'loading'}" :style="style">
<slot />
</div>
</template>
<script>
import { cropImage } from 'utils/qiniu';
export default {
props: ['ratioHeight', 'ratioWidth', 'url', 'qiniuCrop'],
data() {
const ratio = this.ratioHeight / this.ratioWidth * 100 + '%';
return {
status: 'loading',
ratio,
realWidth: 0,
realHeight: 0
};
},
computed: {
src() {
return this.url &&
this.qiniuCrop ?
cropImage(this.url, this.realWidth, this.realHeight) :
this.url;
},
style() {
const backgroundImage = this.status === 'loaded' && `url(${this.src})`;
return {
paddingTop: this.ratio,
backgroundImage
};
}
},
watch: {
url() {
this.loadImage();
}
},
methods: {
loadImage() {
this.status = 'loading';
if (this.src) {
let img = new Image();
img.onload = this.handleLoad;
img.onerror = this.handleError;
img.src = this.src;
}
},
handleLoad() {
this.status = 'loaded';
this.$nextTick(() => {
this.$emit('load');
});
},
handleError() {
this.status = 'error';
this.$nextTick(() => {
this.$emit('error');
});
}
},
mounted() {
({ clientWidth: this.realWidth, clientHeight: this.realHeight } = this.$el);
this.loadImage();
}
};
</script>
<style lang="scss" scoped>
.ratio-fixed-image {
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
background-color: #f0f0f0;
&.loading {
background-image: url('~images/loading.svg');
background-size: auto;
}
}
</style>
console