Search code examples
javascriptcssgsap

How to make links follow the cursor for a defined distance on hover state?


I want to reproduce the link "attraction" effect as shown in the following theme : http://preview.themeforest.net/item/grenada-creative-ajax-portfolio-showcase-slider-theme/full_screen_preview/22712618?_ga=2.243139466.922598619.1568038769-663244003.1563974355

Hover "follow us" on the bottom right of the page to see it in action.

Thanks a lot for your help !


Solution

  • i write this example, try this:

    TweenMax with tilt libraries  
    

    Example

    this is my second example:

    Example 2

    var viewportOffset = {
        x: 0,
        y: $(window).scrollTop()
    };
    
    var Magnet = function(elements) {
        elements.each(function() {
            var element = $(this);
            var isMagnetic = false;
            var isTransformed;
            var max = element.attr("offset-hover-max") || .7;
            var min = element.attr("offset-hover-min") || .5;
    
            function grap(dx, dy) {
                TweenMax.to(element, 0.3, { x: 0.6 * dx, y: 0.6 * dy, rotation: 0.07 * dx, ease: Power2.easeOut })
            };
    
            function reset() {
                TweenMax.to(element, .7, { x: 0, y: 0, scale: 1, rotation: 0, ease: Elastic.easeOut })
            };
    
            $(window).on("mousemove", function(e) {
                var mouse = {
                    x: e.clientX,
                    y: e.clientY - viewportOffset.y
                };
                
                var maxDistance = isMagnetic ? max : min;
    
                var width = element.outerWidth();
                var height = element.outerHeight();
                var offset = element.offset();
                var center = {
                    x: offset.left + width / 2,
                    y: offset.top + height / 2
                };
                var dx = mouse.x - center.x;
                var dy = mouse.y - center.y;
                
                isTransformed = false;
    
                if(Math.sqrt(dx * dx + dy * dy) < width * maxDistance) {
                    isTransformed = true;
                    if(!isMagnetic) isMagnetic = true;
                    grap(dx, dy);
    
                }
    
                if(!isTransformed && isMagnetic) {
                    reset();
                    isMagnetic = false;
                }
            });
        });
    };
    
    $('.magnet-btn').on("mouseenter mouseleave", function(e) {
        var $element = $(this);
        var width = $element.outerWidth();
        var height = $element.outerHeight();
        var x = (e.pageX - $element.offset().left - width / 2) * (width > height ? height / width : 1);
        var y = (e.pageY - $element.offset().top - height / 2) * (height > width ? width / height: 1);
        var $background = $element.find(".magnet-btn__bg");    
        var direction = Math.round((Math.atan2(y, x) * (180 / Math.PI) + 180) / 90 + 3) % 4;
        if ("mouseenter" === e.type) {
            switch (direction) {
                case 0:
                    TweenMax.fromTo($background, 0.3, { left: "0%", top: "-100%" }, { top: "0%", left: "0%", ease: Power3.easeOut });
                    break;
                case 1:
                    TweenMax.fromTo($background, 0.3, { left: "100%", top: "0%" }, { top: "0%", left: "0%", ease: Power3.easeOut });
                    break;
                case 2:
                    TweenMax.fromTo($background, 0.3, { left: "0%", top: "100%" }, { top: "0%", left: "0%", ease: Power3.easeOut });
                    break;
                case 3:
                    TweenMax.fromTo($background, 0.3, { left: "-100%", top: "0%" }, { top: "0%", left: "0%", ease: Power3.easeOut });
            }
        } else {
            switch (direction) {
                case 0:
                    TweenMax.to($background, 0.3, { left: "0%", top: "-100%", ease: Power3.easeOut });
                    break;
                case 1:
                    TweenMax.to($background, 0.3, { left: "100%", top: "0%", ease: Power3.easeOut });
                    break;
                case 2:
                    TweenMax.to($background, 0.3, { left: "0%", top: "100%", ease: Power3.easeOut });
                    break;
                case 3:
                    TweenMax.to($background, 0.3, { left: "-100%", top: "0%", ease: Power3.easeOut });
    
            }
        } 
    });
    
    var btn = $('.magnet-btn');
    Magnet(btn);
    
    $( function() {
            // init plugin
            NodeCursor({
                cursor : true, 
                node : true, 
                cursor_velocity : 1, 
                node_velocity : 0.15, 
                native_cursor : 'none', 
                element_to_hover : '.nodeHover', 
                cursor_class_hover : 'disable', 
                node_class_hover : 'expand', 
                hide_mode : true, 
                hide_timing : 2000, 
            });
    
        });
    html, body {
     
      background-color: #111111;
     
    }
    
    ul {
      list-style: none;
      float: right;
      margin-right: 50px;
      position: relative;
      display: inline-block;
      margin-top: 30px;
      padding-left: 20px;
    }
    
    ul li {
      display: inline-block;
      margin-right: 14px;
    }
    
    ul li a {
      color: #000;
      font-size: 12px;
      font-weight: 600;
      display: block;
      height: 40px;
      width: 40px;
      line-height: 40px;
      text-align: center;
      transition: opacity 0.2s ease-in-out;
    }
    
    .wrapper {
      -webkit-transform: translate(-50%, -50%);
              transform: translate(-50%, -50%);
    }
    .wrapper .magnet-btn {
      position: relative;
      display: block;
      color: black;
      text-decoration: none;
      text-align: center;
      color: white;
      transition: color 0.2s ease-in;
      overflow: hidden;
      border-radius: 3px;
    }
    
    /* ----------------------------
    
      cursor styles
    
    --------------------------- */
    .cursor {
      pointer-events: none;
      position: fixed;
      z-index: 10;
      top: 0;
      left: 0;
      display: block;
      /*styles applied for showing / hiding cursor - do not touch*/
      transition: opacity 300ms linear;
      opacity: 0;
      /*element width*/
      width: 6px;
      height: 6px;
    }
    
    .cursor.moving {
      opacity: 1;
    }
    
    .cursor::before {
      content: ' ';
      height: 100%;
      width: 100%;
      position: absolute;
      background-color: #ffffff;
      border-radius: 50%;
      top: 0;
      left: 0;
      /* transitions animations*/
      opacity: 1;
      transition: opacity 300ms linear;
    }
    
    /* expand is the class you assigned with the plugin to cursor when a selected element is hovered*/
    .cursor.expand::before {
      opacity: 0;
    }
    
    /* ----------------------------
    
      node styles
    
    --------------------------- */
    .node {
      pointer-events: none;
      position: fixed;
      z-index: 100;
      top: 0;
      left: 0;
      display: block;
      /*styles applied for showing / hiding cursor - do not touch*/
      transition: opacity 300ms linear;
      opacity: 0;
      /*element width*/
      width: 15px;
      height: 15px;
    }
    
    .node.moving {
      opacity: 1;
    }
    
    .node::before {
      content: ' ';
      height: 100%;
      width: 100%;
      position: absolute;
      background-color: transparent;
      border-radius: 50%;
      top: 0;
      left: 0;
      border: 1px solid #ffffff;
      /*states and transitions animations*/
      -webkit-transform: scale(1.5);
              transform: scale(1.5);
      opacity: 1;
      transition: opacity 300ms linear, border 300ms linear, background-color 300ms linear, -webkit-transform 300ms linear;
      transition: opacity 300ms linear, transform 300ms linear, border 300ms linear, background-color 300ms linear;
      transition: opacity 300ms linear, transform 300ms linear, border 300ms linear, background-color 300ms linear, -webkit-transform 300ms linear;
    }
    
    /* expand is the class you assigned with the plugin to cursor when a selected element is hovered*/
    .node.expand::before {
      -webkit-transform: scale(3);
              transform: scale(3);
      opacity: 0.2;
    }
    
    /*.node.reduce {
        transform: scale(1);
        background-color: #ffffff;
    }*/
    .hover__btn {
      font-family: 'Roboto', Arial, Helvetica, sans-serif;
      font-size: 14px;
      font-weight: 900;
      letter-spacing: 2px;
      color: #ffffff;
      text-decoration: none;
      outline: none;
      text-transform: uppercase;
      cursor: none;
      position: absolute;
      top: 50%;
      left: 50%;
      -webkit-transform: translate(-50%, -50%);
      transform: translate(-50%, -50%);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/gh/hmongouachon/NodeCursor/src/nodecursor-jquery.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js"></script>
    
    
    <div class="wrapper">
        <ul>
            <li>
        <a href="#" class="magnet-btn nodeHover" offset-hover-max="0.5" offset-hover-min="0.5">In</a></li>
            
        <li> <a href="#" class="magnet-btn nodeHover" offset-hover-max="0.5" offset-hover-min="0.5">Fb</a></li>
            
            <li> <a href="#" class="magnet-btn nodeHover" offset-hover-max="0.5" offset-hover-min="0.5">Db</a></li>
            
             <li> <a href="#" class="magnet-btn nodeHover" offset-hover-max="0.5" offset-hover-min="0.5">Tw</a></li>
             <li> <a href="#" class="magnet-btn nodeHover" offset-hover-max="0.5" offset-hover-min="0.5">Be</a></li>
           
            
            
        </ul>
    </div>
    
        <!-- create cursor markups  -->
        <div class="node" id="node"></div>
    <!--     <div class="cursor" id="cursor"></div> -->