vue-coe-image
Version:
image-component
193 lines (168 loc) • 4.63 kB
JavaScript
/*!
* vue-coe-image v0.2.4
* (c) 2018-present Vinicius Azevedo <viniazvd@gmail.com>
* Released under the MIT License.
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.VueCoeImage = factory());
}(this, (function () { 'use strict';
var image = {
name: 'vue-coe-image',
props: {
loaderImage: {
type: String,
default: 'https://cdn-images-1.medium.com/max/1600/1*9EBHIOzhE1XfMYoKz1JcsQ.gif'
},
src: {
type: [String, File],
required: true
},
srcset: String,
fallback: {
type: String
},
animation: {
type: Boolean,
default: true
},
delay: {
type: [String, Number],
default: 0
},
blurLevel: {
type: Number,
default: 30
},
duration: {
type: Number,
default: 500
},
intersectionOptions: {
type: Object,
default: function () { return ({}); }
}
},
data: function data() {
return {
rate: 1,
observer: {},
image: null,
imageHandler: null,
hasError: false,
intersected: false
};
},
watch: {
src: 'setSource',
hasError: 'setFallback'
},
created: function created() {
var this$1 = this;
this.image = this.loaderImage;
this.$once('hook:mounted', function () {
setTimeout(function () {
this$1.observer = new IntersectionObserver(function (targets) {
var image = targets[0];
if (image.isIntersecting) {
this$1.intersected = true;
this$1.setImage();
this$1.observer.disconnect();
this$1.$emit('intersect');
}
}, this$1.intersectionOptions);
this$1.observer.observe(this$1.$el);
}, this$1.delay);
});
this.$once('hook:beforeDestroy', function () {
setTimeout(function () {
this$1.observer.unobserve(this$1.$el);
}, this$1.delay);
});
},
computed: {
deviation: function deviation() {
return this.blurLevel * this.rate;
}
},
methods: {
setSource: function setSource(x, y) {
if (x !== y) {
this.hasError = false;
this.setImage();
}
},
setFallback: function setFallback(status) {
if (status) { this.image = this.fallback; }
},
handleLoad: function handleLoad() {
this.image = this.imageHandler.src;
this.animation && this.animate();
},
handleError: function handleError() {
if (!this.fallback) {
console.warn('an error occured during the image loading');
}
this.hasError = true;
this.$emit('error');
},
setImage: function setImage() {
this.imageHandler = new Image();
this.imageHandler.src = this.src || this.placeholder;
this.imageHandler.onload = this.handleLoad;
this.imageHandler.onerror = this.handleError;
},
animate: function animate() {
var this$1 = this;
var start = Date.now() + this.duration;
var step = function () {
var remaining = start - Date.now();
if (remaining < 0) {
this$1.rate = 0;
} else {
this$1.rate = remaining / this$1.duration;
requestAnimationFrame(step);
}
};
requestAnimationFrame(step);
}
},
render: function render(h) {
var feGaussianBlur = h('feGaussianBlur', {
attrs: {
in: 'SourceGraphic',
stdDeviation: this.deviation
}
});
var filter = h('filter', {
attrs: {
id: 'blur'
}
}, [feGaussianBlur]);
var defs = h('defs', null, [filter]);
var svg = h('svg', {
class: ['filter-defs-svg hidden'],
attrs: {
xmlns: 'http://www.w3.org/2000/svg',
version: '1.1'
}
}, [defs]);
var image = h('img', {
ref: 'img',
class: 'lazy-load-image',
style: ("url(" + (this.image) + ")"),
attrs: {
src: this.image
}
});
return h('div', {
class: 'vue-coe-image'
}, [!this.hasError && this.intersected && svg, image]);
},
install: function install(Vue) {
Vue.component('VueCoeImage', image);
}
};
return image;
})));