Search code examples
jquerycarousel

Jquery simple image rotation depending on rollover - left or right - how to make this continious?


I am learning Jquery and have a simple image rotation script that shows three images and allows you on mouse over to put one image in the centre and shift the rest accordingly depending if the mouse is on the left or on the right. I am ok on how it works from the right, but not from the left. Both images just pop up suddenly, but from the right it somehow works better, and the left transition is jarring. Any ideas?

And secondly and more importantly, I need to make this rotation continuous. Once the images are rotated, and the mouse leaves and enters again on either left or the right image I need to do the rotation again. What is the best way to go about that? I tried to create .left .center and .right classes and reassign them at the end of each animation but that does not seem to be working.

JS Fiddle - https://jsfiddle.net/unata/4km5cf0r/

<div class="featured_listings">
  <div id="carousel">


<div><img src="https://via.placeholder.com/200/808080/000000?text=roll over me"></div>
<div><img src="https://via.placeholder.com/200/0000CC/000000?Text=div2"></div>
<div><img src="https://via.placeholder.com/200/00CCCC/000000?text=roll over me"></div>

</div>
</div>

Jquery:

$('#carousel div:nth-child(2)').addClass('selected'); 
//put orange border around the selected item            


var div_widthtotal = 230; 
var ijustmoved=0; 
$("#carousel div:nth-child(1)").addClass("left"); 
$("#carousel div:nth-child(2)").addClass("center"); 
$("#carousel div:nth-child(3)").addClass("right"); 


$(".right").mouseenter(function() {
        $(this).addClass('selected'); 
        $(this).siblings().removeClass('selected'); 
    //this is to stop the hover effect from repeating
        if (ijustmoved ==0) {
        $("#carousel").animate({marginLeft: -div_widthtotal}, function(){
            $(".left").clone().insertAfter(".right"); 
            //don't move me anymore
            ijustmoved=1; 
        });         
        }
    });

    $(".left").mouseenter(function() {
        $(this).addClass('selected'); 
            $(this).siblings().removeClass('selected'); 
    if (ijustmoved ==0) {
        //on animation clone the left div 
        $("#carousel").animate({marginLeft: div_widthtotal}, function(){
            $(".right").clone().insertBefore(".left"); 
            $("#carousel").css('margin-left', 0);  
            //don't move me anymore
            ijustmoved=1; 
        });         
        }


    });

