This repository was archived by the owner on Jun 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
This repository was archived by the owner on Jun 23, 2023. It is now read-only.
Lazy Image component #32
Copy link
Copy link
Open
Description
import {reject, findIndex} from 'wasmuth'
import {throttle} from 'throttle-debounce'
const isInViewport = function (element) {
const rect = element.getBoundingClientRect()
const html = document.documentElement
return (
rect.bottom <= (window.innerHeight || html.clientHeight)
)
}
const worker = null
// window.Worker
// ? new window.Worker('workers/downloadImage.js')
// : null
let imageComponents = []
if (worker != null) {
worker.onmessage = ev => {
const idx = findIndex(({props}) => props.src === ev.data.src, imageComponents)
if (idx > -1) {
const match = imageComponents[idx]
window.setTimeout(() => {
match.setState({loaded: true})
match.removeSelf()
}, 100)
}
}
}
document.addEventListener('scroll', throttle(0, () => {
if (!imageComponents.length) return
imageComponents.forEach(i => {
if (isInViewport(i.base)) {
i.loadImage()
}
})
}, true))
export default class Image extends Preact.Component {
constructor (props) {
super(props)
this.state = {
loaded: false,
error: false
}
}
loadImage () {
if (worker != null) {
this.workerDownload()
} else {
this.domDownload()
}
}
workerDownload () {
worker.postMessage({src: this.props.src})
}
domDownload () {
const img = document.createElement('img')
img.onload = () => {
this.setState({loaded: true})
this.removeSelf(img)
}
img.onerror = () => {
this.setState({error: true})
this.removeSelf(img)
}
img.src = this.props.src
}
removeSelf (img) {
if (img) {
img.remove()
}
if (imageComponents.includes(this)) {
imageComponents = reject(i => i === this, imageComponents)
}
}
componentDidMount () {
imageComponents.push(this)
if (isInViewport(this.base)) {
this.loadImage()
}
}
componentWillUnmount () {
this.removeSelf()
}
render (
{src, unloadedSrc = '/images/blank-poster.gif', className, ...props},
{error, loaded}
) {
if (error) {
return <img src={unloadedSrc} className={className} {...props} />
} else if (!loaded) {
return <img src={unloadedSrc} className={`${className} image-loading`} {...props} />
} else {
return <img src={src} className={`${className} image-ready`} {...props} />
}
}
}
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels