起初

今天在看到 3D轨道分割图像 这个示例的时候起初没有在意图片背后的悬浮动画,觉得这个只是加载了一张图片然后分成4块,hover上去的时候就合并在一起,就是4块图片的transition-delay不同,后来看着看着发现其实4块图片整体是有一个3D浮动的动画,而且当我hover上去的时候不管现在整体悬浮到那个位置都会顺滑的回到平面,勾起了我的好奇心。

审查


当初

当初如果是要我做的话,我会给整体它一个 infiniteanimation 给个5s的时间让他自己不断悬浮,然后hover上去的时候回到平面,不过这样做的一个非常大的弊端就是:

在hover上的那一瞬间,不管animation进行到哪一帧,都会立马回到最初的css

所以在这个animation和transition之间的衔接就会很突兀,以前也没有去细想,如今看到了之后发现这是我需要的东西。


审查

刚开始检查类名为 block__image 的元素因为它装载了这4张图片,也是它进行的rotate3D,他有一条css引起了我的好奇

1
transition: 5s ease-in-out;

起初我还在好奇怎么用的不是animation,后来它的style亮了一下发生了改变,内容变为 transform: rotate3d(1.6, 0.7, 0, 1deg);,突然有所感悟,接着审查的结果证明了我的想法。

用chrome去hover了一下类名为 block__content 的元素看看 block__image 发生了什么改变

1
2
3
4
5
6
.block--split-image .block__content:hover + .block__image {
-webkit-transition-duration: 0.5s;
transition-duration: 0.5s;
-webkit-transform: rotate3d(0, 0, 0, 0deg) !important;
transform: rotate3d(0, 0, 0, 0deg) !important;
}

审查

block__image 这个整体的 transition-duration 变成了0.5s,我把他改成了5s,发现它回归平面的时间变久了,同时也可以发现下方的duration已经被覆盖,说明这正是让他回到平面的时间,之后的 transform: rotate3d(0, 0, 0, 0deg) !important; 让他强制回到平面,因为js控制的style优先级最高。最后去js中证实一下自己。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Let's get our orbit on, man...
var orbit = {
// Initialize the orbiting
init: function(selector) {
this.elements = document.querySelectorAll(selector || '[data-orbit]');
// Set the update interval
this.setupIntervals();
},
// Setup the intervals for rotating
setupIntervals: function() {
var self = this;
this.elements.forEach(function(el) {
self.update(el);
this.interval = setInterval(function() {
self.update(el);
}, 5000);
});
},
// Update the orbit rotate3d
update: function(el) {
var min = -1;
var max = 1;
// Get our rotate values
var rotate = [
(Math.floor(Math.random() * (max - min + 1)) + min) + '.' + (Math.floor(Math.random() * 9) + 1),
(Math.floor(Math.random() * (max - min + 1)) + min) + '.' + (Math.floor(Math.random() * 9) + 1)
];
// Set the transform
el.style.webkitTransform = 'rotate3d(' + rotate[0] + ', ' + rotate[1] + ', 0, 1deg)';
el.style.MozTransform = 'rotate3d(' + rotate[0] + ', ' + rotate[1] + ', 0, 1deg)';
el.style.msTransform = 'rotate3d(' + rotate[0] + ', ' + rotate[1] + ', 0, 1deg)';
el.style.OTransform = 'rotate3d(' + rotate[0] + ', ' + rotate[1] + ', 0, 1deg)';
el.style.transform = 'rotate3d(' + rotate[0] + ', ' + rotate[1] + ', 0, 1deg)';
}
}
// Start it up
orbit.init();

正是16-18行每隔5s执行一次update函数,update用来改变它的rotate3D。


技巧

以后遇到这种需求的时候,可以考虑利用transition的优点 —— 动画衔接连续。

  1. 用js控制 操作之前 的动画,css中用transition实现 操作之前 的动画的 duration
  2. 操作后用 css伪元素 控制新的 duration 和新的终点属性,记得要用 !important 让它覆盖js控制的样式
  3. 鼠标离开前加上塞贝尔曲线 cubic-bezier(0.65, 0.05, 0.36, 1),鼠标离开后还可以加上回弹效果 0.25s cubic-bezier(0.175, 0.885, 0.32, 1.275) 会有一种难以合拢,一松开就回弹的效果,让用户感觉更有活力

一个简单的动画衔接就是这样,一些小技巧没什么多深的知识点也说不上有非常大的作用,因为对于我而言用户体验非常重要,这一点小细节可以看出作者的认真。希望日后可以用到自己的实践中。

记录于 2017-05-02 17:38