0

https://codepen.io/mprquinn/pen/OmOMrR/
credit: Mike Quinn

The following code triggers an animation when hovering over a link. As I understand the code, the x and y coords should update the position each time the function is called, as getBoundingClientRect() is supposed to update the coords when the document is scrolled...

If you hover over the link without scrolling the page, you'll see the animation surround the link as intended, but if the document is scrolled, the animation is triggered above the link. I notice in console that X and Y aren't updated when the document is scrolled and getBoundingClientRect() is called...

const links = document.querySelectorAll('a');
    links.forEach(link => link.addEventListener('mouseenter', shootLines));    

    function shootLines(e) {    
      const itemDim = this.getBoundingClientRect(),
            itemSize = {
              x: itemDim.right - itemDim.left,
              y: itemDim.bottom - itemDim.top,
            },
            shapes = ['line'],
            colors = ['#2FB5F3',
                      '#FF0A47',
                      '#FF0AC2',
                      '#47FF0A'];
      
      const chosenC = Math.floor(Math.random() * colors.length),
            chosenS = Math.floor(Math.random() * shapes.length);
      
      // create shape
      const burst = new mojs.Burst({
        left: itemDim.left + (itemSize.x/2),
        top: itemDim.top + (itemSize.y/2),
        radiusX: itemSize.x,
        radiusY: itemSize.y,
        count: 8,
        
        children: {
          shape: shapes[chosenS],
          radius: 10,
          scale: {0.8: 1},
          fill: 'none',
          points: 7,
          stroke: colors[chosenC],
          strokeDasharray: '100%',
          strokeDashoffset: { '-100%' : '100%' },
          duration: 450,
          delay: 100,
          easing: 'quad.out',
          isShowEnd: false,
        }
      });
      
      burst.play();
    }
.container {
  margin-top: 20%;
  height: 110vh;
}
<div class="container"><a href="javascript:void(0);">test</a></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mo-js/0.288.2/mo.min.js"></script>
froggomad
  • 1,747
  • 2
  • 17
  • 40

1 Answers1

1

You only need to define the burst once per link element. I modified the code to iterate the links and define the burst on the link. At the end of the function, I'm adding an event listener to play the burst.

The issue you were facing is that you are using getBoundingClientRect, which gives the viewport coordinates of the element. Burst, by default, operates off the document body element (document coordinates). The document coordinates of the link element never change as you scroll, but the viewport coordinates do. Refer here for a simple explanation.

This is mostly all your same code with the modification to add the event listener to play the burst at the end. I believe this would be more efficient too as its not creating a new burst instance every time the mouse enters the element. The codepen you link to is very inefficient as it creates new burst elements in the document each time a link is hovered, also causing memory leak.

const links = document.querySelectorAll('a');
    links.forEach(link => {    
      const itemDim = link.getBoundingClientRect(),
            itemSize = {
              x: itemDim.right - itemDim.left,
              y: itemDim.bottom - itemDim.top,
            },
            shapes = ['line'],
            colors = ['#2FB5F3',
                      '#FF0A47',
                      '#FF0AC2',
                      '#47FF0A'];
      
      const chosenC = Math.floor(Math.random() * colors.length),
            chosenS = Math.floor(Math.random() * shapes.length);
      
      // create shape
      const burst = new mojs.Burst({
        left: itemDim.left + (itemSize.x/2),
        top: itemDim.top + (itemSize.y/2),
        radiusX: itemSize.x,
        radiusY: itemSize.y,
        count: 8,
        
        children: {
          shape: shapes[chosenS],
          radius: 10,
          scale: {0.8: 1},
          fill: 'none',
          points: 7,
          stroke: colors[chosenC],
          strokeDasharray: '100%',
          strokeDashoffset: { '-100%' : '100%' },
          duration: 450,
          delay: 100,
          easing: 'quad.out',
          isShowEnd: false,
        }
      });

      // Add the mouseenter listener to play the burst.
      link.addEventListener('mouseenter', function () { burst.play(); });
    });
.container {
  margin-top: 20%;
  height: 110vh;
}
<div class="container"><a href="javascript:void(0);">test</a></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mo-js/0.288.2/mo.min.js"></script>
Patrick
  • 6,828
  • 3
  • 23
  • 31