动画绑定

    avalon2实际上没有实现完整的动画模块,它只是对现有的CSS3动画或jquery animate再包装一层。

    我们先说如何用CSS3为avalon实现动画效果。首先要使用avalon.effect注册一个特效。

    css3动画要求我们至少添加4个类名。这个是从angular那里学过来的。因此如何你以前的项目是基于angular,它那些CSS动画类可以原封不动地搬过来用。

    1. avalon.effect('animate', {
    2. enterClass: 'animate-enter',
    3. enterActiveClass: 'animate-enter-active',
    4. leaveClass: 'animate-leave',
    5. leaveActiveClass: 'animate-leave-active',
    6. })

    当然,这些类名会默认帮你添加,因为它内部是这样实现的。

    1. avalon.effect = function (name, opts) {
    2. var definition = avalon.effects[name] = (opts || {})
    3. if (support.css && definition.css !== false) {
    4. patchObject(definition, 'enterClass', name + '-enter')
    5. patchObject(definition, 'enterActiveClass', definition.enterClass + '-active')
    6. patchObject(definition, 'leaveClass', name + '-leave')
    7. patchObject(definition, 'leaveActiveClass', definition.leaveClass + '-active')
    8. }
    9. patchObject(definition, 'action', 'enter')
    10. }
    11. function patchObject(obj, name, value) {
    12. if (!obj[name]) {
    13. obj[name] = value
    14. }
    15. }
    1. avalon.effect('animate', {})
    2. avalon.effect('animate')

    definition配置对象css如果等于false,那么它会强制使用JS方式

    注册完,我们就需要在样式表中添加真正的CSS类。

    我们还得定义一个vm,里面指明动画的动作(默认有三种方式, enter, leave, move) 及动画结束时的回调(这是可选的)

    1. var vm = avalon.define({
    2. $id: 'effect',
    3. aaa: "test",
    4. action: 'enter',
    5. enterCb: function(){
    6. avalon.log('动画完成')
    7. },
    8. leaveCb: function(){
    9. avalon.log('动画回到原点')
    10. }
    11. })

    然后页面上这样使用:

    1. <div ms-controller='effect' >
    2. <div ms-effect="{is:'animate', action:@action,onEnterDone: @enterCb,onLeaveDone: @leaveCb}">
    3. {{@aaa}}
    4. </div>
    5. <button ms-click='@action = @action !== "leave" ? "leave": "enter"'
    6. type="button">click</button>
    7. </div>

    ms-effect的值为一个对象,其中is是必选。除了action, 还支持这么多种回调:

    1. onEnterDone, onLeaveDone, onEnterAbort, onLeaveAbort, onBeforeEnter, onBeforeLeave

    如果使用JS实现,则是这样的:

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <title>TODO supply a title</title>
    5. <meta charset="UTF-8">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <script src="../dist/avalon.js"></script>
    8. <script src="//cdn.bootcss.com/jquery/3.0.0-beta1/jquery.js"></script>
    9. <style>
    10. .ani{
    11. width:100px;
    12. height:100px;
    13. background: #29b6f6;
    14. }
    15. </style>
    16. <script>
    17. avalon.effect('animate', {
    18. enter: function(el, done){
    19. $(el).animate({width: 300},1000,done)
    20. },
    21. leave: function(el, done){
    22. $(el).animate({width: 100},1000,done)
    23. }
    24. })
    25. var vm = avalon.define({
    26. $id: 'effect',
    27. aaa: "effect",
    28. action: 'enter',
    29. enterCb: function(){
    30. avalon.log('动画完成')
    31. },
    32. leaveCb: function(){
    33. avalon.log('动画回到原点')
    34. }
    35. })
    36. </script>
    37. </head>
    38. <body>
    39. <div ms-controller='effect' >
    40. <div class='ani' ms-effect="{is:'animate', action:@action,onEnterDone: @enterCb,onLeaveDone: @leaveCb}">
    41. {{@aaa}}
    42. </div>
    43. <button ms-click='@action = @action !== "leave" ? "leave": "enter"'
    44. type="button">click</button>
    45. </div>
    46. </body>
    47. </html>

    一个CSS3位置效果

    1. <!DOCTYPE html>
    2. <html lang="zh-CN">
    3. <head>
    4. <meta charset="utf-8">
    5. <meta name="format-detection" content="telephone=no">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0,user-scalable=no">
    7. <style>
    8. .animate-enter, .animate-leave{
    9. background: #29b6f6;
    10. transition: width 2s;
    11. -moz-transition: width 2s; /* Firefox 4 */
    12. -webkit-transition: width 2s; /* Safari 和 Chrome */
    13. -o-transition: width 2s; /* Opera */
    14. }
    15. .animate-enter-active, .animate-leave{
    16. width:300px;
    17. }
    18. .animate-leave-active{
    19. width:100px;
    20. }
    21. </style>
    22. <title></title>
    23. </head>
    24. <body ms-controller="body">
    25. <button ms-click="@toggle">toggle</button>
    26. <div ms-effect="{is : 'animate',action: @action}"></div>
    27. <script src="../../dist/avalon.js"></script>
    28. <script>
    29. avalon.effect("animate",{
    30. onEnterDone: function(){
    31. avalon.log('enter done')
    32. },
    33. onLeaveDone: function(){
    34. avalon.log('leave done')
    35. }
    36. });
    37. var vm = avalon.define({
    38. $id : "body",
    39. action: 'enter',
    40. toggle : function(){
    41. vm.action = vm.action === 'enter' ? 'leave' : 'enter'
    42. avalon.log('toggle', vm.action)
    43. }
    44. });
    45. </script>
    46. </body>
    47. </html>

    ms-widget+ms-for+ms-if+ms-effect的动画效果

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <title>ms-if</title>
    5. <meta charset="UTF-8">
    6. <meta name="viewport" content="width=device-width">
    7. <script src="../dist/avalon.js"></script>
    8. <script src="//cdn.bootcss.com/jquery/3.0.0-beta1/jquery.js"></script>
    9. <style>
    10. .ani{
    11. width:100px;
    12. height:100px;
    13. background: #ff6e6e;
    14. }
    15. </style>
    16. <script >
    17. avalon.component('ms-button', {
    18. template: '<button type="button"><span><slot name="buttonText"></slot></span></button>',
    19. defaults: {
    20. buttonText: "button"
    21. },
    22. soleSlot: 'buttonText'
    23. })
    24. avalon.effect('zoom', {
    25. enter: function (el, done) {
    26. $(el).css({width: 0, height: 0}).animate({
    27. width: 100, height: 100
    28. }, 1000, done)
    29. },
    30. leave: function (el, done) {
    31. $(el).animate({
    32. width: 0, height: 0
    33. }, 1000, done)
    34. }
    35. })
    36. var vm = avalon.define({
    37. $id: "effect1",
    38. arr: [1,2,3],
    39. aaa: 222,
    40. toggle: true
    41. })
    42. </script>
    43. </head>
    44. <body ms-controller="test" >
    45. <div ms-for="el in @arr">
    46. <div class='ani'
    47. ms-attr="{eee:el}"
    48. ms-if="@toggle"
    49. ms-widget='{is:"ms-button"}'
    50. ms-effect="{is:'zoom'}">{{@aaa}}::{{el}}</div>
    51. </div>
    52. <button ms-click="@toggle = !@toggle " >点我 </button >
    53. </body>
    54. </html>

    ms-for与stagger的动画效果

    这次为了与angular一致,stagger改为一个小数,它会让当前元素延迟stagger秒执行。

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. .my-repeat-animation {
    7. width: 400px;
    8. height: 30px;
    9. -webkit-animation-duration: 1s;
    10. animation-duration: 1s;
    11. }
    12. .ng-enter {
    13. -webkit-animation-name: enter_animation;
    14. animation-name: enter_animation;
    15. }
    16. .ng-enter-stagger {
    17. animation-delay:300ms;
    18. -webkit-animation-delay:300ms;
    19. }
    20. .ng-leave {
    21. -webkit-animation-name: leave_animation;
    22. animation-name: leave_animation;
    23. }
    24. @keyframes enter_animation {
    25. 0% {
    26. opacity: 0;
    27. }
    28. 100% {
    29. opacity: 1;
    30. }
    31. }
    32. @keyframes leave_animation {
    33. from {
    34. opacity: 1;
    35. }
    36. to {
    37. opacity: 0;
    38. }
    39. }
    40. @-webkit-keyframes enter_animation {
    41. from {
    42. opacity: 0;
    43. }
    44. to {
    45. opacity: 1;
    46. }
    47. }
    48. @-webkit-keyframes leave_animation {
    49. from {
    50. opacity: 1;
    51. }
    52. to {
    53. opacity: 0;
    54. }
    55. }
    56. </style>
    57. <script>
    58. avalon.effect("my-repeat-animation", {
    59. enterClass: "ng-enter",
    60. leaveClass: "ng-leave"
    61. })
    62. var vm = avalon.define({
    63. $id: "test",
    64. array: [1, 2, 3, 4],
    65. getBg: function() {
    66. return '#' + Math.floor(Math.random() * 16777215).toString(16);
    67. },
    68. add: function() {
    69. vm.array.push(vm.array.length + 1)
    70. vm.array.push(vm.array.length + 1)
    71. vm.array.push(vm.array.length + 1)
    72. vm.array.push(vm.array.length + 1)
    73. vm.array.push(vm.array.length + 1)
    74. vm.array.push(vm.array.length + 1)
    75. vm.array.push(vm.array.length + 1)
    76. vm.array.push(vm.array.length + 1)
    77. vm.array.push(vm.array.length + 1)
    78. },
    79. value: ""
    80. })
    81. vm.$watch("value", function(a) {
    82. if (a) {
    83. vm.array.removeAll(function(el) {
    84. return el !== a
    85. })
    86. } else {
    87. if(vm.array.length < 12)
    88. vm.add()
    89. }
    90. })
    91. </script>
    92. </head>
    93. <body ms-controller="test">
    94. <button ms-click="@add">Add</button>
    95. <input placeholder="只保留" ms-duplex-number="@value" />
    96. <div class="my-repeat-animation" ms-for="item in @array"
    97. ms-css="{background:@getBg()}"
    98. ms-effect="{is:'my-repeat-animation',stagger:0.3}">
    99. {{item}}
    100. </div>
    101. </body>