Solution

  • This should help a bunch. It's not perfect yet. There are still some issues with the margin animation switching to zero at the wrong times occasionally. But it's a significant improvement.

    The key to continuous animation was setting up the rollover again on your clones after you add them to the DOM.

    $('#carousel div:nth-child(2)').addClass('selected'); 
    //put orange border around the selected item            
    
    var div_widthtotal = 230; 
    $("#carousel div:nth-child(1)").addClass("left"); 
    $("#carousel div:nth-child(2)").addClass("center"); 
    $("#carousel div:nth-child(3)").addClass("right"); 
    
    function setupRight(el)
    {
      el.unbind('mouseenter.roll').bind('mouseenter.roll', function() {
        el.addClass('selected'); 
        el.siblings().removeClass('selected');
        //on animation clone the left div and remove all the classes)
        $("#carousel").animate({marginLeft: -div_widthtotal}, function()
        {
          $("#carousel div:nth-child(1)").clone().insertAfter("#carousel div:nth-child(3)"); 
          $("#carousel").css('margin-left', 0);  
          setupRight($("#carousel div:nth-child(4)"));
          $("#carousel div:nth-child(1)").empty().remove();
          setupLeft($("#carousel div:nth-child(1)"));
          //don't move me anymore
          el.unbind('mouseenter.roll');
        });
      });
    }
    
    function setupLeft(el)
    {
      el.mouseenter(function() {
        el.addClass('selected'); 
        el.siblings().removeClass('selected');
        //on animation clone the left div 
        $("#carousel").animate({marginLeft: div_widthtotal}, function(){
          $("#carousel div:nth-child(3)").clone().insertBefore("#carousel div:nth-child(1)"); 
          $("#carousel").css('margin-left', 0);  
          $("#carousel div:nth-child(4)").empty().remove();
          setupRight($("#carousel div:nth-child(3)"));
          setupLeft($("#carousel div:nth-child(1)"));
          //don't move me anymore
          el.unbind('mouseenter.roll');
        });
      });
    }
    
    setupRight($("#carousel div:nth-child(3)"));
    setupLeft($("#carousel div:nth-child(1)"));
    

    EDIT - 2020-02-06

    I think this below is now the way you needed it. No payment required. It was fun. You'll probably need to modify it a little for a real-world scenario (particularly the jQuery selectors, like 'img', which are certainly too broad), but hopefully this points you where you need to go.

    HTML

    <div class="featured_listings">
      <div id="carousel">
        <div class="imgWrp">
          <img src="https://via.placeholder.com/200/808080/000000?text=One">
          <img src="https://via.placeholder.com/200/0000CC/000000?Text=Two">
          <img src="https://via.placeholder.com/200/00CCCC/000000?text=Three">
        </div>
      </div>
    </div>
    

    CSS

    html, body {
      margin: 0;
      padding: 0;
    }
    
    
    .featured_listings {
      width: 70%;
      max-width: 940px; 
      margin: auto; 
      margin-top: 10%; 
      overflow: hidden; 
    }
    
    #carousel{
      display: inline-block;
      width: 100%;
      max-width: 100%;
      padding: 1em 0;
      margin: 0;
      overflow: hidden;
      white-space: nowrap;
    }
    
    .featured_listings img {
      max-width: 200px; 
      margin: 0 1em;
    
    }
    
    .imgWrp {
      display: inline-block;
    }
    
    .selected {
      -moz-transform: scale(1.08);
      -ms-transform: scale(1.08);
      -o-transform: scale(1.08);
      -webkit-transform: scale(1.08);
      border: 5px solid #e67e22;
      transform: scale(1.08);
      transition: all ease-in-out .3s;
    }
    

    JS

    $(function() {
      //put orange border around the selected item
      $('#carousel .imgWrp img:nth-child(2)').addClass('selected');
    
      // Set margin amount
      var div_widthtotal = 230;
    
      // Find and create jQuery elements
      var carousel = $('#carousel');
      var imgWrp = $('.imgWrp');
      var newFirst = $('#carousel .imgWrp img:first-child').clone();
      var newSecond = $('#carousel .imgWrp img:nth-child(2)').clone();
      var newThird = $('#carousel .imgWrp img:last-child').clone();
    
        // This function places the images in the correct location
      function scrollToCenter(ms)
      {
        var img = carousel.find('img.selected');
        var desiredCenter = img[0].offsetLeft;
        var actualCenter = carousel.width() / 2;
        var lftScroll = desiredCenter - actualCenter;
        carousel.animate({
          scrollLeft: lftScroll
        }, ms);
      }
    
        // This is the on-mouse-enter function
      function onMouseenter(el)
      {
        if (el.index() == 1)
        {
            var newFirst = $('#carousel .imgWrp img:last-child');
          newFirst.css("margin-right", 0);
          newFirst.css("margin-left", -newFirst.width() + 'px');
          $('#carousel .imgWrp img:first-child').before(newFirst);
          el.addClass('selected');
          el.siblings().removeClass('selected');
          newFirst.animate({ 'marginLeft': '1em', 'marginRight': '1em' }, 400);
        }
        else if (el.index() == 3)
        {
          $('#carousel .imgWrp img:last-child').after($('#carousel .imgWrp img:first-child'));
          scrollToCenter(0);
          el.addClass('selected');
          el.siblings().removeClass('selected');
          scrollToCenter(400);
        }
      }
    
        // This is where all images will be bound to the mouse-enter function at one time
      function bindImgs()
      {
        $('img').each(function(i, img){
          var el = $(img);
          el.unbind('mouseenter.roll').bind('mouseenter.roll', function(e){
            // First, turn off mouse-enter functionality
            $('img').unbind('mouseenter.roll');
            // Next, run the process to move the images around
            onMouseenter(el);
          });
        });
      }
    
        // Make it so the user can re-activeate the mouse-enter functionality when they leave the scroller
      carousel.unbind('mouseleave.scroller').bind('mouseleave.scroller', function(e){
        bindImgs();
      });
    
        // Additional setup
      $('#carousel .imgWrp img:last-child').after(newFirst);
      $('#carousel .imgWrp img:last-child').after(newSecond);
      $('#carousel .imgWrp img:first-child').before(newThird);
    
      // Launch functionality
      scrollToCenter(0);
      bindImgs();
    });