Skip to content

Instantly share code, notes, and snippets.

@salvatorecriscioneweb
Last active November 24, 2019 10:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save salvatorecriscioneweb/71642083eb419e4dac296304e2526fe4 to your computer and use it in GitHub Desktop.
Save salvatorecriscioneweb/71642083eb419e4dac296304e2526fe4 to your computer and use it in GitHub Desktop.
Lazy load image example
<template>
<picture
:class="`LazyImage ${animating ? '-has-animation' : ''}`"
:style="style"
aria-live
>
<source
type="image/webp"
v-for="(src, i) in lazySrcset"
:key="'source-webp-' + id + '-' + i"
:media="getMediaQueries(src, i, lazySrcset.length)"
:data-srcset="getSrcSet(src, lazySrc, 'webp')"
/>
<source
type="image/jpeg"
v-for="(src, i) in lazySrcset"
:key="'source-' + id + '-' + i"
:media="getMediaQueries(src, i, lazySrcset.length)"
:data-srcset="getSrcSet(src, lazySrc, 'jpg')"
/>
<img
:data-src="srcComputed"
:class="id"
:style="{width: '100%'}"
/>
</picture>
</template>
<script>
import LazyLoad from 'vanilla-lazyload';
export default {
name: 'LazyImage',
props: {
backgroundColor: {
type: String,
default: '#1089ff',
},
height: {
type: Number,
default: null,
},
lazySrc: {
type: String,
default: null,
},
lazySrcset: {
type: Array,
default: null,
},
width: {
type: Number,
default: null,
},
id: {
type: String,
default: 'id-example',
}
},
data() {
return {
loading: true,
animating: false,
observer: null,
};
},
computed: {
srcComputed() {
return this.lazySrc + '.jpg'
},
lazySrcReversed() {
return this.lazySrcset.reverse()
},
srcsetComputed() {
if (!this.lazySrcset || this.lazySrcset === '') {
return ''
}
let ret = ''
for (let i = 0; i < this.lazySrcset.length; i++ ) {
ret += `${this.lazySrc}-${this.lazySrcset[i]}w.jpg ${this.lazySrcset[i]}w`
if ( i !== this.lazySrcset.length - 1) {
ret += ', '
}
}
return ret
},
sizesComputed() {
if (!this.lazySrcset || this.lazySrcset === '') {
return ''
}
let ret = ''
for (let i = 0; i < this.lazySrcset.length; i++ ) {
if ( i >= this.lazySrcset.length - 1) {
ret += `${this.lazySrcset[i]}px`
} else {
ret += `(max-width: ${parseInt(this.lazySrcset[i]) + 120}px) ${this.lazySrcset[i]}px, `
}
}
return ret
},
aspectRatio() {
if (!this.width || !this.height) return null;
return (this.height / this.width) * 100;
},
style() {
const style = {
backgroundColor: this.backgroundColor,
display: 'block'
};
if (this.width) style.width = `${this.width}px`;
return style;
},
},
methods: {
getMediaQueries(pt, i, lazySrcset) {
return `(${i >= lazySrcset - 1 ? 'min' : 'max'}-width: ${parseInt(pt) + 120}px)`
},
getSrcSet(src, srcImage, format) {
return `${srcImage}-${src}w.${format}`
}
},
mounted() {
this.$nextTick().then(() => {
this.observer = new LazyLoad({
elements_selector: '.' + this.id,
callback_loaded: () => {
this.animating = true
this.loading = false
}
})
})
}
};
</script>
<style>
.LazyImage {
max-width: 100%;
max-height: 100%;
width: 100%;
vertical-align: middle;
position: relative;
}
.LazyImage img {
max-width: 100%;
clip-path: inset(100% 0 0 0);
transition: clip-path 0.4s ease-in-out;
transition-delay: 1s;
will-change: clip-path;
}
.LazyImage.-has-animation img {
clip-path: inset(0 0 0 0);
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment