那些H5用到的技术(5)——视差滚动效果

  • Post author:
  • Post category:其他



前言

视差滚动(Parallax Scrolling)是指让多层背景以不同的速度移动,形成立体的运动效果,带来非常出色的视觉体验。

目前最火热的视差开源库为parallax.js

官方地址:

https://github.com/wagerfield/parallax


体验地址:

http://matthew.wagerfield.com/parallax/

原理

视差滚动原理其实并不难,parallax.js的源码也仅有600行,大致讲解一下

1、默认情况通过

requestAnimationFrame

方式做数值计算,否则用setTimeout






  1. if




    (!


    window


    .


    requestAnimationFrame


    )




    {




  2. window


    .


    requestAnimationFrame


    =




    function


    (


    callback


    ,


    element


    )




    {






  3. var


    currTime


    =




    new




    Date


    ().


    getTime


    ();





  4. var


    timeToCall


    =




    Math


    .


    max


    (


    0


    ,




    16




    -




    (


    currTime


    -


    lastTime


    ));





  5. var


    id


    =


    window


    .


    setTimeout


    (


    function


    ()




    {



    callback


    (


    currTime


    +


    timeToCall


    );




    },



  6. timeToCall


    );



  7. lastTime


    =


    currTime


    +


    timeToCall


    ;





  8. return


    id


    ;





  9. };





  10. }

2、优先通过

DeviceOrientationEvent

判断是否支持陀螺仪,否则通过mousemove事件监听鼠标移动




  1. Plugin


    .


    prototype


    .


    enable


    =




    function


    ()




    {






  2. if




    (!


    this


    .


    enabled


    )




    {






  3. this


    .


    enabled


    =




    true


    ;





  4. if




    (


    this


    .


    orientationSupport


    )




    {






  5. this


    .


    portrait


    =




    null


    ;



  6. window


    .


    addEventListener


    (


    'deviceorientation'


    ,




    this


    .


    onDeviceOrientation


    );



  7. setTimeout


    (


    this


    .


    onOrientationTimer


    ,




    this


    .


    supportDelay


    );





  8. }




    else




    {






  9. this


    .


    cx


    =




    0


    ;





  10. this


    .


    cy


    =




    0


    ;





  11. this


    .


    portrait


    =




    false


    ;



  12. window


    .


    addEventListener


    (


    'mousemove'


    ,




    this


    .


    onMouseMove


    );





  13. }



  14. window


    .


    addEventListener


    (


    'resize'


    ,




    this


    .


    onWindowResize


    );





  15. this


    .


    raf


    =


    requestAnimationFrame


    (


    this


    .


    onAnimationFrame


    );





  16. }





  17. };

3、css动画优先采用transform的translate3d,否则使用translate进行平移




  1. if




    (


    this


    .


    transform3DSupport


    )




    {






  2. this


    .


    css


    (


    element


    ,




    'transform'


    ,




    'translate3d('


    +


    x


    +


    ','


    +


    y


    +


    ',0)'


    );





  3. }




    else




    if




    (


    this


    .


    transform2DSupport


    )




    {






  4. this


    .


    css


    (


    element


    ,




    'transform'


    ,




    'translate('


    +


    x


    +


    ','


    +


    y


    +


    ')'


    );





  5. }



4、通过设置CSS让浏览器开启GPU加速




  1. Plugin


    .


    prototype


    .


    accelerate


    =




    function


    (


    $element


    )




    {






  2. for




    (


    var


    i


    =




    0


    ,


    l


    =


    $element


    .


    length


    ;


    i


    <


    l


    ;


    i


    ++)




    {






  3. var


    element


    =


    $element


    [


    i


    ];





  4. this


    .


    css


    (


    element


    ,




    'transform'


    ,




    'translate3d(0,0,0)'


    );





  5. this


    .


    css


    (


    element


    ,




    'transform-style'


    ,




    'preserve-3d'


    );





  6. this


    .


    css


    (


    element


    ,




    'backface-visibility'


    ,




    'hidden'


    );





  7. }





  8. };

5、层运动的计算规则

  • 每一个层的运动量依赖于3个因素:
  • scalarX和scalarY的值
  • 父DOM元素的尺寸大小
  • 一个parallax场景中层的depth值

