Skip to content

Commit

Permalink
feat!: remove nuxt-picture wrapper
Browse files Browse the repository at this point in the history
simplify nuxt-picture implementation and potential display issues by removing placeholder. supporting placeholder will be back for both img and picture with a wrapper component
  • Loading branch information
pi0 committed Feb 15, 2021
1 parent 51e2e0a commit 8d7d84b
Showing 1 changed file with 38 additions and 178 deletions.
216 changes: 38 additions & 178 deletions src/runtime/components/nuxt-picture.vue
Original file line number Diff line number Diff line change
@@ -1,51 +1,30 @@
<template>
<div class="wrapper__responsive">
<div class="sizer__responsive" :style="{ paddingTop: sizerHeight }" />
<picture>
<source
v-if="nSources[1]"
:key="nSources[1].src"
:type="nSources[1].type"
:srcset="nSources[1].srcset"
:sizes="nSources[1].sizes"
>
<img
v-if="placeholder"
aria-hidden="true"
class="placeholder"
:src="placeholderSrc"
:style="{ opacity: isLoaded ? 0 : 1 }"
:alt="nAlt"
:decoding="decoding"
:referrerpolicy="referrerpolicy"
:usemap="usemap"
:longdesc="longdesc"
:ismap="ismap"
:crossorigin="crossorigin"
:src="nSources[0].src"
:srcset="nSources[0].srcset"
:sizes="nSources[0].sizes"
:loading="loading"
>
<picture v-if="isVisible">
<source
v-if="nSources[1]"
:key="nSources[1].src"
:type="nSources[1].type"
:srcset="nSources[1].srcset"
:sizes="nSources[1].sizes"
>
<img
v-if="isVisible"
class="img"
decoding="async"
:alt="nAlt"
:referrerpolicy="referrerpolicy"
:usemap="usemap"
:longdesc="longdesc"
:ismap="ismap"
:crossorigin="crossorigin"
:src="nSources[0].src"
:srcset="nSources[0].srcset"
:sizes="nSources[0].sizes"
:style="{ opacity: isLoaded ? 1 : 0.01 }"
:loading="isLazy ? 'lazy' : 'eager'"
@load="onImageLoaded"
@onbeforeprint="onPrint"
>
</picture>
</div>
</picture>
</template>

<script lang="ts">
import { generateAlt, getFileExtension, useObserver, parseSize } from '~image'
export const LazyState = {
IDLE: 'idle',
LOADING: 'loading',
LOADED: 'loaded'
}
import { generateAlt, getFileExtension, parseSize } from '~image'
export default {
name: 'NuxtPicture',
Expand All @@ -54,52 +33,36 @@ export default {
src: { type: String, required: true },
// <img> attributes
width: { type: [String, Number], required: false, default: undefined },
height: { type: [String, Number], required: false, default: undefined },
alt: { type: String, required: false, default: undefined },
width: { type: [String, Number], default: undefined },
height: { type: [String, Number], default: undefined },
alt: { type: String, default: undefined },
referrerpolicy: { type: String, default: undefined },
usemap: { type: String, default: undefined },
longdesc: { type: String, default: undefined },
ismap: { type: Boolean, default: false },
crossorigin: { type: Boolean, default: false },
loading: { type: String, default: 'lazy' },
ismap: { type: Boolean, default: undefined },
crossorigin: { type: Boolean, default: undefined },
loading: { type: String, default: undefined },
decoding: { type: String, default: undefined },
// modifiers
format: { type: String, required: false, default: undefined },
legacyFormat: { type: String, required: false, default: undefined },
quality: { type: [Number, String], required: false, default: undefined },
background: { type: String, required: false, default: undefined },
fit: { type: String, required: false, default: undefined },
modifiers: { type: Object, required: false, default: undefined },
format: { type: String, default: undefined },
legacyFormat: { type: String, default: undefined },
quality: { type: [Number, String], default: undefined },
background: { type: String, default: undefined },
fit: { type: String, default: undefined },
modifiers: { type: Object, default: undefined },
// options
preset: { type: String, required: false, default: undefined },
provider: { type: String, required: false, default: undefined },
preset: { type: String, default: undefined },
provider: { type: String, default: undefined },
// extras
placeholder: { type: [Boolean, String], default: false },
sizes: { type: [Object, String], required: false, default: undefined }
},
data () {
const isLazy = this.loading === 'lazy'
return {
isLazy,
lazyState: isLazy ? LazyState.IDLE : LazyState.LOADED
}
sizes: { type: [Object, String], default: undefined }
},
computed: {
ratio () {
return this.nHeight / this.nWidth
},
isVisible () {
if (this.lazyState === LazyState.IDLE) {
return false
}
return true
},
isLoaded () {
return this.lazyState === LazyState.LOADED
},
nAlt () {
return this.alt ?? generateAlt(this.src)
},
Expand Down Expand Up @@ -182,25 +145,7 @@ export default {
if (this.nFormat === 'svg') {
return
}
return this.sources.map(source => `${source.srcset} ${source.width}w`)
},
placeholderSrc () {
if (!this.placeholder) {
return
}
// Custom placeholder src
if (typeof this.placeholder === 'string') {
return this.placeholder
}
const width = 30
return this.$img(this.src, {
...this.nModifiers,
width,
height: this.ratio ? Math.round(width * this.ratio) : undefined
}, this.nOptions)
},
sizerHeight () {
return this.ratio ? `${this.ratio * 100}%` : '100%'
return this.sources.map(source => `${source.srcset} ${source.width}`)
}
},
created () {
Expand All @@ -209,91 +154,6 @@ export default {
// eslint-disable-next-line no-unused-expressions
this.nSources
}
},
mounted () {
if (this.isLazy) {
this.observe()
}
},
beforeDestroy () {
this.unobserve()
},
methods: {
observe () {
this._removeObserver = useObserver(this.$el, type => this.onObservered(type))
},
unobserve () {
if (this._removeObserver) {
this._removeObserver()
delete this._removeObserver
}
},
onImageLoaded (event) {
this.$emit('load', event)
if (this.lazyState !== LazyState.LOADED) {
this.lazyState = LazyState.LOADED
}
},
onObservered (type) {
if (type === 'print') {
return this.onPrint()
}
this.lazyState = LazyState.LOADING
},
onPrint () {
this.lazyState = LazyState.LOADED
this.unobserve()
}
}
}
</script>

<style scoped>
.img {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 0px;
height: 0px;
box-sizing: border-box;
border: none;
margin: auto;
inset: 0px;
display: block;
padding: 0;
min-width: 100%;
max-width: 100%;
min-height: 100%;
max-height: 100%;
transition: opacity 500ms ease 0s;
object-fit: cover;
object-position: center center;
}
.placeholder {
position: absolute;
left: 0;
top: 0;
margin: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-position: center center;
filter: blur(10px);
transition-delay: 500ms;
}
.wrapper__responsive {
display: block;
overflow: hidden;
position: relative;
box-sizing: border-box;
margin: 0;
}
.sizer__responsive {
display: block;
box-sizing: border-box;
}
</style>

0 comments on commit 8d7d84b

Please sign in to comment.