Home > other >  How can I move tiles in circularly in a multi-row carousel?
How can I move tiles in circularly in a multi-row carousel?

Time:08-30

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 >Prev</button>&nbsp;
        <button >Next</button>&nbsp;

        <div >
            <div >1</div>
            <div >2</div>
            <div >3</div>
            <div >4</div>
            <div >5</div>
            <div >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 :)

CodePudding user response:

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>

CodePudding user response:

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>

  • Related