计算的公式如下:




  1. xMotion


    =


    parentElement


    .


    width


    *




    (


    scalarX


    /




    100


    )




    *


    layerDepth



  2. yMotion


    =


    parentElement


    .


    height


    *




    (


    scalarY


    /




    100


    )




    *


    layerDepth

例如在场景中一个data-depth为0.5的层,它的scalarX和scalarY值都为10(默认值),它的父容器的尺寸为1000px x 1000px,那么这个层在x和y方向的总运动量就为:




  1. xMotion


    =




    1000




    *




    (


    10




    /




    100


    )




    *




    0.5




    =




    50




    # 50px of positive and negative motion in x



  2. yMotion


    =




    1000




    *




    (


    10




    /




    100


    )




    *




    0.5




    =




    50




    # 50px of positive and negative motion in y

使用方式

非常简单,官方建议使用ul+li标签的无序列表(当然你用div或者其他标签都行),你只需要给它们一个class layer和一个data-depth属性来指定该层的深度。深度为0的层将是固定不动的,深度为1的层运动效果最激烈的层。0-1之间的层会根据值来相对移动。




  1. <ul




    id


    =


    "scene"


    >





  2. <li




    class


    =


    "layer"




    data-depth


    =


    "0.00"


    ><img




    src


    =


    "layer1.png"


    ></li>





  3. <li




    class


    =


    "layer"




    data-depth


    =


    "0.20"


    ><img




    src


    =


    "layer2.png"


    ></li>





  4. <li




    class


    =


    "layer"




    data-depth


    =


    "0.40"


    ><img




    src


    =


    "layer3.png"


    ></li>





  5. <li




    class


    =


    "layer"




    data-depth


    =


    "0.60"


    ><img




    src


    =


    "layer4.png"


    ></li>





  6. <li




    class


    =


    "layer"




    data-depth


    =


    "0.80"


    ><img




    src


    =


    "layer5.png"


    ></li>





  7. <li




    class


    =


    "layer"




    data-depth


    =


    "1.00"


    ><img




    src


    =


    "layer6.png"


    ></li>



  8. </ul>



别忘了设置样式




  1. ul


    {




  2. list


    -


    style


    :


    none


    ;



  3. display


    :


    block


    ;



  4. padding


    :




    0


    ;



  5. margin


    :




    0


    ;



  6. }



  7. .


    scene


    ,



  8. .


    scene


    .


    layer


    {




  9. height


    :




    100


    %;



  10. width


    :




    100


    %;



  11. position


    :


    absolute


    ;



  12. }




  1. //jquery.parallax.js



  2. $


    (


    '. scene'


    ).


    parallax


    ();



  3. //parallax.js



  4. var


    scene


    =


    document


    .


    getElementById


    (


    'scene'


    );



  5. var


    parallax


    =




    new




    Parallax


    (


    scene


    );

一般这样使用就足够了,除非是比较复杂的效果,要设置一些特定参数,调用API,具体内容参见官方文档

结合swiper.js

使用方式上不变,只不过需要把需要视差的元素再包裹一层




  1. <div




    class


    =


    "swiper-slide"


    >





  2. <ul




    class


    =


    "parallax"


    >





  3. <li




    class


    =


    "layer"




    data-depth


    =


    "0.5"


    ><img




    style


    =


    "


    position


    :


    absolute


    ;


    left


    :


    0


    ;


    top


    :




    5


    %


    "




    class


    =


    "ani"




    swiper-animate-effect


    =


    "fadeInUp"




    swiper-animate-duration


    =


    "1s"




    swiper-animate-delay


    =


    "0.3s"




    src


    =


    "./img/5.jpg"




    alt


    =


    ""


    ></li>





  4. <li




    class


    =


    "layer"




    data-depth


    =


    "0.2"


    >





  5. <video




    id


    =


    "video"




    style


    =


    "


    width


    :




    80


    %;


    left


    :




    10


    %;


    top


    :




    20


    %


    "




    src


    =


    "./video/test.mp4"




    preload




    autoplay




    controls


    >





  6. </video>





  7. </li>





  8. </ul>



  9. </div>

最终效果图:

o_testt.gif

demo地址:


https://github.com/leestar54/h5-demo/blob/master/parallax.html

转载于:https://www.cnblogs.com/leestar54/p/6786752.html