skip to Main Content

is it posible, to animate css rotate as linear transition (take start and end points of transition and use them like a keyframes where points go straight forward to their final position)?

for example:

img_1

by default rotation from 1 to 2 would go by circular way (blue one), but i want it to go from "point to point" (yellow one), but also keep it smooth (not make something like steps(1))

3

Answers


  1. You can use keyframes

      body {
            position: relative;
        }
    
        #box1 {
            position: relative;
            animation: mymove 5s infinite;
            width: 100px;
            height: 100px;
            left: 200px;
            top: 100px;
            background-color: aqua;
        }
    
        @keyframes mymove {
            0% {
                left: 200px;
                top: 100px;
                transform: rotate(0deg);
            }
    
            25% {
                left: 300px;
                top: 200px;
                transform: rotate(90deg);
            }
            75% {
                left: 200px;
                top: 300px;
                transform: rotate(180deg);
            }
            100% {
                left: 100px;
                top: 200px;
                transform: rotate(270deg);
            }
        }
    <div id="box1"></div>

    Here you can learn more about keyframes : link

    Login or Signup to reply.
  2. What you’re proposing to do is not possible with only rotation.

    The path that needs to be traversed in a circle is always equidistant from the center point, or origin.

    The path that needs to be traversed in your question involves scaling or translating the object being rotated.

    Edit: More detailed explanation: If you measure the distance to a point on the circle from the origin, it is further than the distance to the midpoint on the line from the origin.

    The scale needs to be equal to 1 at each point. The scale needs to be smaller at a keyframe exactly in between one point and the next. Or a similar solution if you are translating it instead.

    The result is that you need to add a scaling transition between each rotate you already have and the scale back to 1 at your existing ones.

    Edit #2: This is by no means perfect, but this is the basic idea. I would ideally write something like this in SCSS due to the math involved, but there’s nothing like the basics.

    The red circle is moving along the outer path of an invisible circle between 12 points like a clock.

    For each half hour, I translate the red circle closer to the origin, then back out on the hour. This is what makes it appear as if it is taking a straight line from one point to the next.

    Rotating the circle at normal speed and varying the distance to the center at just the right ratio will give you what you want.

    Finding the right ratio depends on how many target points/keyframes rest along the circles edge. If you have half as many points as the clock example with 12, the midpoint of each line segment will be closer to the center and thus more translation is necessary in each frame. If you have more than 12, the midpoints will be further away than in the example.

    html {
        height: 100%;
        box-sizing: border-box;
    }
    *, *::before, *::after {
        box-sizing: inherit;
    }
    body {
        display: flex;
        min-height: 100%;
        background: #333;
    }
    @keyframes tick {
        0%     { transform: rotate(0)      translateX(100px); }
        4.16%  { transform: rotate(15deg)  translateX(98px); }
        8.32%  { transform: rotate(30deg)  translateX(100px); }
        12.48% { transform: rotate(45deg)  translateX(98px); }
        16.64% { transform: rotate(60deg)  translateX(100px); }
        20.8%  { transform: rotate(75deg)  translateX(98px); }
        24.96% { transform: rotate(90deg)  translateX(100px); }
        29.12% { transform: rotate(105deg) translateX(98px); }
        33.28% { transform: rotate(120deg) translateX(100px); }
        37.44% { transform: rotate(135deg) translateX(98px); }
        41.6%  { transform: rotate(150deg) translateX(100px); }
        45.76% { transform: rotate(165deg) translateX(98px); }
        49.92% { transform: rotate(180deg) translateX(100px); }
        54.08% { transform: rotate(195deg) translateX(98px); }
        58.24% { transform: rotate(210deg) translateX(100px); }
        62.4%  { transform: rotate(225deg) translateX(98px); }
        66.56% { transform: rotate(240deg) translateX(100px); }
        70.72% { transform: rotate(255deg) translateX(98px); }
        74.88% { transform: rotate(270deg) translateX(100px); }
        79.04% { transform: rotate(285deg) translateX(98px); }
        83.2%  { transform: rotate(300deg) translateX(100px); }
        87.36% { transform: rotate(315deg) translateX(98px); }
        91.52% { transform: rotate(330deg) translateX(100px); }
        95.68% { transform: rotate(345deg) translateX(98px); }
        100%   { transform: rotate(360deg) translateX(100px); }
    }
    .box {
        width: 24px;
        height: 24px;
        margin: auto;
        background: #a33;
        border-radius: 50%;
        box-shadow: 0 2px 3px 0 #222;
        animation: tick 6s linear infinite;
        transform: rotate(0) translateX(100px);
    }
    <body>
        <div class="box"></div>
    </body>
    Login or Signup to reply.
  3. To get the line to rotate with its end point following a straight line rather than round the arc of the circle you can place a solid color over the part you do not want displayed.

    This snippet does this by using the before pseudo element of a div as the line and the after pseudo element (rotated about its bottom right hand corner) to hide the end of the line.

    Using CSS rotation transform on the line with linear timing means the movement is linear.

    This snippet adds the outer circle and the yellow line shows the cut off.

    .line {
      position: relative;
      --deg: 70deg;
      width: 400px;
      height: 400px;
      /* the following settings are just for the demo */
      border: solid blue 4px;
      border-radius: 50%;
      overflow: hidden;
      box-sizing: border-box;
    }
    
    .line::before {
      content: '';
      position: absolute;
      background: black;
      width: 50%;
      height: 3px;
      top: 50%;
      left: 0;
      transform-origin: right center;
      animation: rot 5s linear alternate infinite forwards;
      z-index: -1;
    }
    
    .line::after {
      content: '';
      position: absolute;
      width: 100%;
      height: 100%;
      top: -50%;
      left: -100%;
      transform: rotate(calc((var(--deg)) / 2));
      transform-origin: right bottom;
      background: white;
      z-index: -1;
      /* the following settings are just for the demo */
      border-right: solid 4px gold;
      box-sizing: border-box;
    }
    
    @keyframes rot {
      0% {
        transform: rotate(var(--deg));
      }
      100% {
        transform: rotate(0deg);
      }
    }
    <div class="line"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search