implement lazy images
This commit is contained in:
parent
9d779a203c
commit
436c8c05aa
47
routes/_components/LazyImage.html
Normal file
47
routes/_components/LazyImage.html
Normal file
|
@ -0,0 +1,47 @@
|
|||
<div class="lazy-image"
|
||||
style="width: {{width}}px; height: {{height}}px; background: {{background}};">
|
||||
{{#if displaySrc}}
|
||||
<img
|
||||
class="{{hidden ? 'hidden' : ''}} {{className || ''}}"
|
||||
aria-hidden="{{ariaHidden || ''}}"
|
||||
alt="{{alt || ''}}"
|
||||
src="{{displaySrc}}"
|
||||
:width
|
||||
:height
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
<style>
|
||||
.lazy-image {
|
||||
overflow: hidden;
|
||||
}
|
||||
.lazy-image img {
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
export default {
|
||||
oncreate() {
|
||||
requestAnimationFrame(() => {
|
||||
let img = new Image()
|
||||
let src = this.get('src')
|
||||
let fallback = this.get('fallback')
|
||||
img.onload = () => {
|
||||
requestAnimationFrame(() => {
|
||||
this.set({
|
||||
displaySrc: src,
|
||||
hidden: true
|
||||
})
|
||||
requestAnimationFrame(() => {
|
||||
this.set({hidden: false})
|
||||
})
|
||||
})
|
||||
}
|
||||
img.onerror = () => {
|
||||
this.set({displaySrc: fallback})
|
||||
}
|
||||
img.src = src
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -17,13 +17,14 @@
|
|||
playsinline
|
||||
/>
|
||||
{{else}}
|
||||
<img class="{{class}} {{imageError ? 'image-error' : ''}}"
|
||||
<LazyImage
|
||||
alt="{{label}}"
|
||||
src="{{imageError ? oneTransparentPixel : staticSrc}}"
|
||||
width="{{width}}"
|
||||
height="{{height}}"
|
||||
on:imgLoad="set({imageLoaded: true})"
|
||||
on:imgLoadError="set({imageError: true})"
|
||||
src="{{staticSrc}}"
|
||||
fallback="{{oneTransparentPixel}}"
|
||||
:width
|
||||
:height
|
||||
background="var(--loading-bg)"
|
||||
className="{{class}}"
|
||||
/>
|
||||
{{/if}}
|
||||
<PlayVideoIcon className="{{playing ? 'hidden' : ''}}"/>
|
||||
|
@ -39,9 +40,9 @@
|
|||
</style>
|
||||
<script>
|
||||
import { mouseover } from '../_utils/events'
|
||||
import { imgLoad, imgLoadError } from '../_utils/events'
|
||||
import PlayVideoIcon from './PlayVideoIcon.html'
|
||||
import { ONE_TRANSPARENT_PIXEL } from '../_static/media'
|
||||
import LazyImage from './LazyImage.html'
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
|
@ -50,15 +51,14 @@
|
|||
}
|
||||
},
|
||||
events: {
|
||||
mouseover,
|
||||
imgLoad,
|
||||
imgLoadError
|
||||
mouseover
|
||||
},
|
||||
data: () => ({
|
||||
oneTransparentPixel: ONE_TRANSPARENT_PIXEL
|
||||
}),
|
||||
components: {
|
||||
PlayVideoIcon
|
||||
PlayVideoIcon,
|
||||
LazyImage
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -6,13 +6,14 @@
|
|||
style="width: {{inlineWidth}}px; height: {{inlineHeight}}px;"
|
||||
>
|
||||
<PlayVideoIcon />
|
||||
<img alt="{{media.description || ''}}"
|
||||
src="{{imageError ? oneTransparentPixel : media.preview_url}}"
|
||||
<LazyImage
|
||||
alt="{{media.description}}"
|
||||
src="{{media.preview_url}}"
|
||||
fallback="{{oneTransparentPixel}}"
|
||||
width="{{inlineWidth}}"
|
||||
height="{{inlineHeight}}"
|
||||
class="{{noNativeWidthHeight ? 'no-native-width-height' : ''}} {{imageError ? 'image-error' : ''}}"
|
||||
on:imgLoad="set({imageLoaded: true})"
|
||||
on:imgLoadError="set({imageError: true})"
|
||||
background="var(--loading-bg)"
|
||||
className="{{noNativeWidthHeight ? 'no-native-width-height' : ''}}"
|
||||
/>
|
||||
</button>
|
||||
{{else}}
|
||||
|
@ -48,25 +49,23 @@
|
|||
playing="{{mouseover}}"
|
||||
/>
|
||||
{{else}}
|
||||
<img class="{{!imageLoaded ? 'image-loading' : ''}} {{imageError ? 'image-error' : ''}} {{noNativeWidthHeight ? 'no-native-width-height' : ''}}"
|
||||
on:imgLoad="set({imageLoaded: true})"
|
||||
on:imgLoadError="set({imageError: true})"
|
||||
alt="{{media.description || ''}}"
|
||||
src="{{imageError ? oneTransparentPixel : media.preview_url}}"
|
||||
<LazyImage
|
||||
alt="{{media.description}}"
|
||||
src="{{media.preview_url}}"
|
||||
fallback="{{oneTransparentPixel}}"
|
||||
width="{{inlineWidth}}"
|
||||
height="{{inlineHeight}}"
|
||||
background="var(--loading-bg)"
|
||||
className="{{noNativeWidthHeight ? 'no-native-width-height' : ''}}"
|
||||
/>
|
||||
{{/if}}
|
||||
</button>
|
||||
{{/if}}
|
||||
<style>
|
||||
:global(.status-media img.image-loading, .status-media img.image-error) {
|
||||
background: var(--loading-bg);
|
||||
}
|
||||
:global(.status-media video, .status-media img) {
|
||||
object-fit: cover;
|
||||
}
|
||||
.no-native-width-height {
|
||||
:global(.no-native-width-height) {
|
||||
background-color: var(--mask-bg);
|
||||
}
|
||||
.play-video-button {
|
||||
|
@ -86,24 +85,28 @@
|
|||
cursor: zoom-in;
|
||||
}
|
||||
|
||||
:global(.status-media video, .status-media img) {
|
||||
:global(.status-media video, .status-media img, .status-media .lazy-image,
|
||||
.status-media .show-image-button, .status-media .non-autoplay-gifv,
|
||||
.status-media .play-video-button) {
|
||||
max-width: calc(100vw - 40px);
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
:global(.status-media video, .status-media img) {
|
||||
:global(.status-media video, .status-media img, .status-media .lazy-image,
|
||||
.status-media .show-image-button, .status-media .non-autoplay-gifv,
|
||||
.status-media .play-video-button) {
|
||||
max-width: calc(100vw - 20px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import { DEFAULT_MEDIA_WIDTH, DEFAULT_MEDIA_HEIGHT } from '../../_static/media'
|
||||
import { imgLoad, imgLoadError } from '../../_utils/events'
|
||||
import { importDialogs } from '../../_utils/asyncModules'
|
||||
import { mouseover } from '../../_utils/events'
|
||||
import NonAutoplayGifv from '../NonAutoplayGifv.html'
|
||||
import PlayVideoIcon from '../PlayVideoIcon.html'
|
||||
import { ONE_TRANSPARENT_PIXEL } from '../../_static/media'
|
||||
import { store } from '../../_store/store'
|
||||
import LazyImage from '../LazyImage.html'
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
|
@ -143,13 +146,12 @@
|
|||
}),
|
||||
store: () => store,
|
||||
events: {
|
||||
imgLoad,
|
||||
imgLoadError,
|
||||
mouseover
|
||||
},
|
||||
components: {
|
||||
NonAutoplayGifv,
|
||||
PlayVideoIcon
|
||||
PlayVideoIcon,
|
||||
LazyImage
|
||||
}
|
||||
}
|
||||
</script>
|
Loading…
Reference in a new issue