Search code examples
cssanimationcss-animationskeyframe

Smooth circular animation with cubic-bezier timing function CSS


I have a problem and I don't know how to solve it. I have defined for an image a keyframe which moves it in a half circular path. I used a linear animation timing function, but it was not smooth enough between the points. After that, I thought about using a bezier easeInExpo function for a better transition, but it just got worse. If I define multiple points at the keyframe the bezier is moving in steps and not smooth at all, but if I define the start and the endpoint it's smooth but it is skipping the path.

My keyframe:

.marketplace {
    position:absolute;
    height: 20%;
    top:15%;
    left: 62%;
    transform:rotate(270deg);
    animation-name: marketplace-animation;
    animation-duration:0.3s;
    animation-delay: 0.6s;
   /* animation-timing-function: linear;*/
    animation-timing-function: cubic-bezier(0.7, 0, 0.84, 0);
    animation-fill-mode: forwards;
    visibility:hidden; 
}

@keyframes marketplace-animation {
    0% {
        visibility: visible;
        top:20%;
        left: 35%;
    }

    25% {
        top:6%;
        left: 41%;
    }

    50% {
        top:4%;
        left: 48%;
        }

    75%{
        top:4%;
        left: 56%;
    }

    99% {
        visibility: hidden;
      }

    100% {
        visibility: visible;
        top:15%;
        left: 62%;
    }
}

So my question is if I choose the linear timing for a smoother circular animation I have to define more points or if I want to use the bezier method how can I make it to work smooth and to remain in the path? Thanks in advance!


Solution

  • Use two animations:

    .marketplace {
        position:absolute;
        background:red;
        height: 100px;
        width:100px; 
        /* the final position */
        top:15%;
        left: 62%;
        /**/
        animation: 
           x 2s linear,
           y 2s cubic-bezier(0,1,0.8,2.8); /* adjust the bezier to control the curve */
    }
    
    /* the initial position */
    @keyframes x {
      from {
        left:0%;
      }
    }
    
    @keyframes y {
      from {
        top:50%;
      }
    }
    <div class="marketplace"></div>