SSENSE / vue-carousel

A flexible, responsive, touch-friendly carousel for Vue.js
https://ssense.github.io/vue-carousel/
MIT License
1.72k stars 505 forks source link

When page is opened image in vue-carousel is not visible. Need to click. #444

Open PetroGromovo opened 5 years ago

PetroGromovo commented 5 years ago

Bug Report

Hello, Working with Laravel 5.7 / Vuejs 2.6 / Bootstrap 4.3 app I use "vue-carousel": "^0.18.0" I have a problem that defing carousel with images at page opening the page is not visible at all. But if to click on the empty image space then image is visible and carousel works ok. in vue file :


                    <div class="pull-left" style="max-width: 350px;">
                        <carousel
                                v-show="hostelImages.length"
                                :centerMode="false"
                                :perPage="1"
                                :navigationEnabled="true"
                                paginationColor="#7e7e7e"
                                paginationPosition="bottom"
                                class="m-4"
                                zIndex= "100 !important"
                        >
                            <slide v-for="nextHostelImage, index in hostelImages" :key="nextHostelImage.id">
                                <img :src="nextHostelImage.filenameData.image_url" :alt="nextHostelImage.filename" style="width:320px; height : auto; ">
                                <p class="description-text pl-5 pr-5">
                                    {{ nextHostelImage.info }}
                                </p>
                            </slide>
                        </carousel>

                        <a class="a_link" href="/images/emptyImg.png" v-show="!hostelImages.length">
                            <!--{{  "?dt=".time()  }}-->
                            <img class="single_vote_image_left_aligned" src="/images/emptyImg.png" alt="alt text">
                        </a>
                    </div>

                    <p class="card-text mt-3 description-text" v-html="hostelRow.descr"></p>
                    ...

<script>
    import {bus} from '../../../app';
    import appMixin from '../../../appMixin';
    import hostelsMixin from '../../../hostelsMixin';
    import {Carousel, Slide} from 'vue-carousel';

    export default {

        components: {
            Carousel,
            Slide
        },

...
<style scoped lang="css">

   #container {
      padding: 0 60px;
   }

   .VueCarousel-slide {
      position: relative;
      background: #42b983;
      border: 2px dotted green;
      color: #fff;
      font-size: 24px;
      text-align: center;
      min-height: 100px;
   }

   .label {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
   }

</style>

Why error and how to fix it ?

Thanks!

Environment

Additional context/Screenshots You can look at it live : http://hostels-tours.nilov-sergey-demo-apps.tk/hostel/new-hostel-test21/south-australia/far-north/adelaide-1

PetroGromovo commented 5 years ago

Searching for a decision I found vue-focus directive. I installed it to my app and checking it on simple text input I see that it works ok. I tried to use it in carousel component as :


                        <carousel
                                v-show="hostelImages.length"
                                :centerMode="false"
                                :perPage="1"
                                :navigationEnabled="true"
                                paginationColor="#7e7e7e"
                                paginationPosition="bottom"
                                class="m-4"
                                zIndex= "100 !important"
                        >
                            <slide v-for="nextHostelImage, index in hostelImages" :key="nextHostelImage.id">
                                <img
                                        :src="nextHostelImage.filenameData.image_url"
                                        :alt="nextHostelImage.filename"
                                        style="width:320px; height : auto; "
                                        v-focus.lazy="true"
                                >
                                <p class="description-text pl-5 pr-5">
                                    {{ nextHostelImage.info }}
                                </p>
                            </slide>
                        </carousel>

OR

                        <carousel
                                v-show="hostelImages.length"
                                :centerMode="false"
                                :perPage="1"
                                :navigationEnabled="true"
                                paginationColor="#7e7e7e"
                                paginationPosition="bottom"
                                class="m-4"
                                zIndex= "100 !important"
                                v-focus.lazy="true"
                        >
                            <slide v-for="nextHostelImage, index in hostelImages" :key="nextHostelImage.id">
                                <img
                                        :src="nextHostelImage.filenameData.image_url"
                                        :alt="nextHostelImage.filename"
                                        style="width:320px; height : auto; "
                                >
                                <p class="description-text pl-5 pr-5">
                                    {{ nextHostelImage.info }}
                                </p>
                            </slide>
                        </carousel>

But in both cases I do not see images on page opened.

2) If there is a way to simulate click of a mouse on carousel's image?

3) Testing in browser I noticed that when I change device in browse I see that my carousel's image becomes visible. Can that be decision for my problem ?

LouBNielsen commented 5 years ago

@PetroGromovo I have the exact same issue.. Did you find another solution so you did'nt have to simulate a maouse click?

LouBNielsen commented 5 years ago

Found another one who had the same problem: try: style="visibility: visible; flex-basis: 522px;"

or

.VueCarousel-slide { visibility: visible; flex-basis: 100%; width: 100%; }

le0park commented 5 years ago

I have a same problem, and find some trick. I think the problem is, window doesn't fire resize event when image loaded.

