Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <template>
- <div v-if="renderComponent" v-lazyload class="image__wrapper">
- <!-- <ImageSpinner v-if="!src" class="image__spinner" />-->
- <img
- class="image__item"
- :src="src"
- :data-srcset="getSrcset"
- :data-src="dataSrc"
- alt="random image"
- width="100%"
- >
- </div>
- </template>
- <script>
- // uncomment to use the loading spinner instead of the default gif
- import ImageSpinner from './ImageSpinner';
- import LazyLoad from '~/directives/LazyLoad';
- export default {
- name: 'ImageItem',
- // uncomment to use the loading spinner instead of the default gif
- components: {
- ImageSpinner,
- },
- directives: {
- lazyload: LazyLoad,
- },
- props: {
- // Image to lazyload
- source: {
- type: String,
- default: '',
- required: false,
- },
- srcset: {
- type: String,
- default: '',
- required: true,
- },
- // Image while images load
- src: {
- type: String,
- default: '/images/oval.svg',
- required: false,
- },
- dataSrc: {
- type: String,
- required: false,
- },
- },
- data() {
- return {
- renderComponent: true,
- };
- },
- computed: {
- getSrcset() {
- return this.srcset || (this.src ? this.src : 'http://lorempixel.com/640/480');
- },
- },
- watch: {
- source: {
- immediate: false,
- handler() {
- this.forceRerender();
- },
- },
- srcset: {
- immediate: false,
- handler() {
- this.forceRerender();
- },
- },
- },
- methods: {
- forceRerender() {
- // Remove my-component from the DOM
- this.renderComponent = false;
- this.$nextTick(() => {
- // Add the component back in
- this.renderComponent = true;
- });
- },
- },
- };
- </script>
- <style lang="scss">
- .image {
- &__wrapper {
- display: flex;
- justify-content: center;
- align-items: center;
- border-radius: 4px;
- &.loaded {
- .image {
- &__item {
- visibility: visible;
- opacity: 1;
- border: 0;
- }
- &__spinner {
- display: none !important;
- width: 100% !important;
- &.ripple {
- display: none !important;
- width: 100% !important;
- }
- }
- }
- }
- }
- &__item {
- width: 100%;
- /*border-radius: 4px;*/
- transition: all 0.4s ease-in-out;
- /* opacity: 0;
- visibility: hidden; */
- }
- }
- </style>
- //directive
- export default {
- inserted: (el) => {
- function loadImage() {
- const imageElement = Array.from(el.children).find((el) => el.nodeName === 'IMG');
- if (imageElement) {
- imageElement.addEventListener('load', () => {
- setTimeout(() => {
- el.classList.add('loaded');
- // if (!imageElement.dataset.lazy) {
- // el.children[0].remove();
- // }
- }, 100);
- });
- imageElement.addEventListener('error', () => ({}));
- imageElement.src = imageElement.dataset.src;
- imageElement.srcset = imageElement.dataset.srcset;
- // imageElement.src = imageElement.dataset.src;
- }
- }
- function handleIntersect(entries, observer) {
- entries.forEach((entry) => {
- if (!entry.isIntersecting) {
- } else {
- loadImage();
- observer.unobserve(el);
- }
- });
- }
- function createObserver() {
- const options = {
- // circumstances under which the observer's callback is invoked
- root: null, // defaults to the browser viewport if not specified or if null
- threshold: '0', // the degree of intersection between the target element and its root (0 - 1)
- // threshold of 1.0 means that when 100% of the target is visible within
- // the element specified by the root option, the callback is invoked
- };
- // Whether you're using the viewport or some other element as the root,the API works the same way,
- // executing a callback function you provide whenever the visibility of the target element changes
- // so that it crosses desired amounts of intersection with the root
- const observer = new IntersectionObserver(handleIntersect, options);
- observer.observe(el); // target element to watch
- }
- if (!window.IntersectionObserver && typeof IntersectionObserver !== 'function') {
- loadImage();
- } else {
- createObserver();
- }
- },
- };
- //usage
- <LazyImage
- :srcset="activityListing.image_gallery && activityListing.image_gallery.cover_image && activityListing.image_gallery.cover_image.image_url"
- src="https://holobookings.imgix.net/images/image-galleries/rUXblxUtvHZGJwnXtmFlV4BbzngDp9DyieVwHZzp.jpeg?fit=crop&h=200&w=200&auto=format&q=10&blur=100"
- />
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement