Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a CSS 'path' on hover

I'm trying to generate a 'nice' CSS menu using (mainly) CSS, but with a tiny bit of jQuery as well:

My overall idea is:

+------------------------+
|                        |
|                        |
|         +---+          |
|         |   |          |
|         |___|          | <-- Hover this center piece
|                        |
|                        |
|                        |
+------------------------+

+------------------------+
|     _                  |
|    |\                  | <-- All start moving up to top of screen
|      \  +---+          |
|         |   |          |
|         |___|          |
|                        |
|                        |
|                        |
+------------------------+

+------------------------+
| +---+                  |
| |   |                  |
| |___|                  |
|                        |
|  || All, but one       |
|  || moves down         |
|  \/                    |
|                        |
+------------------------+

+------------------------+
| +---+                  |
| |   |                  |
| |___|                  |
|                        |
|        One stays,      |
| +---+  the rest move this way
| |   |  --->            |
| |___|                  |
+------------------------+

+------------------------+
| +---+                  |
| |   |                  |
| |___|              ^   | The rest move up
|                    |   |
|                    |   |
| +---+            +---+ |
| |   |            |   | |
| |___|            |___| |<-- Another stays
+------------------------+

Complete:

+------------------------+
| +---+            +---+ |
| | 1 |            | 4 | |
| |___|            |___| |
|                        |
|                        |
| +---+            +---+ |
| | 2 |            | 3 | |
| |___|            |___| |
+------------------------+

However, that presumes that there will be four div children, So I'm trying to generate a way of 'determining the angle/position' in jQuery (which, to be honest, isn't working too well).


Similar design:

Enter image description here


So in the end, since there are four divs, they will be at 90 degree intervals from the center (360/4 divs = 90 degrees apart).

If there were, say, six child divs;

360/6 = 60 degrees

So they will be evenly spaced out at 60 degree intervals.


I'll be adding animation as well between them, so hence why I've been playing about with rotations, etc., but I just can't seem to get to grips with it:

My current sample is:

