skip to Main Content

I’m trying to create a tile-like content carousel for a website I’m creating. Basically I need the ordinary content carousel functionality that comes in a lot of different jQuery plug-ins etc. – but instead of the slider being linear, I need the items to shift tiles in a circular manner like this:

Step 1:
enter image description here

Step 2:
enter image description here

Step 3:
enter image description here

I tried creating the setup using Flexbox and some simple jQuery:

$(document).ready(function () {
  
  $(".item").each(function (index) {
    $(this).css("order", index);
  });

  $(".prev").on("click", function () {
    // Move all items one order back

    $(".item").each(function (index) {
      var currentOrder = parseInt($(this).css("order"));
      if (currentOrder == undefined) {
        currentOrder = index;
      }
      var newOrder = currentOrder - 1;
      if (newOrder < 0) {
        newOrder = 5;
      }
      $(this).css("order", newOrder);
    });
  });

  $(".next").on("click", function () {
    // Move all items one order forward

    $(".item").each(function (index) {
      var currentOrder = parseInt($(this).css("order"));
      var newOrder = currentOrder + 1;

      if (newOrder > 5) {
        newOrder = 0;
      }
      $(this).css("order", newOrder);
    });
  });
});
.container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  width: 500px;
}

.item {
  width: 125px;
  height: 75px;
  color: white;
  text-align: center;
  font-size: 24px;
  border: 1px solid white;
  padding-top: 50px;
  box-sizing: content-box;
  background-color: rgb(42, 128, 185);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

        <button class="prev">Prev</button>&nbsp;
        <button class="next">Next</button>&nbsp;

        <div class="container">
            <div class="item one">1</div>
            <div class="item two">2</div>
            <div class="item three">3</div>
            <div class="item four">4</div>
            <div class="item five">5</div>
            <div class="item six">6</div>
        </div>

but this leaves me with some unresolved issues:

  1. How do I animate the tiles when changing the order (when clicking next/prev)?
  2. How do I fix the order so that the items move in a continuous line instead of wrapping to the start of next line (I’d like the order to be like displayed in step 2 -> 3)?

Any existing plug-in (I’ve looked but can’t find any) or codepen etc. would be very much appreciated as I’m not sure if my approach is maintainable (or even doable).

Thanks a bunch 🙂

2

Answers


  1. This kind of carousel ?

    const
      containerBox   = document.querySelector('#container')
    , nextOrder = [3,0,1,4,5,2]
    , prevOrder = [1,2,5,0,3,4]
      ;
    next.onclick =_=>
      {
      let divs = [...containerBox.querySelectorAll('div')]
      nextOrder.forEach(n=> containerBox.appendChild( divs[n]) )
      }
    prev.onclick =_=>
      {
      let divs = [...containerBox.querySelectorAll('div')]
      prevOrder.forEach(n=> containerBox.appendChild( divs[n]) )
      }
    #container {
      display        : flex;
      flex-direction : row;
      flex-wrap      : wrap;
      width          : 500px;
      margin : 20px;
      }
    #container > div {
      width       : 125px;
      height      : 75px;
      color       : white;
      text-align  : center;
      font-size   : 24px;
      border      : 1px solid white;
      padding-top : 50px;
      box-sizing  : content-box;
      background  : #2a80b9;
    }
    <button id="prev">Prev</button> 
    <button id="next">Next</button> 
    
    <div id="container">
        <div> 1 </div>
        <div> 2 </div>
        <div> 3 </div>
        <div> 6 </div>
        <div> 5 </div>
        <div> 4 </div>
    </div>
    Login or Signup to reply.
  2. I’ve used absolute position formula from index to (top, left). Then i’ve used jQuery to animate that. That’s lame but can be improved if that’s an issue. It looks nice.

    const containerBox = document.querySelector('#container')
    let divs = [...containerBox.querySelectorAll('div')]
    var size = 100
    var margin = 2
    
    function get_top_left(pos) {
      if (pos < divs.length / 2) {
        return {
          left: pos * size + margin * (pos),
          top: 0
        }
      } else {
        return {
          left: (divs.length - pos - 1) * size + margin * (divs.length - pos - 1),
          top: size + margin
        }
      }
    }
    
    var offset = 0
    
    function draw() {
    
      divs.forEach(function(div, index) {
        var len = divs.length
        index = ((index + offset) % len + len) % len
        var pos = get_top_left(index);
        //div.style.left = pos.left + "px"
        //div.style.top = pos.top + "px"
        $(div).animate({
          "left": pos.left + "px",
          "top": pos.top + "px"
        })
      })
    
    }
    
    next.onclick = _ => {
      offset += 1
      draw()
    }
    prev.onclick = _ => {
      offset -= 1
      draw()
    }
    
    draw();
    #container {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
      width: 500px;
      height: 260px;
      margin: 10px;
      position: relative;
    }
    
    #container>div {
      width: 100px;
      height: 66px;
      color: white;
      text-align: center;
      font-size: 24px;
      border: 1px solid white;
      padding-top: 34px;
      box-sizing: content-box;
      background: #2a80b9;
      position: absolute;
      top: 0;
      left: 0;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <button id="prev">Prev</button>
    <button id="next">Next</button>
    
    <div id="container">
      <div> 1 </div>
      <div> 2 </div>
      <div> 3 </div>
      <div> 4 </div>
      <div> 5 </div>
      <div> 6 </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search