Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript Slider doesn't work correctly with transition end

I don't know why people's are not answering this question.I'm making a horizontal infinite loop slider. What approach i'm using is making a ul container which has 3 images, for example if there are 3 images then clone the first image and place it to the end of the slider, same with last image make clone and place it before the first image. So now total images are 5. Default slider translation always start from first image not from clone one. Here is an example. What i'm facing is, I want to reset the slider after slider comes to the last clone image with same continuous loop like a carousel slider. I try using addEventListener with the event name transitionend but that event doesn't perform correctly and showing unsatisfied behavior. Is there a way to fix this?

(function () {
    var resetTranslation = "translate3d(-300px,0px,0px)";
    var elm = document.querySelector('.Working');
    elm.style.transform = resetTranslation;
    var arr = document.querySelectorAll('.Working li');
    var clonefirst,
        clonelast,
        width = 300;
    index = 2;
    clonefirst = arr[0].cloneNode(true);
    clonelast = arr[arr.length - 1].cloneNode(true);

    elm.insertBefore(clonelast, arr[0]);
    arr[arr.length - 1].parentNode.insertBefore(clonefirst, arr[arr.length - 1].nextSibling);
    //Update
    arr = document.querySelectorAll('.Working li');
    elm.style.transition = 'transform 1.5s ease';

    setInterval(function () {

        elm.style.transform = 'translate3d(-' + index * width + 'px,0px,0px)';
        if (index == arr.length - 1) {
            elm.addEventListener('transitionend', function () {
                elm.style.transform = resetTranslation;
            });
            index = 1;
        }
        index++;

    }, 4000)

})();
*{
    box-sizing: border-box;
}
.wrapper{
    position: relative;
    overflow: hidden;
    height: 320px;
    width: 300px;


}

.Working{
    list-style: none;
    margin: 0;
    padding: 0;
    position: relative;
    width: 3125%;


}
.Working li{
    position: relative;
    float: left;
}


img{
    max-width: 100%;
    display: block;
}

.SubContainer:after{
    display: table;
    clear: both;
    content: "";
}
<div class="wrapper">
    <ul class="SubContainer Working">
        <li> <img class="" src="http://i.imgur.com/HqQb9V9.jpg" /></li>
        <li><img class="" src="http://i.imgur.com/PMBBc07.jpg" /></li>
        <li><img  class="" src="http://i.imgur.com/GRrGSxe.jpg" /></li>
    </ul>
</div>
like image 285
hamel123 Avatar asked Mar 24 '17 20:03

hamel123


People also ask

What is transitionend event in CSS?

Definition and Usage. The transitionend event occurs when a CSS transition has completed. Note: If the transition is removed before completion, e.g. if the CSS transition-property property is removed, the transitionend event will not fire.

How do you fire a transition event in JavaScript?

To this, we'll add some JavaScript to indicate that the transitionstart, transitionrun, transitioncancel and transitionend events fire. In this example, to cancel the transition, stop hovering over the transitioning box before the transition ends. For the transition end event to fire, stay hovered over the transition until the transition ends.

Why is my transitionend event not firing?

If the transitioncancel event is fired, the transitionend event will not fire. This event is not cancelable. Use the event name in methods like addEventListener (), or set an event handler property. A TransitionEvent.

What happens if there is no transition delay or duration?

If there is no transition delay or duration, if both are 0s or neither is declared, there is no transition, and none of the transition events are fired. If the transitioncancel event is fired, the transitionend event will not fire. This event is not cancelable.


2 Answers

I've messed around with your code to hack in a fix: https://jsfiddle.net/rap8o3q0/

The changed part:

var currentItem = 1;

setInterval(function () {
    var getWidth = window.innerWidth;

    if(len === currentItem){
        i = 1;
        currentItem = 1;
    } else {
        currentItem++;
        i++;
    }

    var val = 'translate3d(-' + (i-1) * getWidth + 'px,0px,0px)';
    UnorderedListElement.style.transform = val;

}, 3000);
like image 88
rorymorris89 Avatar answered Oct 20 '22 23:10

rorymorris89


Your transition end event is not immediately fire because last transition doesn't computed when last clone image appear. You can easily achieve this thing by using setTimeout function and pass number of milliseconds to wait, after that reset the translation. I don't know it's an efficient solution but i think its easily done by using this function. Now I'm fixing your code with this.

(function () {
    var elm = document.querySelector('.Working');
    var arr = document.querySelectorAll('.Working li');
    var clonefirst,
        clonelast,
        width = 300;
    index = 2;
    clonefirst = arr[0].cloneNode(true);
    clonelast = arr[arr.length - 1].cloneNode(true);

    elm.insertBefore(clonelast, arr[0]);
    arr[arr.length - 1].parentNode.insertBefore(clonefirst, arr[arr.length - 1].nextSibling);
    //Update
    arr = document.querySelectorAll('.Working li');

     setInterval(function () {
        $(elm).css({
            'transform': 'translate3d(-' + (index * width) + 'px,0px,0px)',
            'transition': 'transform 1.5s ease'
        });
        if (index == arr.length - 1) {
            setTimeout(function () {
                $(elm).css({'transform': 'translate3d(-300px,0px,0px)', 'transition': 'none'});
                index = 1;
            }, 1400);

        }
        index++;

    }, 2000)

})();
* {
    box-sizing: border-box;
}

.wrapper {
    position: relative;
    overflow: hidden;
    height: 320px;
    width: 300px;
    margin-top: 8px;

}

.Working {
    list-style: none;
    margin: 0;
    padding: 0;
    position: relative;
    transform: translateX(-300px);
    width: 3125%;

}

.Working li {
    position: relative;
    float: left;
}

img {
    max-width: 100%;
    display: block;
}

.SubContainer:after {
    display: table;
    clear: both;
    content: "";
}

#checkboxer:checked + .wrapper {
    overflow: visible;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="checkboxer">Remove Overflow Hidden</label>
<input type="checkbox" id="checkboxer" name="checkboxer"/>

<div class="wrapper">
    <ul class="SubContainer Working">
        <li> <img class="" src="http://i.imgur.com/HqQb9V9.jpg" /></li>
        <li><img class="" src="http://i.imgur.com/PMBBc07.jpg" /></li>
        <li><img  class="" src="http://i.imgur.com/GRrGSxe.jpg" /></li>
    </ul>
</div>
like image 38
Ahmad Hussnain Avatar answered Oct 21 '22 00:10

Ahmad Hussnain