外部元素在scaleY(1) 和scaleY(0.5) 之间进行插值。
在时间t,转换将是scaleY(1-t/2)
t = 0 t t = 1s
┌ ┐ ┌ ┐ ┌ ┐
│ 1 0 0 0 │ │ 1 0 0 0 │ │ 1 0 0 0 │
│ 0 1 0 0 │ │ 0 1-t/2 0 0 │ │ 0 1/2 0 0 │
│ 0 0 1 0 │ │ 0 0 1 0 │ │ 0 0 1 0 │
│ 0 0 0 1 │ │ 0 0 0 1 │ │ 0 0 0 1 │
└ ┘ └ ┘ └ ┘
内部元素在scaleY(1) 和scaleY(2) 之间进行插值。
在时间t,转换将是scaleY(1+t)
t = 0 t t = 1s
┌ ┐ ┌ ┐ ┌ ┐
│ 1 0 0 0 │ │ 1 0 0 0 │ │ 1 0 0 0 │
│ 0 1 0 0 │ │ 0 1+t 0 0 │ │ 0 2 0 0 │
│ 0 0 1 0 │ │ 0 0 1 0 │ │ 0 0 1 0 │
│ 0 0 0 1 │ │ 0 0 0 1 │ │ 0 0 0 1 │
└ ┘ └ ┘ └ ┘
但是,这是相对于外部而言的。在绝对意义上,矩阵相乘:
t = 0 t t = 1s
┌ ┐ ┌ ┐ ┌ ┐
│ 1 0 0 0 │ │ 1 0 0 0 │ │ 1 0 0 0 │
│ 0 1*1 0 0 │ │ 0 1+t/2-t²/2 0 0 │ │ 0 2/2 0 0 │
│ 0 0 1 0 │ │ 0 0 1 0 │ │ 0 0 1 0 │
│ 0 0 0 1 │ │ 0 0 0 1 │ │ 0 0 0 1 │
└ ┘ └ ┘ └ ┘
那么,是的,起点和终点对应单位矩阵。
但在两者之间有抛物线scaleY(1+t/2-t²/2)。
使用贝塞尔曲线或许可以达到预期的效果。
令f(t)和g(t)分别为.outer和.inner的计时函数。
根据定义,f(0) = g(0) = 0 和 f(1) = g(1) = 1。
外层的比例由下式给出
( 1-f(t)/2 ) ( 1+g(t) ) = 1 + g(t) - f(t)/2 - f(t)g(t)/2
我们希望它是1,所以
f(t) = 2 g(t) / (1+g(t))
f'(t) = 2 g'(t) / (1+g(t))^2
f'(0) = 2 g'(0)
f'(1) = g'(1) / 2
也就是说,外部的起始坡度必须是内部坡度的两倍,结束坡度反之亦然。
选择f(t) = t(线性)和g,(.3, 0.15), (.7, .4) 给出的贝塞尔曲线似乎会产生不错的效果。注意g'(0) = 2 = 2 f'(0) 和g'(1) = 1/2 = 1/2 f'(0)。
.outer, .inner, .inner-expectation {
transition: transform 2s;
height: 400px;
}
.outer, .inner {
transition-timing-function: linear;
}
.inner {
transition-timing-function: cubic-bezier(.3, 0.15, .7, .4);
}
.inner {
background-image: url(https://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/Souq_Waqif%2C_Doha%2C_Catar%2C_2013-08-05%2C_DD_107.JPG/1920px-Souq_Waqif%2C_Doha%2C_Catar%2C_2013-08-05%2C_DD_107.JPG);
background-size: cover;
}
a:hover ~ .outer {
transform: scaleY(0.5);
}
a:hover ~ .outer .inner {
transform: scaleY(2);
}
* {
box-sizing: border-box;
}
a {
display: block;
position: absolute;
top: 0;
left: 200px;
padding: 20px;
background: wheat;
}
.text {
position: absolute;
top: 0;
height: 100%;
}
.outer {
background: #fcf8b3;
position: absolute;
top: 80px;
left: 200px;
width: 400px;
height: 400px;
}
.inner, .inner-expectation {
position: absolute;
width: 300px;
top: 0;
left: 100px;
}
.inner .text, .inner-expectation .text {
right: 0;
}
.inner-expectation {
width: 20px;
top: 80px;
left: 610px;
background: rgba(255, 0, 0, 0.5);
}
<a href="#">hover me</a>
<div class="outer">
<div class="text">outer</div>
<div class="inner">
<div class="text">inner</div>
</div>
</div>
<div class="inner-expectation"></div>
问题是当悬停结束时,效果会中断。但这并不能完美解决。
反转时,外层的比例为(1+f(t))/2,内层的比例为2-g(t)(相对于外层)。
在绝对意义上,内部的规模将是
(1+f(t))/2 * (2-g(t)) = 1 - g(t)/2 + f(t) - f(t)g(t)/2
我们希望它是1。然后,f(t) = g(t) / ( 2-g(t) )。
但我们已经有了f(t) = 2 g(t) / (1+g(t))。
g(t) / ( 2-g(t) ) = 2 g(t) / (1+g(t)) => g(t) = 1
但是g(0) 必须是0。矛盾。你不可能在两个方向都取得完美的结果。
如果你愿意使用JS,你可以在鼠标进入或离开目标元素时交换外层和内层的计时功能。