0
votes

On my journey to learning Javascript/jQuery - Ive been trying to figure out how to do this and I think i've totally messed up the JSFiddle.

Fiddle: http://jsfiddle.net/y7qWw/

What i'm trying to do is rotate a div around a circle so that it is at a specified point.

1) User clicks a link with Movies Left - id=goLMovies, which moves the div to the left of the circle

example1

1) User clicks a link with Movies Right - id=goRMovies, which moves the div to the top of the circle

2

There will be several boxes around the div with different id's. Depending on which link with which id is clicked the relative div will rotate around to the top of the circle.

It's important that the inside html elements DO NOT rotate, like the text in the circle.

jQuery:

jQuery(function($){

!jQuery.easing && (jQuery.easing = {});
!jQuery.easing.easeOutQuad && (jQuery.easing.easeOutQuad = function( p ) { return 1 - Math.pow( 1 - p, 2 ); });

var squareController = {
create: function( square ){
  var obj = {
    angle: square.data('angle'),
    element: square,
    measure: $('<div />').css('width', 360 * 8 + parseFloat(square.data('angle'))),
    update: squareController.update,
    reposition: squareController.reposition,
  };
  obj.reposition();
  return obj;
},
update: function( angle ){
  this.angle = angle;
  this.reposition();
},
reposition: function(){
  var radians = this.angle * Math.PI / 180, radius = 600 / 2;
  this.element.css({
    marginLeft: (Math.sin( radians ) * radius - 50) + 'px',
    marginTop: (Math.cos( radians ) * radius - 50) + 'px'
  });
}
};

var spin = {
squares: [],
left: function(group){
  var self = this;
  $.each(this.squares, function(i, square){
      if(square.element.data("group")==group||group==""){
        square.measure.stop(true, false).animate(
          { 'width': '-=45' },
          {
            easing: 'easeOutQuad',
            duration: 1000,
            step: function( now ){ square.update( now ); }
          }
        );
      }          
  });
},
right: function(){
  var self = this;
  $.each(this.squares, function(i, square){
    square.measure.stop(true, false).animate(
      { 'width': '+=45' },
      {
        easing: 'easeOutQuad',
        duration: 1000,
        step: function( now ){ square.update( now ); }
      }
    );
  });
},
prep: function( squares ){
  for ( var i=0, square; i<squares.length; i++ ) {
    this.squares.push(squareController.create($(squares[i])));
  }
}
};

var dataGroup;  

$('#goL').click(function(){ spin.left() });
$('#goR').click(function(){ spin.right() });

$('#goLMovies').click(function(){ 
  dataGroup = "movies";
  spin.left(dataGroup) 
});

$('#goLSomething').click(function(){ 

  dataGroup = "something";
  spin.left(dataGroup) 
});

$('#goLAnimation').click(function(){ 

  dataGroup = "animation";
  spin.left(dataGroup) 
});

spin.prep($('.square'));

});

Html:

<a id="goR" href="javascript:void(0);">Left All</a><br/>
<a id="goL" href="javascript:void(0);">Right All</a><br/><br/>

<a id="goLMovies" href="javascript:void(0);">Go Left Movies</a><br/>
<a id="goLSomething" href="javascript:void(0);">Go Left Something</a><br/>
<a id="goLAnimation" href="javascript:void(0);">Go Left Animation</a><br/>

<div class="maincircle">
    <div class="inner">
        <div class="squareOne square" data-angle="180" data-group="movies">Movies</div>
        <div class="squareTwo square" data-angle="5" data-group="animation">Animation</div>
        <div class="squareThree square" data-angle="90" data-group="something">Something?</div>
    </div>
</div>

Thank you in advance for all the help. If someone could comment on their code also to help me develop I would be very grateful.

1
Your code is too much messed up for me to fix that. I will post a fiddle with one box moving along the circle. You may extrapolate that for your case.RaviH
@RaviH Thanks, I look forward to it :)DannieCoderBoi
See thykka's answer below. He has done it in style. Though I got the fiddle working, I will not post it because I feel thykka's solution is elegant.RaviH

1 Answers

4
votes

Here's one way of doing it:

<div class="circle">
  <p>top</p>
  <p>right</p>
  <p>bottom</p>
  <p>left</p>
  <div class="box">Wheee!</div>
</div>
.circle {
  position: relative;
  width: 400px;
  height: 400px;
  border-radius: 200px;
}
.box {
  height: 2rem;
  width: 4rem;
  position: absolute;
  /*  Transfom origin at the center of the circle  */
  top: 50%;
  left: 50%;
  /*  The first translate centers the element,
      the second rotates it,
      the third offsets it to the circle's edge,
      the fourth rotates it back to preserve the element's orientation */
  transform: translate(-50%, -50%) rotate(-90deg) translateY(-200px) rotate(90deg);
  transition: transform 1s ease-out; /* this thing animates it! */
}
$(".circle").on("click", "p",  function(e) {
  var deg = $(e.target).html()
  deg = deg === "top"    ? 0 : // corresponding angle values
        deg === "right"  ? 90 :
        deg === "bottom" ? 180 :
        deg === "left"   ? 270 : -30;
  rotateTo(deg);
});
function rotateTo(deg) {
  var bplate = [
    "translate(-50%,-50%) rotate(", -90, "deg) translateY(-200px) rotate(", 90, "deg)"
  ];
  bplate[1] = deg;
  bplate[3] = 0-deg;
  $(".circle>.box").css({
    "transform": bplate.join("")
  });
}

CSSdeck example

If you wish the rotated element's orientation to remain tangent to the circle, just drop the fourth transform from css & js.