Skip to content

沿环形路径平移的动画

需要两个元素的解决方案

  1. 绕着一个圆的中心旋转,但内容自身也会旋转,这样会影响可读性

    css
    @keyframes spin {
        to { transform: rotate(1turn); }
    }
    .avatar {
        animation: spin 3s linear infinite;
        transform-origin: 50% 150px; /* 大圆半径为 150px */
    }
  2. 为了让自身不旋转,在外面再套一层 divdiv 自身环绕大圆选装,头像自身反向旋转,用内层的变形来抵消外层的变形效果

    html
    <div class="round">
        <div class="wrapper">
            <img src="avatar.jpg" alt="avatar">
        </div>
    </div>
    css
    .round {
        width: 300px;
        height: 300px;
        padding: 15px;
    }
    
    @keyframes spin {
        to { transform: rotate(1turn); }
    }
    .round .wrapper {
        transform-origin: 50% 150px;
        animation: spin 3s linear infinite;
    }
    .round .wrapper img {
        animation: inherit; /* 使用继承,复用性更高 */
        animation-direction: reverse; /* 反向抵消 */
    }

    单个元素的解决方案

    transform-origin 只是一个语法糖,实际上可以用 translate() 来代替

    css
    /* 下面两段代码实际上是等效的 */
    .box {
        transform: rotate(30deg);
    	transform-origin: 200px 300px;
    }
    .box {
        transform: translate(200px, 300px)
            	   rotate(30deg)
            	   translate(-200px, -300px);
    	transform-origin: 0 0;
    }

所以我们可以把两个旋转动画放到一个动画里

css
@keyframes spin {
    from { 
        transform: translate(50%150px)
            	   rotate(0turn)
            	   translate(-50%-150px)
            	   translate(50%50%)
            	   rotate(1turn)
            	   translate(-50%-50%); 
    }
    to { 
        transform: translate(50%150px)
            	   rotate(1turn)
            	   translate(-50%-150px)
            	   translate(50%50%)
            	   rotate(0turn)
            	   translate(-50%-50%); 
    }
}
.box > img {
    animation: spin 3s linear infinite;
}

中间两个 translate 可以相互抵消,因此可以简写为

css
@keyframes spin {
    from { 
        transform: translate(50%150px)
            	   rotate(0turn)
            	   translateY(-150px) translateY(-50%)
            	   rotate(1turn)
            	   translate(-50%-50%); 
    }
    to { 
        transform: translate(50%150px)
            	   rotate(1turn)
            	   translateY(-150px) translateY(-50%)
            	   rotate(0turn)
            	   translate(-50%-50%); 
    }
}