# 巧妙使用transform实现环形路径平移动画

EdwardUp

## 从旋转动画开始

``````@keyframes spin {
to {
transform: rotate(1turn);
}
}

.avatar{
animation: spin 10s infinite linear;
transform-origin: 50% 150px;
}``````

``<img class="avatar" src="edwardup_avatar.jpg" alt="" />``

## 利用多元素的变形相消

w3c的The Transform Function Lists里提到：

If a list of <transform-function> is provided, then the net effect is as if each transform function had been specified separately in the order provided.

``<div style="transform:translate(-10px,-20px) scale(2) rotate(45deg) translate(5px,10px)"></div>``

``````<div style="transform:translate(-10px,-20px)">
<div style="transform:scale(2)">
<div style="transform:rotate(45deg)">
<div style="transform:translate(5px,10px)">
</div>
</div>
</div>
</div>``````

``<div style="transform:rotate(45deg) rotate(-45deg)"></div>``

``````<div style="transform:rotate(45deg)">
<div style="transform:rotate(-45deg)"></div>
</div>``````

``````<div class="avatar">
<img src="edwardup_avatar.jpg" alt="" />
</div>``````

``````@keyframes spin {
to { transform: rotate(1turn); }
}
@keyframes spin-reverse {
from { transform: rotate(1turn); }
}
.avatar {
animation: spin 10s infinite linear;
transform-origin: 50% 150px;
}
.avatar > img {
animation: spin-reverse 10s infinite linear;
}``````

## 只使用单个元素

### transform-origin的本质

• [1] 从一个单位矩阵（identity matrix）开始

• [2] 根据`transform-origin`的x、y、z坐标值，进行平移（translate）

• [3] 从左向右依次对`transform`里的变换函数执行乘法

• [4] 根据`transform-origin`的x、y、z坐标值，进行反向平移

transform-origin 只是一个语法糖而已。实际上你总是可以用 translate() 来代替它

``````.avatar{
transform: rotate(30deg);
transform-origin: 200px 300px;
}``````

``````.avatar{
transform: translate(200px, 300px) rotate(30deg) translate(-200px, -300px);
transform-origin: 0 0;
}``````

### 精简的单元素解决方案

``````@keyframes spin {
from { transform: translate(50%, 150px) rotate(0turn) translate(-50%, -150px); }
to { transform: translate(50%, 150px) rotate(1turn) translate(-50%, -150px); }
}
@keyframes spin-reverse {
from { transform: translate(50%, 50%) rotate(1turn) translate(-50%, -50%); }
to { transform: translate(50%, 50%) rotate(0turn) translate(-50%, -50%); }
}
.avatar {
animation: spin 10s infinite linear;
}
.avatar > img {
animation: spin-reverse 10s infinite linear;
}``````

``<img class="avatar" src="edwardup_avatar.jpg" alt="" />``

``````@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%); }
}
.avatar {
animation: spin 10s infinite linear;
}``````

``````@keyframes spin {
from { transform:
translateY(150px) translateY(-50%) rotate(0turn)
translateY(-150px) translateY(50%) rotate(1turn); }
to { transform:
translateY(150px) translateY(-50%) rotate(1turn)
translateY(-150px) translateY(50%) rotate(0turn); }
}
.avatar {
animation: spin 10s infinite linear;
}``````

``````@keyframes spin {
from { transform:
rotate(0turn)
translateY(-150px) translateY(50%)
rotate(1turn); }
to { transform:
rotate(1turn)
translateY(-150px) translateY(50%)
rotate(0turn); }
}
.avatar {
animation: spin 10s infinite linear;
}``````

## 一点额外的尝试

### 螺旋路径平移

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

### S形路径

``````@keyframes spin{
0%{
transform:
rotate(-90deg) translateX(50px) rotate(90deg);}
49.9%{
transform:
rotate(-270deg) translateX(50px) rotate(270deg);}
50.0% {
transform:
translateY(100px) rotate(-90deg) translateX(50px) rotate(90deg);}
100% {
transform:
translateY(100px) rotate(90deg) translateX(50px) rotate(-90deg);}
}``````

## 一点补充

`matrix()``transform`里一个特殊的变换函数，它可以通过矩阵乘法把`rotate()``translate()`等其他变换函数全部合并在一起。但是，`matrix()`并不能简化本文的动画代码，因为css动画将无法确认如何生成关键帧之间的补间动画，如果关键帧里只有一个合并后的`matrix()`，css动画只会按照平铺的方式去完成过渡。

``````@keyframes spin {
to {
transform: matrix(1, 0, 0, 1, 0, 0);
}
}``````

## 结语

（重新编辑自我的博客，原文地址：http://acgtofe.com/posts/2016...

5.8k 声望
202 粉丝
0 条评论