简体   繁体   中英

Slider animation handle with JQuery, hover element issue using promises

I have problem with a slider. It works correctly without one, strange for me, situation. When I mouseover fast from one dot to another, it will not wait until previous animation ends and two texts overlap. Can somebody older and wiser help me?

HTML structure of project:

<section class="product-section">
<div class="vertical-text vertical-text-custom-5">
    Pluginy
</div>
<div class="carrousel-image-container-1 product-release-management">
    <i class="image-carrousel-1"></i>
</div>
<div class="carrousel-image-container-2 product-SLA">
    <i class="image-carrousel-2"></i>
</div>
<div class="carrousel-image-container-3 product-test-management">
    <i class="image-carrousel-3"></i>
</div>
<div class="col-custom-5">
    <div class="col-custom-7 text-size-xl">
        <div class="text-container-17">
            <div class="product product-release-management">
                <span class="text-color-6 text-weight-thin">Rivet</span> <br>
                <span class="text-color-5 text-weight-bold">Release Management</span> <br>
                <span class="text-color-3 text-weight-bold">plugin</span>
            </div>
            <div class="product product-SLA">
                <span class="text-color-6 text-weight-thin">Rivet</span> <br>
                <span class="text-color-5 text-weight-bold">SLA</span> <br>
                <span class="text-color-3 text-weight-bold">plugin</span>
            </div>
            <div class="product product-test-management">
                <span class="text-color-6 text-weight-thin">Rivet</span> <br>
                <span class="text-color-5 text-weight-bold">Test Management</span> <br>
                <span class="text-color-3 text-weight-bold">plugin</span>
            </div>
        </div>
        <div id="carrousel-dots-contener" class="carrousel-dots text-color-5">
            <div class="dot-container" data-carrousel-dot='dot-1'>
                <div class="dot-border">
                    <div class="dot dot-custom-2">&#9679;</div>
                </div>
            </div>
            <!--
                 -->
            <div class="dot-container" data-carrousel-dot='dot-2'>
                <div class="dot-border">
                    <div class="dot dot-custom-2">&#9679;</div>
                </div>
            </div>
            <!--
                 -->
            <div class="dot-container" data-carrousel-dot='dot-3'>
                <div class="dot-border">
                    <div class="dot dot-custom-2">&#9679;</div>
                </div>
            </div>
        </div>
    </div>
</div>

REST OF CODE HERE

These are the main issues:

  • The promise() call works fine when you are sure you don't need to interrupt the animation, but as soon as you have mouse events that need immediate action (like hideAll ), this promise will become a problem: it will still resolve, but at an inconvenient moment. In fact, as soon as you do another animation like hideAll , you want to cancel the execution of the code that follows the resolved promise. So... add a condition before proceeding with fadeIn() to see that the product selection is still relevant.

  • runInterval calls cyclicChange immediately, which is great when the page loads, but which is a bit annoying when moving the mouse over one dot to the next: as the mouse may exit the area, runInterval gets called and makes the selection jump to potentially another dot, which makes it kinda jumpy. It is better to remove this immediate call to cyclicChange and then to add some code to show the first product when start runs.

  • To avoid unwanted queuing of animations, you could call stop(true) before doing fadeOut() .

I applied these changes to your JavaScript code, where I also made some other improvements, unrelated to the problem:

var carrousel = (function() {

    var interval = null,
        products,
        current = -1;

    products = [
        '.product-release-management',
        '.product-SLA',
        '.product-test-management'
    ];

    function showProduct(id) {
        // Avoid unnecessary work
        if (id == current) return; // nothing to do;
        // In other cases: hide first
        hideAll();
        current = id;
        $('.product').promise().done(function() {
            // Make sure selection is still like at the start of showProduct execution
            if (current === id) $(products[current]).fadeIn(500);
        });
        $("div[data-carrousel-dot='dot-" + (current + 1) + "']").addClass('dot-active');
    }        
    function hideAll() {
        // 1. easier selector for selecting all product classes
        // 2. stop any ongoing animation
        $(products.join(",")).stop(true, true).fadeOut(500); 
        $("div[data-carrousel-dot").removeClass('dot-active');
    }
    function cyclicChange() {
        if ( isNaN(interval) ) return; // timer is not active
        showProduct((current + 1) % products.length); // easier way to roundtrip
    }
    function runInterval(){
        interval = setInterval(cyclicChange, 3000); 
    }
    function mouseOverDotHandler() {
        $('.dot-container').hover(    
            function() {
                // Easier way to get number
                showProduct($(this).index());
            }
        );

        $('#carrousel-dots-contener').hover(
            function(){
                clearInterval(interval);
                interval = null; // use variable for indicating the pause
            },
            runInterval
        );
    }

    return {
        start: function() {
            showProduct(0);
            runInterval();
            mouseOverDotHandler();
        }
    }
})();

$(document).ready(function(){
    carrousel.start();
});

See it run on jsbin.com .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM