• CSS3 贝塞尔曲线实现


    cubic-bezier 曲线是 css3 动画的一个重要基石。另一个为 steps (ease 等都是 cubic-bezier 的特殊形式),css3 中的 cubic_bezier 曲线限制了首尾两控制点的位置,通过调整中间两控制点的位置可以灵活得到常用的动画效果,同时 canvas 也进行了相应的支持,也存在相应的工具可以根据想要的曲线得到对应 cubic bezier 曲线的控制点参数。

    而 ie(6-9) 却没有相应的支持,为了能在各个平台得到一致的动画效果,则不可避免要在 ie 上通过定时器沿着指定控制点参数的 cubic bezier 曲线来手动更新动画对象的数值.

    模拟实现

    公式

    cubic-bezier 公式不是简单的 y= x 公式,而是引入了第三个变量 t,由于动画中关键在于计算比例,即在总时间的某个时间点百分比得到相应的值相对于最终值的比例,那么只需要得到 0,1 区间的曲线即可。 而 [x,y] -> [0,1] 内的曲线则是通过 t 在 0,1 内连续变化而得到:

     

    其中 P0, P1 ,P2, P3 都为两维 xy 向量

    将向量拆开表示即为:

    Java代码  收藏代码
    1. y= (1-t)^3*p0y + 3*(1-t)^2*t*p1y + 3*(1-t)*t^2p2y + t^3p3y  
    2.   
    3.   
    4. x= (1-t)^3*p0x + 3*(1-t)^2*t*p1x + 3*(1-t)*t^2p2x + t^3p3x  

      

    而 css3 所用的 cubic bezier 已经限定死 p0 = (0,0) , p3= (1,1) ,因此公式可简化为

    Java代码  收藏代码
    1. var ax = 3 * p1x - 3 * p2x + 1,  
    2.       bx = 3 * p2x - 6 * p1x,  
    3.       cx = 3 * p1x;  
    4.   
    5. var ay = 3 * p1y - 3 * p2y + 1,  
    6.       by = 3 * p2y - 6 * p1y,  
    7.       cy = 3 * p1y;  
    8.   
    9. y= ((ay * t + by) * t + cy ) * t  
    10.   
    11. x= ((ax * t + bx) * t + cx ) * t  

      

    为了提高效率以及减少计算精度丢失公式进一步经过了 Horner 's method 变化。

    计算

    css3 中某个限定了特定控制参数的 cubic -bezier 曲线如下所示:

    动画所做的事情就是把 x 轴当做时间比例,根据曲线得到 y 轴对应的值,并更新到动画对象中去.

    即转化为以下问题:如何根据上述公式在已知 x 的情况下如何得到 y.

    求 t

    首先需要根据公式

    Java代码  收藏代码
    1. var ax = 3 * p1x - 3 * p2x + 1,  
    2.       bx = 3 * p2x - 6 * p1x,  
    3.       cx = 3 * p1x;  
    4.   
    5. x= ((ax * t + bx) * t + cx ) * t  

      

    在已知 x 的情况下求 t,即经典的多项式求参问题,首先可以通过 newton method 尝试求出 t 的值,若不行(可能性很小)则可通过可靠但慢速的二分法求值.

    求 y

    上步得到 t 后则可以带入另一个 y 公式求得最终值 y

    Java代码  收藏代码
    1. var ay = 3 * p1y - 3 * p2y + 1,  
    2.       by = 3 * p2y - 6 * p1y,  
    3.       cy = 3 * p1y;  
    4.   
    5. y= ((ay * t + by) * t + cy ) * t  

      

    上述解法也是源自 webkit webcore c++ 原生实现.

    使用对比

    在传入动画的 easing 设置时,可以传入 css3 cubic-bezier 的语法格式或者直接传入特定的曲线设置(ease-in ease-out).

    Js代码  收藏代码
    1. $('#xx').animate({  
    2.    left:500  
    3. },{  
    4.   duration: 2,  
    5.   easing: 'cubic-bezier(1,0.22,0,0.84)' // 'ease-in'  
    6. });  

    效果对比:

    cubic-bezier in kissy

    通过对比即可发现,ease-out 和以前 js 实现的简单二次曲线 easeOut 还是有明显的不同,并且 js 实现和 css3 原生几乎效果完全一样(效率可能稍微低了些),更多自带曲线对比可见:

    easing for kissy

  • 相关阅读:
    apk反编译
    Eclipse Android项目中如如第三方library文件
    layout_gravity属性和gravity属性区别(转载)
    android weight 属性正解(转载)
    010_01Servlet Request&Response
    009_02sendRedirect() forward() include()
    009_01Servlet基础简介
    008_02HTTP基础知识
    008_01WEB基础知识
    【实用】让代码变的更加简洁
  • 原文地址:https://www.cnblogs.com/xdoudou/p/4262318.html
Copyright © 2020-2023  润新知