如何添加物理CSS动画? [英] How to add physics to CSS animations?

查看:131
本文介绍了如何添加物理CSS动画?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是使用css做一些加载,我希望他们有一个真正的行为,我尝试使用 animation-timing-function:cubic-bezier(1,0,1, 1),看起来不错,但不像我想要的真实,因为我不知道如何做 cubic-bezier 参数真的工作,我找到了这个网站,只是玩弄他们,直到我有一些好东西。



总结一下,如何为我的动画添加一个真实的物理行为?



请尽量使用CSS,如果不可能,欢迎使用JS解决方案。

这里有一个 FIDDLE 示例。



只是一个指导的建议



有一些像定义的常量物理变量,或者可以添加到函数和sumule的物理行为甚至可能已经mixins模拟某些行为,我不知道简单的东西,只有CSS。



Thx提前

解决方案

您可以仅使用CSS,但您将花费大量时间了解Bezier的数字,关键帧位置,比例等,并且在其上:你的布局,重力,尺寸,距离的微小变化,你必须开始全部(至少上述部分)。



CSS动画很不错,但是你会得到一个更好的结果与一个小的JavaScript代码,更何况有更多的灵活性,如果你需要改变的东西 - p>


  • 定义球的向量

  • 定义任意的引力

  • 计算向量和反弹

  • 使用transforms将结果值绑定到DOM元素(与位置相比,使结果更平滑)。

  • 使用<$



c $ c> requestAnimationFrame ,它会同步监视并提供与CSS动画一样流畅的动画。示例



这个例子显示了基本的,不包括阴影,但是留给读者做练习。



  var div = document.querySelector(div),v = {x:2.3,y:1},//一些向量pos = {x:100,y:20} //一些位置g = 0.5,//一些重力吸收= 0.7,//摩擦/吸收底= 150,//底部碰撞帧= 0; //重置动画(演示)//使用粒子和矢量函数主要计算动画calc(){pos.x + = v.x; //用向量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; //使用吸收减少功率} if(pos.x< 0 || pos.x> 620)vx = -vx;} // 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>< / 



如果您想要更准确地反弹地板,请选择

您可以使用实际排名的差异来反映:

  if(pos.y> bottom){
var diff = pos.y - bottom;
pos.y = bottom - diff;
...

如果你需要这个几个元素,只需创建一个instantiate-如果你现在想要改变方向,起点,重力等等,你只需要更新一个对象



示例中间步骤生成CSS关键帧



可以修改上面的代码来缩小CSS动画的数字。



使用帧数并规范化序列范围,通过计算帧来运行计算。然后提取每个帧的值,每10帧以及每次反弹,最后将格式数字作为关键帧。



理想情况下,您将始终包括顶部和底部位置可以通过监视向量的y值(符号)的方向来检测这一点,这里未显示。



这将作为一个中间步骤来产生CSS规则我们稍后将使用:



  var v = {x:2.3,y:1},//一些向量pos = {x:100 ,y:20},//一些位置g = 0.5,//一些重力吸收= 0.7,//摩擦/吸收底= 150,//底部碰撞帧= 0,//重置动画(演示)maxFrames = 220,//所以我们可以正规化step = 10,//抓取每nth + bounce heights = [],//收集在一个数组作为步骤1 css =; // build CSS animation // calc CSS-framesfor(var i = 0; i <= maxFrames; i ++){var t = i / maxFrames; pos.x + = v.x; //用向量pos.y +更新位置+ = v.y; v.y + = g; // update vector with gravity if(pos.y> bottom){pos.y = bottom; v.y = -v.y *吸收; heights.push({pst:t * 100,y:pos.y}); } //第二步:将高度数组格式化为CSScss + =@keyframes demo {} {// {} \ n; for(i = 0; i ;} css + =}; document.write (< pre>+ css +< / pre>);  



如果我们从中获取结果,并将其作为CSS用于我们的最终页面,我们得到这个结果(对不起,仅仅在这个演示中的非前缀版本):



(你当然需要调整和微调这个,但你会得到gist。)



  div {animation:demo 3s linear infinite; width:20px; height:20px; border-radius:50%; background:rgb(0,148,243);位置:固定; 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 px)} 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 )} 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(150.000px)} 72.727%{transform:translateY(150.000px)} 77.273%{transform:translateY(150.000px)} 81.818%{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支持虽然更准确的这些类型的动画,采纳新的要求。


I'm just doing some loading using css and I want them to have a real behavior, I'm trying with the animation-timing-function: cubic-bezier(1, 0, 1, 1), looks fine but not as real like I want, at first because I don't know how do cubic-bezier parameters really work, I found this site and just played around with them until I got something nice.

To sum up, how to add a real physic behavior to my animation?

PLEASE ONLY CSS, if not possible, a JS solution is welcome.

Here you have a FIDDLE example.

Just a suggestion to guide

Something like a less or SCSS with constant physical variables that are defined, or values that you can add to the function and sumule the physical behavior may even have already mixins that simulates certain behavior, I do not know something simple and only CSS.

Thx in advance

解决方案

You can use CSS-only but you will spend a lot of time figuring out the numbers for the Bezier, keyframe positions, scale and so on, and on top of that: a slight change in your layout, "gravity", dimensions, distance and you have to start "all over" (for the above part at least).

CSS animations are nice, but you will gain a better result with a little JavaScript code, not to mention have a lot more flexibility if you need to change something -

  • Define a vector for the ball
  • Define a arbitrary gravity
  • Calculate the vector and bounce
  • Bind resulting values to DOM element using transforms (gives smoother result compared to position).
  • Animate using requestAnimationFrame which syncs to monitor and gives just as smooth animations as CSS animations does.

Example

This example shows the basic, does not include the shadow, but that is left as an exercise for the reader.

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 you want a more accurate bounce of the floor, you can use the diff of actual position to reflect that as well:

if (pos.y > bottom) {
    var diff = pos.y - bottom;
    pos.y = bottom - diff;
    ...

And if you need this for several element, just create an instantiate-able object which embeds a reference to the element to animate, the calculations etc.

If you now want to change direction, start point, gravity and so on, you just update the respective values and everything works smooth when replayed.

Example intermediate step to produce CSS key-frames

You can modify the code above to crunch numbers for a CSS-animation.

Use number of frames and normalize the sequence range, run the calculations by counting frames. Then extract values per, lets say every 10 frames as well as every bounce, finally format numbers as key-frames.

Ideally you will always include top and bottom position - you can detect this by monitoring the direction of the vector's y-value (the sign), not shown here.

This will work as an intermediate step to produce the CSS-rule which we will use later:

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>");

If we grab the result from that and uses it as CSS for our final page, we get this result (sorry, non-prefixed version only in this demo):

(You will of course have to tweak and fine-tune this, but you'll get the gist.)

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>

Personally I would recommend the JavaScript support though as it is more accurate for these type of animations, and as mentioned, it can easily adopt to new requirements.

这篇关于如何添加物理CSS动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