Try :

var resizeEvent = window.document.createEvent('UIEvents');
resizeEvent.initUIEvent('resize', true, false, window, 0);
window.dispatchEvent(resizeEvent);

inside of mounted hook function.

damienmcd commented 5 years ago

I've found a hacky workaround for this but I 100% think this issue needs to be fixed properly. My workaround is to call the $forceUpdate() in the mounted hook on a timeout. The timeout should be longer than the time it takes for all of the carousel's content to load.

mounted() {
    setTimeout(() => {
      this.$forceUpdate()
    }, 4000)
}

This will force the component to re-render. NOTE This does not just re-render the carousel, it re-renders the component in which the vue-carousel is being used. Again, this is not a permanent workaround and I recommend that it is not used in a production environment.

lennoximus commented 5 years ago

@damienmcd can't you just put a ref on carousel and call $forceUpdate in the carousel itself?

Also, talking about "magic numbers" with usage of setTimeout: in case we are dealing with images (img tags to be sure) you can apply this kind of stuff using load event, so carousel only updates when images are really loaded by the browser.

damienmcd commented 5 years ago

Hi @lennoximus. Thanks for your suggestion, you're correct that using a ref on the carousel and just calling the forceUpdate on that is a better way to handle the re-render of the carousel. I don't know how I didn't think of that. Maybe it was the Friday afternoon brain switching off!

With regard to using the load event, this is not called if the images are loaded from the cache so I may have to create the images with a new Image() and bind a load event listener to them.

Anyway, hopefully the actual issue can be fixed by the vue-carousel devs soon so we don't have to be hacking around with alternatives.

damienmcd commented 5 years ago

A quick update on this. Adding a ref to the vue-carousel and calling $forceUpdate() on that does not resolve this issue. It works on Chrome sometimes but not on IE11, which I need it to work on. I'm still looking for a fix for this and I'll post my findings here if I manage to get it working.

kubmin commented 5 years ago

Hi all. I've had the same problem and came up with a "hacky" solution using the imagesLoaded directive from here.

Basically you use the directive to detect if the images have loaded. If they did, use the $forceUpdate function in the imagesLoaded callback to update the carousel accordingly.

Hope this helps!

<template>
    <carousel v-images-loaded="imageLoaded" ref="carousel">
        <slide v-for="(photo, index) in photos" :key="index">
           <img :src="photo.file"/>
        </slide>
    </carousel>
</template>

<script>
    export default {
        methods: {
            imageLoaded() {
                console.log('force load');
                this.$refs.carousel.$forceUpdate()
            },
        },
    }
<script>
JonikUl commented 4 years ago

Hi all! My solution without $forceUpdate(). Use vue-carousel computeCarouselWidth() method.

<carousel
  :perPage="1"
  :paginationEnable="true"
  paginationColor="#b3b3b3"
  paginationActiveColor="#494ce8"
  ref="carousel"
>
  <slide v-for="(slide, index) in product.gallery" :key="index">
    <img :src="slide.img" :alt="slide.name" />
  </slide>
</carousel>
mounted () {
    setTimeout(this.$refs.carousel.computeCarouselWidth, 300)
}
NOPROD commented 4 years ago

@kubmin Thanks, you save me

JonikUl commented 4 years ago

@kubmin Thanks, you save me

good luck)

g-merrill commented 4 years ago

@JonikUl Thank you so much! This simple solution worked for me.

JonikUl commented 4 years ago

@JonikUl Thank you so much! This simple solution worked for me.

TU, glad that helped

danialvesb commented 3 years ago

With just this class my problem was solved:

.VueCarousel {
  width: 100%;
  height: 100%;
}
Rahulojhaiit commented 3 years ago

Hi everyone. I inspected that the carousel which was not visible due to visiblity:hidden style property on the div with class "Vue-carousel-inner". So I removed it by DOM Manipulation after loading data in carousel.

setTimeout(() => { document.getElementsByClassName("VueCarousel-inner")[0].style.visibility = 'visible' }, 10)

This solved my problem.

albertoc17 commented 3 years ago

I have a same problem, and find some trick. I think the problem is, window doesn't fire resize event when image loaded.

Try :

var resizeEvent = window.document.createEvent('UIEvents');
resizeEvent.initUIEvent('resize', true, false, window, 0);
window.dispatchEvent(resizeEvent);

inside of mounted hook function.

This works for me! and and then assign this function to @click

    updateCarrusel() {
     const resizeEvent = window.document.createEvent('UIEvents');
    resizeEvent.initUIEvent('resize', true, false, window, 0);
     window.dispatchEvent(resizeEvent);
   },
dcgitx commented 1 year ago

My go at same problem 2023 - not great, works for me though with ref on the carousel as per the docs...

https://ismail9k.github.io/vue3-carousel/api/methods.html

const myCarousel = ref(null);

onMounted(()=>{
    setTimeout(() => {
        myCarousel.value.updateSlideWidth();
    }, 400);
});