Skip to content

Instantly share code, notes, and snippets.

@regenrek
Created July 28, 2020 02:23
Show Gist options
  • Save regenrek/f053917485463bbc99632c13ed9ca9b1 to your computer and use it in GitHub Desktop.
Save regenrek/f053917485463bbc99632c13ed9ca9b1 to your computer and use it in GitHub Desktop.
#### USAGE
<aspect-ratio-image class="max-w-80" :imageSrc="person.image[0].image" :aspectRatio="person.image[0].aspect_ratio" />
#### AspecRatioImage Component
<template>
<figure
:class="[
objectFit !== '' ? 'is-' + objectFit : '',
'aspect-ratio-image',
`aspect-ratio-${aspectRatio}`
]"
>
<picture>
<source
v-for="(option, i) in options"
:key="i"
:srcset="!lazy && getSourceSet(option)"
:data-srcset="lazy && getSourceSet(option)"
:media="option.media"
:type="option.type"
>
<img
:src="!lazy && getPath({ width: 1920 })"
:data-src="lazy && getPath({ width: 1920 })"
:class="[imgClasses]"
>
</picture>
</figure>
</template>
<script>
export default {
props: {
imageSrc: {
type: String,
default: ''
},
objectFit: {
type: String,
default: 'cover'
},
lazy: {
type: Boolean,
default: false
},
options: {
type: Array,
default: () => [
{ type: 'image/webp', media: '(min-width: 1240px)', width: '1920' },
{ type: 'image/webp', media: '(min-width: 1024px)', width: '1240' },
{ type: 'image/webp', media: '(min-width: 768px)', width: '1024' },
{ type: 'image/webp', media: '(min-width: 568px)', width: '768' },
{ type: 'image/webp', media: false, width: '568' },
{ type: false, media: '(min-width: 1240px)', width: '1920' },
{ type: false, media: '(min-width: 1024px)', width: '1240' },
{ type: false, media: '(min-width: 768px)', width: '1024' },
{ type: false, media: '(min-width: 568px)', width: '768' },
{ type: false, media: false, width: '568' }
]
},
aspectRatio: {
type: String,
default: '16/9'
}
},
computed: {
imgClasses () {
return { lazyload: this.lazy, preview: this.placeholder }
}
},
methods: {
getSourceSet (options) {
const sizes = [1]
return sizes.map(
size =>
`${this.getPath({
...options,
width: options.width * size
})} ${size}x`
)
},
getPath (options) {
const imageService = '//img2.storyblok.com/'
const src = this.imageSrc
let path = src.replace('//a.storyblok.com', '')
path = path === src ? src.replace('//a.storyblok.com', '') : path
const filters = this.getFilters(options)
const dimensions = this.getDimensions(options)
return [imageService, dimensions, filters, path].join('')
},
getFilters (options) {
const filters = ['/filters']
if (options.type) {
filters.push(':format(webp)')
}
return filters.length > 1 ? filters.join('') : ''
},
getDimensions (options) {
const [width, height] = this.aspectRatio.split('/')
const ratio = height / width
return `${options.width}x${Math.floor(options.width * ratio)}`
}
}
}
</script>
<style lang="postcss" scoped>
figure {
overflow: hidden;
position: relative;
display: block;
margin: 0;
}
figure img {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
transform: translate(-50%, -50%);
}
figure.is-cover img {
object-fit: cover;
font-family: "object-fit: cover";
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment