3

I am trying to make an image rotate when you hover over certain items on the page. It uses the solution provided here (with edits for my purposes): https://stackoverflow.com/a/10235298. You can see an example of what I am trying to achieve here: https://jsfiddle.net/t100gq25/

$(function () {
  var img = $('.arrow');

  if (img.length > 0) {
    var offset = img.offset();

    $('.animation-trigger').mouseenter(function (event) {
      var element = $(this);
      var elementPosition = element.offset();
      var elementX = elementPosition.left + (element.width() / 2);
      var elementY = elementPosition.top + (element.height() / 2);
      var imgX = offset.left + (img.width() / 2);
      var imgY = offset.top + (img.height() / 2);
      var radians = Math.atan2(elementX - imgX, elementY - imgY);
      var degrees = (radians * (180 / Math.PI) * -1) + 90;


      img.css('-moz-transform', 'rotate(' + degrees + 'deg)')
        .css('-webkit-transform', 'rotate(' + degrees + 'deg)')
        .css('-o-transform', 'rotate(' + degrees + 'deg)')
        .css('-ms-transform', 'rotate(' + degrees + 'deg)');
    });
  }
});
body {
  padding-top: 150px;
}

.container {
  height: 500px;
}

.menu-1,
.menu-2,
.menu-3,
.menu-4 {
  position: absolute;
  z-index: 99
}

.menu-1 {
  top: 20%;
  left: 20%;
}

.menu-2 {
  top: 20%;
  right: 20%;
}

.menu-3 {
  bottom: 20%;
  left: 20%;
}

.menu-4 {
  bottom: 20%;
  right: 20%;
}

.arrow {
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -100px;
  margin-left: -100px;
  height: 200px;
  width: 200px;

  -webkit-transition: all 400ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
  -moz-transition: all 400ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
  -o-transition: all 400ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
  transition: all 400ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<a href="#" class="menu-1">
    <img src="http://placehold.it/140x35&text=4" class="animation-trigger">
</a>

<a href="#" class="menu-2">
    <img src="http://placehold.it/140x35&text=1" class="animation-trigger">
</a>

<a href="#" class="menu-3">
    <img src="http://placehold.it/140x35&text=3" class="animation-trigger">
</a>

<a href="#" class="menu-4">
    <img src="http://placehold.it/140x35&text=2" class="animation-trigger">
</a>

<img src="https://image.freepik.com/free-icon/arrow-full-shape-pointing-to-right-direction_318-32063.png" class="arrow">

It works great! However if you hover over link 1, the arrow will turn to it and then you decide to hover over link 4 and the arrow will again point to it. However it goes all the way around (clockwise) instead of taking the short route of just spinning back(anti-clockwise).

I've had a go at a few attempts but none have worked and if I come up with an idea that could work it's extremely long winded. I'm struggling to work out the best way to approach this so any help would be very much appreciated.

Please note the jsfiddle is a quick mock up example of what I am trying to achieve. Unfortunately I cannot share the actual source code due to client confidentiality. Any solutions provided I will apply to the final site.

Many thanks:)

Community
  • 1
  • 1

1 Answers1

3

You will need to store all elements degrees and check if arrow needs to rotate clockwise or anti-clockwise for shortest rotation.

$(function() {
  var img = $('.arrow');

  // Store clock wise degrees of all elements
  var clockwiseElemDegrees = {};
  var currentArrowAngle = 0;

  // Treat initial position of arrow as element 0
  var prevElem = '0';
  clockwiseElemDegrees['0'] = 0;

  if (img.length > 0) {

    var offset = img.offset();
    var imgX = offset.left + (img.width() / 2);
    var imgY = offset.top + (img.height() / 2);

    // Get element degrees      
    $('.animation-trigger').each(function() {
      var element = $(this);
      var elementPosition = element.offset();
      var elementX = elementPosition.left + (element.width() / 2);
      var elementY = elementPosition.top + (element.height() / 2);

      var radians = Math.atan2(elementY - imgY, elementX - imgX);
      var degrees = radians * (180 / Math.PI);

      clockwiseElemDegrees[element.attr('elem')] = (degrees < 0) ? (degrees + 360) : degrees;
    });


    $('.animation-trigger').mouseenter(function(event) {

      // Check if arrow should be rotated clockwise
      var clockwiseDegreesForNextElem = clockwiseElemDegrees[$(this).attr('elem')];
      var clockwiseDegreesForPrevElem = clockwiseElemDegrees[prevElem];
      if (clockwiseDegreesForNextElem < clockwiseDegreesForPrevElem)
        clockwiseDegreesForNextElem += 360;

      var clockwiseRotationRequired = clockwiseDegreesForNextElem - clockwiseDegreesForPrevElem;

      if (clockwiseRotationRequired <= 180) {
        // Do clockwise rotation
        currentArrowAngle += clockwiseRotationRequired;
      } else {
        // Do anticlockwise rotation
        currentArrowAngle -= (360 - clockwiseRotationRequired);
      }

      prevElem = $(this).attr('elem');

      img.css('-moz-transform', 'rotate(' + currentArrowAngle + 'deg)')
        .css('-webkit-transform', 'rotate(' + currentArrowAngle + 'deg)')
        .css('-o-transform', 'rotate(' + currentArrowAngle + 'deg)')
        .css('-ms-transform', 'rotate(' + currentArrowAngle + 'deg)');
    });
  }
});
body {
  padding-top: 150px;
}
.container {
  height: 500px;
}
.menu-1,
.menu-2,
.menu-3,
.menu-4 {
  position: absolute;
  z-index: 99
}
.menu-1 {
  top: 20%;
  left: 20%;
}
.menu-2 {
  top: 20%;
  right: 20%;
}
.menu-3 {
  bottom: 20%;
  left: 20%;
}
.menu-4 {
  bottom: 20%;
  right: 20%;
}
.arrow {
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -100px;
  margin-left: -100px;
  height: 200px;
  width: 200px;
  -webkit-transition: all 400ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
  -moz-transition: all 400ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
  -o-transition: all 400ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
  transition: all 400ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<a href="#" class="menu-1">
  <img src="http://placehold.it/140x35&text=4" class="animation-trigger" elem="1">
</a>

<a href="#" class="menu-2">
  <img src="http://placehold.it/140x35&text=1" class="animation-trigger" elem="2">
</a>

<a href="#" class="menu-3">
  <img src="http://placehold.it/140x35&text=3" class="animation-trigger" elem="3">
</a>

<a href="#" class="menu-4">
  <img src="http://placehold.it/140x35&text=2" class="animation-trigger" elem="4">
</a>

<img src="https://image.freepik.com/free-icon/arrow-full-shape-pointing-to-right-direction_318-32063.png" class="arrow">
Chitrang
  • 2,079
  • 1
  • 16
  • 18