Skip to content

Instantly share code, notes, and snippets.

@gisu
Created March 16, 2019 16:04
Show Gist options
  • Save gisu/36ca9a70ca376a042a73b1c98e205798 to your computer and use it in GitHub Desktop.
Save gisu/36ca9a70ca376a042a73b1c98e205798 to your computer and use it in GitHub Desktop.
Vue Wrapper for Imgix
<template>
<figure
class="eg-image relative"
@clicks="clickTransfer()"
>
<div
:class="[bgColorClass, { 'h-full w-full': background, rounded, 'skeleton': showSkeleton}]"
:style="[presized ? styleObject : '']"
>
<no-ssr>
<div
v-if="background && !imageBroken"
ref="imageContainer"
:data-bgset="sources"
:class="{'w-full absolute pin-t pin-r pin-b pin-l max-h-full': presized, rounded, imageClass}"
:style="{ backgroundPosition: bgPosition }"
data-sizes="auto"
class="lazyload bg-no-repeat bg-cover h-full"
@error="imageLoadOnError"
>
<slot v-if="image" />
</div>
<img
v-if="!background && !imageBroken"
ref="imageContainer"
:alt="alt || 'image'"
:data-srcset="sources"
:class="{'w-full absolute pin-t pin-r pin-b pin-l max-h-full': presized, rounded, imageClass}"
data-sizes="auto"
class="lazyload block"
@error="imageLoadOnError"
>
</no-ssr>
</div>
<figcaption
v-if="caption"
class="text-sm py-1"
v-html="caption"
/>
</figure>
</template>
<script>
/**
* Create an Imageblock with responsive Images. Uses Imgix to load the Images
*/
export default {
name: 'EGImage',
props: {
baseUrl: {
type: String,
default: process.env.imgixUrl
},
fit: {
type: String,
default: 'crop' // clamp, crop, max
},
sizes: {
type: Array,
default: () => [2000, 1500, 1000, 600, 320]
},
background: {
type: Boolean,
default: false
},
bgPosition: {
type: String,
default: '50% 50%'
},
bgColorClass: {
type: String,
default: 'bg-grey-medium-darker'
},
aspectRatio: {
type: Number,
default: 0.53
},
params: {
type: String,
default: ''
},
presized: {
type: Boolean,
default: true
},
actualLanguage: {
type: String,
default: 'de'
},
image: {
required: true,
type: [String, Boolean]
},
alt: {
type: String,
default: ''
},
caption: {
type: String,
default: ''
},
rounded: {
type: Boolean,
default: false
},
imageClass: {
type: String,
default: ''
}
},
data () {
return {
styleObject: {
height: '0',
position: 'relative',
overflow: 'hidden',
paddingTop: `${this.aspectRatio * 100}%`
},
imageBroken: false
}
},
computed: {
showSkeleton () {
return !this.image
},
sources () {
if (!this.image) {
this.imageLoadOnError()
return []
}
const buildUrl = (width, ar) => {
const basePath = this.image.startsWith('http') ? this.image : this.baseUrl + this.image
return `${basePath}?fit=${this.fit}&w=${width}&h=${width * ar}${this.params || ''}&auto=compress,format?q=85`
}
const generateImageList = (sizes, ar) => {
return sizes.reduce((imagelist, size) => {
imagelist += `${buildUrl(size, ar)} ${size}w, `
return imagelist
}, '').slice(0, -2)
}
// Build the whole Image Source Block
if (typeof this.sizes[0] === 'object') {
if (this.background) {
return this.sizes.reduce((response, val) => {
response += `${generateImageList(val.sizes, val.ar)} ${
val.maxWidth ? `[(max-width: ${val.maxWidth}px)] | ` : ''
}`
return response
}, '')
}
return generateImageList(this.sizes[0].sizes, this.aspectRatio)
}
return generateImageList(this.sizes, this.aspectRatio)
}
},
mounted () {
this.$el.addEventListener('lazyloaded', (e) => {
this.$emit('finishLoad', true)
})
},
destroyed () {
this.$el.removeEventListener('lazyloaded', {})
},
methods: {
clickTransfer () {
this.$emit('clickTransfer', true)
},
imageLoadOnError () {
this.imageBroken = !this.imageBroken
}
}
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment