Skip to content

Instantly share code, notes, and snippets.

@dimensi
Created July 12, 2018 21:50
Show Gist options
  • Select an option

  • Save dimensi/5fd2552f5279515e84b0b90b9f0674db to your computer and use it in GitHub Desktop.

Select an option

Save dimensi/5fd2552f5279515e84b0b90b9f0674db to your computer and use it in GitHub Desktop.
<template>
<div :class="b({ loading: isLoading })" :style="style">
<ImgLoader class="image-handler__loader" v-if="isLoading"/>
<img :src="image" v-bind="$attrs" ref="image">
</div>
</template>
<script>
import ImgLoader from 'src/views/elements/ImgLoader';
export const waitImage = ref =>
new Promise((resolve, reject) => {
ref.addEventListener('load', function onload() {
resolve();
ref.removeEventListener('load', onload);
});
ref.addEventListener('error', function onerror(err) {
reject(err);
ref.removeEventListener('error', onerror);
});
});
export default {
name: 'ImageHandler',
components: {
ImgLoader,
},
inheritAttrs: false,
props: {
src: String,
defaultSrc: String,
minHeight: [Number, String],
},
data() {
return {
imageFailed: false,
isLoading: true,
};
},
computed: {
image() {
if (!this.src || this.imageFailed) {
return this.defaultSrc;
}
return this.src;
},
style() {
if (!this.minHeight) return null;
return {
'min-height': `${this.minHeight}px`,
};
},
},
async mounted() {
try {
await waitImage(this.$refs.image);
} catch (err) {
this.imageFailed = true;
}
this.isLoading = false;
},
};
</script>
<style lang="scss">
.image-handler {
display: block;
position: relative;
&--loading img {
opacity: 0;
}
&__loader {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
img {
display: block;
max-width: 100%;
transition: opacity 0.3s;
}
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment