我只是使用css进行一些加载,我希望他们有一个真实的行为,我尝试使用animation-timing-function: cubic-bezier(1, 0, 1, 1)
,看起来很好,但不像我想的那样真实,起初因为我不知道cubic-bezier
参数是如何工作的,所以我找到了this网站并且只是玩弄它们直到我得到了一些不错的东西。
总结一下,如何在动画中添加真实的物理行为?
请仅使用CSS,如果不可能,欢迎使用JS解决方案。
这里有一个FIDDLE示例。
只是一个指导
的建议像一个较小的或SCSS与定义的常量物理变量,或者你可以添加到函数的值和sumule的物理行为甚至可能已经mixin模拟某些行为,我不知道简单的东西,只有CSS
提前谢谢
答案 0 :(得分:11)
你可以只使用CSS,但你会花费大量时间来计算Bezier,关键帧位置,比例等的数字,最重要的是:稍微改变一下您的布局,“重力”,尺寸,距离,您必须从“全部”开始(至少在上面的部分)。
CSS动画很不错,但使用一些JavaScript代码可以获得更好的结果,更不用说如果你需要改变一些东西会有更多的灵活性 -
requestAnimationFrame
动画制作,并提供与CSS动画一样平滑的动画。这个例子显示了基本的,不包括阴影,但这是留给读者的练习。
var div = document.querySelector("div"),
v = {x: 2.3, y: 1}, // some vector
pos = {x: 100, y: 20}, // some position
g = 0.5, // some gravity
absorption = 0.7, // friction/absorption
bottom = 150, // floor collision
frames = 0; // to reset animation (for demo)
// main calculation of the animation using a particle and a vector
function calc() {
pos.x += v.x; // update position with vector
pos.y += v.y;
v.y += g; // update vector with gravity
if (pos.y > bottom) { // hit da floor, bounce
pos.y = bottom; // force position = max bottom
v.y = -v.y * absorption; // reduce power with absorption
}
if (pos.x < 0 || pos.x > 620) v.x = -v.x;
}
// animate
(function loop() {
calc();
move(div, pos);
if (++frames > 220) { // tweak, use other techniques - just to reset bounce
frames = 0; pos.y = 20;
}
requestAnimationFrame(loop)
})();
function move(el, p) {
el.style.transform = el.style.webkitTransform = "translate("+p.x+"px,"+p.y+"px)";
}
div {
width:20px;
height:20px;
background:rgb(0, 135, 222);
border-radius:50%;
position:fixed;
}
<div></div>
如果你想要更准确地反弹地板,你可以使用实际位置的差异来反映这一点:
if (pos.y > bottom) {
var diff = pos.y - bottom;
pos.y = bottom - diff;
...
如果您需要多个元素,只需创建一个实例化对象,该对象嵌入对该元素的引用以进行动画处理,计算等。
如果你现在想要改变方向,起点,重力等等,你只需要更新各自的值,重播时一切都会顺利进行。
您可以修改上面的代码来处理CSS动画的数字。
使用帧数并标准化序列范围,通过计算帧来运行计算。然后提取每个值,假设每10帧以及每次反弹,最后将数字格式化为关键帧。
理想情况下,您将始终包含顶部和底部位置 - 您可以通过监视矢量的y值(符号)的方向来检测这一点,此处未显示。
这将作为生成我们稍后将使用的CSS规则的中间步骤:
var v = {x: 2.3, y: 1}, // some vector
pos = {x: 100, y: 20}, // some position
g = 0.5, // some gravity
absorption = 0.7, // friction/absorption
bottom = 150, // floor collision
frames = 0, // to reset animation (for demo)
maxFrames = 220, // so we can normalize
step = 10, // grab every nth + bounce
heights = [], // collect in an array as step 1
css = ""; // build CSS animation
// calc CSS-frames
for(var i = 0; i <= maxFrames; i++) {
var t = i / maxFrames;
pos.x += v.x; // update position with vector
pos.y += v.y;
v.y += g; // update vector with gravity
if (pos.y > bottom) {
pos.y = bottom;
v.y = -v.y * absorption;
heights.push({pst: t * 100, y: pos.y});
}
else if (!(i % step)) {heights.push({pst: t * 100, y: pos.y})}
}
// step 2: format height-array into CSS
css += "@keyframes demo {\n";
for(i = 0; i < heights.length; i++) {
var e = heights[i];
css += " " + e.pst.toFixed(3) + "% {transform: translateY(" + e.y.toFixed(3) + "px)}\n";
}
css += "}";
document.write("<pre>" + css + "</pre>");
如果我们从中获取结果并将其用作最终页面的CSS,我们会得到这个结果(对不起,此演示中只有非前缀版本):
(你当然必须调整和调整这个,但你会得到要点。)
div {
animation: demo 3s linear infinite;
width:20px;
height:20px;
border-radius:50%;
background:rgb(0, 148, 243);
position:fixed;
left:100px;
}
@keyframes demo {
0.000% {transform: translateY(21.000px)}
4.545% {transform: translateY(58.500px)}
9.091% {transform: translateY(146.000px)}
9.545% {transform: translateY(150.000px)}
13.636% {transform: translateY(92.400px)}
18.182% {transform: translateY(75.900px)}
22.727% {transform: translateY(109.400px)}
25.455% {transform: translateY(150.000px)}
27.273% {transform: translateY(127.520px)}
31.818% {transform: translateY(106.320px)}
36.364% {transform: translateY(135.120px)}
37.727% {transform: translateY(150.000px)}
40.909% {transform: translateY(125.563px)}
45.455% {transform: translateY(133.153px)}
47.273% {transform: translateY(150.000px)}
50.000% {transform: translateY(134.362px)}
54.545% {transform: translateY(148.299px)}
55.000% {transform: translateY(150.000px)}
59.091% {transform: translateY(138.745px)}
61.818% {transform: translateY(150.000px)}
63.636% {transform: translateY(141.102px)}
67.727% {transform: translateY(150.000px)}
68.182% {transform: translateY(147.532px)}
72.727% {transform: translateY(150.000px)}
77.273% {transform: translateY(150.000px)}
81.818% {transform: translateY(150.000px)}
86.364% {transform: translateY(150.000px)}
90.909% {transform: translateY(150.000px)}
95.455% {transform: translateY(150.000px)}
100.000% {transform: translateY(150.000px)}
}
<div></div>
我个人会推荐JavaScript支持,因为它对这些类型的动画更准确,如上所述,它可以很容易地采用新的要求。