implement lazy images

This commit is contained in:
Nolan Lawson 2018-03-13 23:07:30 -07:00
parent 9d779a203c
commit 436c8c05aa
3 changed files with 86 additions and 37 deletions

View 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>

View File

@ -17,14 +17,15 @@
playsinline
/>
{{else}}
<img class="{{class}} {{imageError ? 'image-error' : ''}}"
alt="{{label}}"
src="{{imageError ? oneTransparentPixel : staticSrc}}"
width="{{width}}"
height="{{height}}"
on:imgLoad="set({imageLoaded: true})"
on:imgLoadError="set({imageError: true})"
/>
<LazyImage
alt="{{label}}"
src="{{staticSrc}}"
fallback="{{oneTransparentPixel}}"
:width
:height
background="var(--loading-bg)"
className="{{class}}"
/>
{{/if}}
<PlayVideoIcon className="{{playing ? 'hidden' : ''}}"/>
</div>
@ -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>

View File

@ -6,13 +6,14 @@
style="width: {{inlineWidth}}px; height: {{inlineHeight}}px;"
>
<PlayVideoIcon />
<img alt="{{media.description || ''}}"
src="{{imageError ? oneTransparentPixel : media.preview_url}}"
width="{{inlineWidth}}"
height="{{inlineHeight}}"
class="{{noNativeWidthHeight ? 'no-native-width-height' : ''}} {{imageError ? 'image-error' : ''}}"
on:imgLoad="set({imageLoaded: true})"
on:imgLoadError="set({imageError: true})"
<LazyImage
alt="{{media.description}}"
src="{{media.preview_url}}"
fallback="{{oneTransparentPixel}}"
width="{{inlineWidth}}"
height="{{inlineHeight}}"
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}}"
width="{{inlineWidth}}"
height="{{inlineHeight}}"
<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>