user3026971
user3026971

Reputation: 5

jQuery circle menu

Anyone with idea to make list items rotating in circle.

I'm using this jQuery code to organize elements in circle, now i need to make them rotating, infinite.

    var type = 1,
        radius = '18em', 
        start = -90, 
        $elements = $('ul li'),
        numberOfElements = (type === 1) ? $elements.length : $elements.length - 1,
        slice = 360 * type / numberOfElements;

    $elements.each(function (i) {
        var $self = $(this),
            rotate = slice * i + start,
            rotateReverse = rotate * -1;

            $self.css({
                'transform': 'rotate(' + rotate  + 'deg) translate(' + radius + ') rotate(' + rotateReverse + 'deg)'
            }); 
    });

Here is codepen https://codepen.io/pen/jOELYdW.

Upvotes: 0

Views: 430

Answers (2)

Hamid Javadi
Hamid Javadi

Reputation: 211

To using jQuery you can store the current degree of rotation for each item with the data attribute.

$item.data('degree', degree);

Also, you should set an interval to calculate the new degree of the item in each interval.

var $menu = $('#circle'),
    $items = $menu.children('.item'),
    itemCount = $items.length,
    eachSlice = 360 / itemCount;

// ...

// calculate new degree in set interval
currentDegree = $item.data('degree'),
newDegree = currentDegree + eachSlice;

You can see a complete source in the following snippet

$(document).ready(function () {

    var $menu = $('#circle'),
        $items = $menu.children('.item'),
        itemCount = $items.length,
        eachSlice = 360 / itemCount;

    $items.each(function(index, item) {

        var $item = $(item),
            $itemContent = $item.children('.item-content'),
            degree = index * eachSlice;

        $item
            .css({
                'transform' : 'rotate(' + degree + 'deg)'
            })
            .data('degree', degree);

        $itemContent
            .css({
                'transform': 'rotate(' + degree * -1 + 'deg)'
            });

        setTimeout(() => {
            $itemContent.addClass('transition');
            $item.addClass('transition');
        }, 100);

    });

    setInterval(() => {

        $items.each(function (index, item) {

            var $item = $(item),
                $itemContent = $item.children('.item-content'),
                currentDegree = $item.data('degree'),
                newDegree = currentDegree + eachSlice;
                
            $item
                .css({
                    'transform': 'rotate(' + newDegree + 'deg)'
                })
                .data('degree', newDegree);

            $itemContent
                .css({
                    'transform': 'rotate(' + newDegree * -1 + 'deg)'
                });

        });

    }, 2000);

});
#circle {
  border: 1px solid #ccc;
  border-radius: 50%;
  height: 500px;
  margin: 50px auto;
  position: relative;
  width: 500px;
}

.item {
  border: 1px solid #a55;
  border-radius: 50%;
  display: flex;
  flex-direction: column;
  height: 80px;
  justify-content: center;
  left: -40px;
  position: absolute;
  transform-origin: calc(250px + 40px) 40px;
  text-align: center;
  
  top: calc(50% - 40px);
  width: 80px;
}

.transition {
    transition: 2s linear;
}
<script src="https://code.jquery.com/jquery-3.4.1.min.js" type="text/javascript"></script>
<div id="circle">
    <div class="item" id="item-1">
        <span class="item-content">Item 1</span>
    </div>
    <div class="item" id="item-2">
        <span class="item-content">Item 2</span>
    </div>
    <div class="item" id="item-3">
        <span class="item-content">Item 3</span>
    </div>
    <div class="item" id="item-4">
        <span class="item-content">Item 4</span>
    </div>
    <div class="item" id="item-5">
        <span class="item-content">Item 5</span>
    </div>
    <div class="item" id="item-6">
        <span class="item-content">Item 6</span>
    </div>
</div>

Upvotes: 2

Hamid Javadi
Hamid Javadi

Reputation: 211

You can set coordinates of them on the circle radius with CSS. use position, transform-origin, rotate and animation.

Also, you can animate them on the circle radius if you want.

I have written an example for you in the following snippet and this Codepen

You can improve it according to what you needed.

@keyframes animate-on-circle {
  0% {
    transform: rotate(0deg);
  }
  25% {
    transform: rotate(90deg);
  }
  50% {
    transform: rotate(180deg);
  }
  75% {
    transform: rotate(270deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

#circle {
  border: 1px solid #ccc;
  border-radius: 50%;
  height: 500px;
  margin: 50px auto;
  position: relative;
  width: 500px;
}

.item {
  border: 1px solid #a55;
  border-radius: 50%;
  display: flex;
  flex-direction: column;
  height: 80px;
  justify-content: center;
  left: -40px;
  position: absolute;
  transform-origin: calc(250px + 40px) 40px;
  text-align: center;
  top: calc(50% - 40px);
  width: 80px;
}

#item-1 {
  animation: animate-on-circle infinite 10s linear;
}

#item-2 {
  animation: animate-on-circle infinite 10s 2s linear;
}

#item-3 {
  animation: animate-on-circle infinite 10s 4s linear;
}

#item-4 {
  animation: animate-on-circle infinite 10s 6s linear;
}

#item-5 {
  animation: animate-on-circle infinite 10s 8s linear;
}
<div id="circle">
  <div class="item" id="item-1">Item 1</div>
  <div class="item" id="item-2">Item 2</div>
  <div class="item" id="item-3">Item 3</div>
  <div class="item" id="item-4">Item 4</div>
  <div class="item" id="item-5">Item 5</div>
</div>

Upvotes: 1

Related Questions