DEV Community

Cover image for The Weekly Animation - 1 + 1/2
Stiv Marcano
Stiv Marcano

Posted on • Edited on

The Weekly Animation - 1 + 1/2

In the previous article We learned how to animate the non-interactive part of this animation From Lukas Kus using GSAP Timeline. Now in order to completely replicate what was done on the dibbble it would be cool to simulate the user dragging on what we did previously to reveal an image, and that's exactly what we're doing today.

Again, here's the end result.

Setting up the background image

We'll need to carefully set up the background image behind the main circle, this will depend heavily on how you first positioned your SVG on the canvas. On the example above it's done by wrapping everything on the same divand absolutely positioning it using thetop and left css properties. You can see it on line 58 of the css tab.

I used Lorem Picsum to fetch a different image of the height I wanted everytime to get a nicer result as well.

The draggable interaction

In order to make the image move and then fade away after reaching certain threshold I'll be using a GSAP Draggable which simplifies the process of making any DOM element Draggable.

First of all, let's arrange our SVG in a way we could move all elements we want to be movable at the same time, as currently the Draggable plugin does not support moving non-nested elements at the same time natively.

To do so, I added a <g> to surround the fill part of the main circle and the small orange dot that remains. See HTML line 7.

After that we need to create the actual function that makes the element Draggable. It's done on line 84, let's go over the main parts of it.

  const dg = Draggable.create("#movable", {
    type: "x, y",
    edgeResistance: "0.8",
    bounds: ".inner-circle",
    inertia: true
  })[0];
Enter fullscreen mode Exit fullscreen mode

The Draggable.create function targets everything inside the tag with id #movable.

The type parameter defines the axis we want to move on, in our case we want to freely move around so we use both x,y.

edgeResistance is a value between 0 and 1 that defines how much does the image can go outside the boundaries and the 'strength' the boundaries apply to bring the main item back.

bounds is the query of an element that should contain the element we provided when creating the draggable. It's important that the element is bigger than the draggable, and that it contains it at least visually so we can actually see our animation. In this case is the inner circle we draw with the animation.

inertia gives a sense of smoothness to our draggable when manipulating it with the dom.

const el = dg.addEventListener("drag", (e) => {
    if (shouldOpen(dg) && isActive) {
      closingTl.play();
      isActive = false;
    }
  });
Enter fullscreen mode Exit fullscreen mode

To make the background image appear after we pass a certain treshold we should track whether the draggable element moved the way we wanted, so we listen whenever the element is dragged and check if the position is inside the boundarieswe difine within shouldOpen.

function shouldOpen(dg) {
  const threshold = 25;
  const isOutOfXBoundaries =
    dg.x < dg.minX - threshold || dg.x > dg.maxX + threshold;
  const isOutOfYBoundaries =
    dg.y < dg.minY - threshold || dg.y > dg.maxY + threshold;

  return isOutOfXBoundaries || isOutOfYBoundaries;
}
Enter fullscreen mode Exit fullscreen mode

The shouldOpen function simply receives a draggable event and checks if it's within a range i arbitrarily designed, not too much to see here.

If the image is outside the range we defined then we trigger a new animation that fades out the SVG and brings up the image itself. And we're done!

The point where it all connects it's on line 9 where we define

const tl = new TimelineMax({ repeat: 0, onComplete: addDraggable });
Enter fullscreen mode Exit fullscreen mode

We're using the addDragable function only after the animation completes, since we don't want the user to be able to move the animation while it's still playing.

It may look like a lot of code and orchestration at firts, but just think of how much more complex it would have been using plain css animations and js. Also, by tweaking some values you could make the animation play backwards, or replay it on demand as I've done on the code example.

If you liked this post, make sure to leave a like and follow me on DEV.TO and twitter as @stiv_ml

Top comments (0)