Skip to content

Commit

Permalink
feat: add lazyload prop. change $el to $refs
Browse files Browse the repository at this point in the history
  • Loading branch information
guastallaigor committed Nov 26, 2020
1 parent ba03b8e commit a78800a
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 45 deletions.
117 changes: 86 additions & 31 deletions src/components/VueImageKit.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,39 @@
<template>
<div class="vue-image-kit">
<div v-if="dataUrl" class="vue-image-kit__placeholder" :style="{ backgroundColor }">
<img :src="placeholder || dataUrl" alt="Placeholder" :style="{ width: `${width}px`, height: `${height}px` }"/>
</div>
<img class="vue-image-kit__img" :sizes="getSizes" :alt="alt" :style="{ width: `${width}px`, height: `${height}px` }"/>
<div
:class="{ 'vue-image-kit--loaded': !lazyLoad }"
class="vue-image-kit"
ref="main"
>
<template v-if="lazyLoad">
<div
v-if="getDataUrl"
:key="getRandomId"
:style="{ backgroundColor }"
class="vue-image-kit__placeholder"
>
<img
:src="placeholder || getDataUrl"
:style="{ width: `${width}px`, height: `${height}px` }"
alt="Placeholder"
ref="placeholder"
/>
</div>
<img
:sizes="getSizes"
:style="{ width: `${width}px`, height: `${height}px` }"
:alt="alt"
class="vue-image-kit__img"
ref="lazyLoad"
/>
</template>
<img
v-else
:sizes="getSizes"
:style="{ width: `${width}px`, height: `${height}px` }"
:alt="alt"
ref="normalLoad"
class="vue-image-kit__img"
/>
</div>
</template>

Expand Down Expand Up @@ -54,6 +84,10 @@ export default {
customTransform: {
type: String,
default: ''
},
lazyLoad: {
type: Boolean,
default: true
}
},
data: () => ({
Expand All @@ -63,7 +97,10 @@ export default {
timeOut: null
}),
computed: {
dataUrl () {
getRandomId () {
return Math.random().toString(36).substr(2, 9)
},
getDataUrl () {
const { width, height, showCanvas } = this
if (!width || !height || !showCanvas) return ''
Expand All @@ -79,7 +116,9 @@ export default {
const { srcset, imageKitPrefix, hash, customTransform, src } = this
return srcset
.map(size => `${imageKitPrefix}/${hash}/tr:w-${size}${customTransform ? ',' + customTransform : ''}/${src} ${size}w`)
.map(size => `${imageKitPrefix}/${hash}/tr:w-${size}${customTransform
? ',' + customTransform
: ''}/${src} ${size}w`)
.join(', ')
},
getSizes () {
Expand All @@ -98,49 +137,65 @@ export default {
}
},
mounted () {
this.showCanvas = true
this.observer = new IntersectionObserver(([entry]) => {
this.triggerIntersection(entry)
})
this.observer.observe(this.$el)
this.$once('hook:beforeDestroy', () => {
this.observer.disconnect()
if (this.timeOut) {
clearTimeout(this.timeOut)
}
})
if (this.lazyLoad) {
this.initLazyLoad()
return
}
this.initNormalLoad()
},
methods: {
initNormalLoad () {
const img = this.$refs.normalLoad
this.setImgAttributes(img)
},
initLazyLoad () {
this.showCanvas = true
this.observer = new IntersectionObserver(([entry]) => {
this.triggerIntersection(entry)
})
this.observer.observe(this.$refs.main)
this.$once('hook:beforeDestroy', () => {
this.observer.disconnect()
if (this.timeOut) {
clearTimeout(this.timeOut)
}
})
},
onloadImage (imgEl) {
delete imgEl.onload
const { $el } = this
const placeholder = $el.querySelector('.vue-image-kit__placeholder')
const { main, placeholder } = this.$refs
$el.classList.add('vue-image-kit--loaded')
if (main) {
main.classList.add('vue-image-kit--loaded')
}
if (placeholder) {
this.timeOut = setTimeout(() => {
placeholder.remove()
}, 300)
}
},
setImgAttributes (img) {
const { srcset, getSrcset, imageKitPrefix, hash, src } = this
this.showCanvas = false
if (srcset) {
img.srcset = getSrcset
}
img.src = `${imageKitPrefix}/${hash}/${src}`
},
triggerIntersection (entry = {}) {
const { $el, srcset, getSrcset, imageKitPrefix, hash, src } = this
const img = $el.querySelector('.vue-image-kit__img')
const img = this.$refs.lazyLoad
img.onload = function () {
this.onloadImage(img)
}.bind(this)
if (entry.isIntersecting) {
this.showCanvas = false
if (srcset) {
img.srcset = getSrcset
}
img.src = `${imageKitPrefix}/${hash}/${src}`
this.setImgAttributes(img)
this.observer.disconnect()
}
}
Expand Down
36 changes: 22 additions & 14 deletions stories/index.stories.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable import/no-extraneous-dependencies */
import { storiesOf } from '@storybook/vue'
import { withKnobs, array, text, number } from '@storybook/addon-knobs'
import { withKnobs, array, text, number, boolean } from '@storybook/addon-knobs'
import VueImageKit from '../src/components/VueImageKit'

const timelineStory = storiesOf('VueImageKit', module)
Expand Down Expand Up @@ -67,20 +67,28 @@ timelineStory.add('Default', () => {
alt: {
type: String,
default: text('Alt', '')
},
lazyLoad: {
type: Boolean,
default: boolean('Lazy Load', true)
}
},
template: `<div><div style="height:4500px;width:100vw;background:gray">&nbsp;</div><vue-image-kit
:hash="hash"
:src="src"
:placeholder="placeholder"
:background-color="backgroundColor"
:srcset="srcset"
:sizes="sizes"
:width="width"
:height="height"
:alt="alt"
:default-size="defaultSize"
:custom-transform="customTransform"
/></div>`
template: `<div>
<div style="height:2500px;width:100vw;background:gray">&nbsp;</div>
<vue-image-kit
:hash="hash"
:src="src"
:placeholder="placeholder"
:background-color="backgroundColor"
:srcset="srcset"
:sizes="sizes"
:width="width"
:height="height"
:alt="alt"
:lazy-load="lazyLoad"
:default-size="defaultSize"
:custom-transform="customTransform"
/>
</div>`
}
})

0 comments on commit a78800a

Please sign in to comment.