$(".wrap").hover(function(){
    var x =$(this).children().length; //Counts '.circles'
    var degree = 360 / x; //Gets angle
    var percent = 100 / x;
    var curPercent = percent;
    $(this).children().each(function (index) {
        $(this).css("transform","rotate(" + degree*index + "deg)");
        $(this).css("top",percent + "px");
        $(this).css("left",percent + "px");

        percent = percent + curPercent;
    });
});
.wrap{
    height: 300px;
    width: 300px;
    background: red;
    position: relative;
    transform-origin: center center;
    transition: all 0.8s;
}
.wrap:hover .circle{
    top: 0;
    left: 0;
}
.circle{
    transition: all 0.8s;
    position: absolute;
    height: 50px;
    width: 50px;
    top: calc(50% - 25px);
    left: calc(50% - 25px);
    background: tomato;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap">
    <div class="circle">1</div>
    <div class="circle">2</div>
    <div class="circle">3</div>
    <div class="circle">4</div>
</div>

Fiddle


Would anyone:

  • (A): Know how to get the divs to 'rotate' the specified angle or distance in relevance to the parent specified in the jQuery code?

  • (B): Get the 'animation' to reset on hover out?

  • (C): Have any idea what I'm talking about?

Similar implementations (although not exact):

  • Here
  • This more so - but this uses Sass (not wanted)
like image 377
jbutler483 Avatar asked Feb 13 '15 10:02

jbutler483


People also ask

How do you hover CSS?

The :hover selector is used to select elements when you mouse over them. Tip: The :hover selector can be used on all elements, not only on links. Tip: Use the :link selector to style links to unvisited pages, the :visited selector to style links to visited pages, and the :active selector to style the active link.

Can you make a div hover?

To display div element using CSS on hover a tag: First, set the div element invisible i.e display:none;. By using the adjacent sibling selector and hover on a tag to display the div element.

Can I hover a class on CSS?

The :hover CSS pseudo-class matches when the user interacts with an element with a pointing device, but does not necessarily activate it. It is generally triggered when the user hovers over an element with the cursor (mouse pointer).

Can we use hover in inline CSS?

Short answer: you can't. Long answer: you shouldn't. Give it a class name or an id and use stylesheets to apply the style. :hover is a pseudo-selector and, for CSS, only has meaning within the style sheet.


2 Answers

Using a different approach you'll get a slightly different effect. You can play with the times of the setTimeout and the transition to modify the behavior.

See the fiddle

+ function() {
  var to;
  $(".wrap").on('mouseenter', function() {
    var circles = $(this).children();
    var degree = (2 * Math.PI) / circles.length; //calc delta angle
    var transforms = [];

    // Calculate the position for each circle
    circles.each(function(index) {
        var x = 100 * Math.cos(-0.5 * Math.PI + degree * (-1 * index - 0.5));
        var y = 100 * Math.sin(-0.5 * Math.PI + degree * (-1 * index - 0.5));

      transforms.push('translate(' + x + 'px,' + y + 'px)');
    });

    // Function to moves all the circles
    // We'll pop a circle each time and than call this function recursively
    function moveCircles() {
      var transform = transforms.shift();
      circles.css('transform', transform);

      circles.splice(0, 1);
      if (circles.length) to = setTimeout(moveCircles, 400);
    }

    moveCircles();
  });

  $(".wrap").on('mouseleave', function() {
    var circles = $(this).children().css('transform', '');
    clearTimeout(to);
  });
}();
   .wrap {
     height: 300px;
     width: 300px;
     background: red;
     position: relative;
     transform-origin: center center;
     transition: all 0.8s;
   }
   .circle {
     transition: all 0.8s;
     position: absolute;
     height: 50px;
     width: 50px;
     text-align: center;
     line-height: 50px;
     top: calc(50% - 25px);
     left: calc(50% - 25px);
     background: tomato;
     border-radius: 50%;
   }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap">
  <div class="circle">1</div>
  <div class="circle">2</div>
  <div class="circle">3</div>
  <div class="circle">4</div>
  <div class="circle">5</div>
  <div class="circle">6</div>
</div>
like image 124
Arnold Daniels Avatar answered Oct 14 '22 06:10

Arnold Daniels


function rotateStep($this, $circle, angle) {
    $this.animate({
        rotation: angle
    }, {
        step: function(now, fx) {
            $this.css({
                transform: 'rotate(' + now + 'deg)'
            });
            $circle.css({
                transform: 'translate(-50%, -50%) rotate(' + -now + 'deg)'
            });
        }
    });
}

$('.wrap').hover(function() {
    var $this = $(this),
        $circleWrappers = $this.find('.circleWrapper'),
        angleOffset = 360 / $circleWrappers.length,
        angle = - angleOffset / 2,
        distance = Math.min($this.width(), $this.height()) / 2;
    
    $circleWrappers.each(function() {
        var $this = $(this),
            $circle = $(this).find('.circle');
        $circle.animate({ top: -distance });
        rotateStep($this, $circle, angle);
        angle -= angleOffset;
    });
}, function() {
    var $this = $(this),
        $circleWrappers = $this.find('.circleWrapper');
    
    $circleWrappers.each(function() {
        var $this = $(this),
            $circle = $(this).find('.circle');
        $circle.animate({ top: 0 });
        rotateStep($this, $circle, 0);
    });
});
.wrap {
    position: relative;
    background-color: #cccccc;
    width: 400px;
    height: 400px;
    transition:all 0.8s;
    transform-origin: center center;
}
.circleWrapper {
    display: inline-block;
    position: absolute;
    left: 50%;
    top: 50%;
}
.circle {
    position: absolute;
    width: 80px;
    height: 80px;
    border-radius: 40px;
    background-color: white;
    box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.5);
    line-height: 80px;
    text-align: center;
    font-family: arial;
    font-size: 42px;
    font-weight: bold;
    transform: translate(-50%, -50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap">
    <div class="circleWrapper"><div class="circle">1</div></div>
    <div class="circleWrapper"><div class="circle">2</div></div>
    <div class="circleWrapper"><div class="circle">3</div></div>
    <div class="circleWrapper"><div class="circle">4</div></div>
</div>

JSFiddle

like image 33
huysentruitw Avatar answered Oct 14 '22 07:10

huysentruitw