UNPKG

vue-coe-image

Version:
193 lines (168 loc) 4.63 kB
/*! * 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; })));