Simple Vue Image Components
by Anurak Sumranphan
HTML
<div id="app">
<v-image
src="https://cdn.vuetifyjs.com/images/cards/desert.jpg"
:aspect-ratio="1.77"
>
</v-image>
</div>
CSS
body {
background: #1c2128;
padding: 20px;
font-family: Helvetica, Arial, sans-serif;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
width: 300px;
transition: all 0.2s;
}
.v-image {
background-color: #000000;
background-position: center center;
background-size: cover;
background-repeat: no-repeat;
}
Vue
function convertToUnit (size, unit = 'px') {
return `${size}${unit}`
}
Vue.component('v-image', {
props: {
src: String,
lazySrc: String,
height: [Number, String],
width: [Number, String],
minWidth: [Number, String],
minHeight: [Number, String],
maxWidth: [Number, String],
maxHeight: [Number, String],
aspectRatio: Number
},
data: function () {
return {
tag: 'div',
calculatedRatio: null
}
},
computed: {
styles: function () {
let styles = {}
if (this.src) styles.backgroundImage = 'url(' + this.src + ')'
if (this.height) styles.height = convertToUnit(this.height)
if (this.width) styles.width = convertToUnit(this.width)
if (this.minWidth) styles.minWidth = convertToUnit(this.minWidth)
if (this.minHeight) styles.minHeight = convertToUnit(this.minHeight)
if (this.maxWidth) styles.maxWidth = convertToUnit(this.maxWidth)
if (this.maxHeight) styles.maxHeight = convertToUnit(this.maxHeight)
if (this.calculatedRatio) {
styles.paddingBottom = this.calculatedRatio
}
return styles
},
calculateRatio: function () {
const aspectWidth = this.$parent.$el.offsetWidth
const aspectHeight = aspectWidth / this.aspectRatio
const percent = (aspectHeight / aspectWidth) * 100
return `${percent}%`
}
},
mounted () {
this.$nextTick(function () {
this.calculatedRatio = this.calculateRatio
});
},
render: function (h) {
const data = {
class: 'v-image',
style: this.styles
}
return h(this.tag, data, this.$slots.default)
}
})
new Vue({
el: "#app"
})