• easy-animation | Animation for Sass


    最近因为项目缘故,勾搭上了Sass

    其实在折腾Sass之前,也有简单用过一下Less。但碍于Less提供的一些API实在让人觉得有点多余,用着就是不顺手,最后就不了了之啦。

    Sass之所以用起来舒服和顺手,很大程度上是因为Compass的存在。Compass提供的足够丰富的API,简直让你觉得写CSS是一种享受。

    不过...

    Compass居然不支持animation!对,没错,就是CSS3那个做来做动画的animation!(至少我翻了好久的Compass文档也没找到...)

    或许你会吐槽说:“啧,自己用Sass的@mixin封装一个animation的方法就搞定啦!”

    恩,我一开始也是这么想的,然后我也这么做了...

    ———— 正文分割线 ————

    作为一个Sass新手,我想要一个animation的@mixin时,必然是:

    /* animation.scss */
    @mixin animation($duration, $name, $count, $function) {
      -webkit-animation-duration: $duration;
      -webkit-animation-name: $name;
      -webkit-animation-iteration-count: $count;
      -webkit-animation-timing-function: $function;
    
      -moz-animation-duration: $duration;
      -moz-animation-name: $name;
      -moz-animation-iteration-count: $count;
      -moz-animation-timing-function: $function;
    
      -ms-animation-duration: $duration;
      -ms-animation-name: $name;
      -ms-animation-iteration-count: $count;
      -ms-animation-timing-function: $function;
    
      -o-animation-duration: $duration;
      -o-animation-name: $name;
      -o-animation-iteration-count: $count;
      -o-animation-timing-function: $function;
    
      animation-duration: $duration;
      animation-name: $name;
      animation-iteration-count: $count;
      animation-timing-function: $function;
    }

    恩,这样貌似就达到了用Sass实现了animation的目的啦。

    然后我们再优化一下代码:

    /* animation.scss */
    @mixin animation($name, $duration, $function: ease, $delay: 0s, $count: infinite) {
      -webkit-animation: $name $duration $function $delay $count;
         -moz-animation: $name $duration $function $delay $count;
          -ms-animation: $name $duration $function $delay $count;
           -o-animation: $name $duration $function $delay $count;
              animation: $name $duration $function $delay $count;
    }

    这样看,代码优雅多了(自我感觉良好~)。

    文章这样就结束了?坑爹吗?!

    当然不是!想用animation做动画,自然还要把@keyframes也用上。按照上面的思路,继续用@mixin封装一下相关css代码:

    /* keyframes.scss */
    @mixin keyframes($animationName) {
      @-webkit-keyframes $animationName {
        @content;
      }
    
      @-moz-keyframes $animationName {
        @content;
      }
    
      @-ms-keyframes $animationName {
        @content;
      }
    
      @-o-keyframes $animationName {
        @content;
      }
    
      @keyframes $animationName {
        @content;
      }
    }

    看起来貌似一切都妥妥的。

    配合上Compass愉快的投入生产:

    /* demo1.scss */
    @import "compass";
    @import "animation.scss";
    @import "keyframes.scss";
    
    .circle {
      @include animation(circle, 1s, linear);
    }
    @include keyframes(circle) {
      0% {
        opacity: 0;
        @include translate(100px, 0);
      }
      100% {
        opacity: 1;
        @include translate(0, 0);
      }
    }

    这样写Sass,真的很简洁很舒服。忍不住打开编译生成的css文件一看,差点哭了出来:

    /* demo1.css */
    .circle {
      -webkit-animation: circle 1s linear 0s infinite;
      -moz-animation: circle 1s linear 0s infinite;
      -ms-animation: circle 1s linear 0s infinite;
      -o-animation: circle 1s linear 0s infinite;
      animation: circle 1s linear 0s infinite;
    }
    
    @-webkit-keyframes circle {
      0% {
        opacity: 0;
        -webkit-transform: translate(100px, 0);
        -moz-transform: translate(100px, 0);
        -ms-transform: translate(100px, 0);
        -o-transform: translate(100px, 0);
        transform: translate(100px, 0);
      }
      100% {
        opacity: 1;
        -webkit-transform: translate(0, 0);
        -moz-transform: translate(0, 0);
        -ms-transform: translate(0, 0);
        -o-transform: translate(0, 0);
        transform: translate(0, 0);
      }
    }
    
    @-moz-keyframes circle {
      0% {
        opacity: 0;
        -webkit-transform: translate(100px, 0);
        -moz-transform: translate(100px, 0);
        -ms-transform: translate(100px, 0);
        -o-transform: translate(100px, 0);
        transform: translate(100px, 0);
      }
      100% {
        opacity: 1;
        -webkit-transform: translate(0, 0);
        -moz-transform: translate(0, 0);
        -ms-transform: translate(0, 0);
        -o-transform: translate(0, 0);
        transform: translate(0, 0);
      }
    }
    
    @-ms-keyframes circle {
      0% {
        opacity: 0;
        -webkit-transform: translate(100px, 0);
        -moz-transform: translate(100px, 0);
        -ms-transform: translate(100px, 0);
        -o-transform: translate(100px, 0);
        transform: translate(100px, 0);
      }
      100% {
        opacity: 1;
        -webkit-transform: translate(0, 0);
        -moz-transform: translate(0, 0);
        -ms-transform: translate(0, 0);
        -o-transform: translate(0, 0);
        transform: translate(0, 0);
      }
    }
    
    @-o-keyframes circle {
      0% {
        opacity: 0;
        -webkit-transform: translate(100px, 0);
        -moz-transform: translate(100px, 0);
        -ms-transform: translate(100px, 0);
        -o-transform: translate(100px, 0);
        transform: translate(100px, 0);
      }
      100% {
        opacity: 1;
        -webkit-transform: translate(0, 0);
        -moz-transform: translate(0, 0);
        -ms-transform: translate(0, 0);
        -o-transform: translate(0, 0);
        transform: translate(0, 0);
      }
    }
    
    @keyframes circle {
      0% {
        opacity: 0;
        -webkit-transform: translate(100px, 0);
        -moz-transform: translate(100px, 0);
        -ms-transform: translate(100px, 0);
        -o-transform: translate(100px, 0);
        transform: translate(100px, 0);
      }
      100% {
        opacity: 1;
        -webkit-transform: translate(0, 0);
        -moz-transform: translate(0, 0);
        -ms-transform: translate(0, 0);
        -o-transform: translate(0, 0);
        transform: translate(0, 0);
      }
    }

    可以看到,每一个@keyframes里面,都重复输出了一套完整兼容的transform。虽然这样的代码不会出现任何异常,但作为一个稍稍有点洁癖的程序员,估计都无法忍受这样的效果。

    随后想了几个解决方法,都不能很好的解决。主要被以下几个问题困扰着:

    1. @keyframes所配置的属性,有可能带浏览器的prefix(-webkit-transform),也有可能不带(opacity )。
    2. 如何才能对不同prefix的@keyframes输出对应的属性。如@-webkit-keyframes能对应上-webkit-transform,而opacity这类非私有的属性则不带上prefix。
    3. 每一个@keyframes对应的配置属性,都是通过@content来传值的。翻查了一下Sass的文档,也没看到哪里有提及到访问@content的方式。

    Google了一下相关信息,也没找到现成的animation for sass的方法。

    幸亏最后在stackoverflow上发现了一个有趣的问题→_→传送门

    提问人和我遇到了类似的情况,也是卡在了@keyframes的私有属性输出的问题。十分幸运的是,在问题下面的回答中,发现了Bourbon这个Sass的库。

    Bourbon所封装的@keyframes方法,就很好的解决了我上面遇到的问题。

    忍不住看了一下它的源码,实现思路很妙。还帮助我更好的弄清了Compass中experimental的实现思路。

    考虑到Compass和Bourbon没有相互依赖的关系,同时使用会出现变量污染的问题。最后根据Bourbon的实现思路,重构了这么一个叫做 easy-animation 的动画工具集。

    /* easy-animation.scss */
    
    
    // easy-animation
    // Author: Maple Jan
    // Date: 2014-04-11
    
    
    // Support browser's private prefix.
    $ea-prefix-for-webkit:       true !default;
    $ea-prefix-for-mozilla:      true !default;
    $ea-prefix-for-microsoft:    true !default;
    $ea-prefix-for-opera:        true !default;
    $ea-prefix-for-spec:         true !default; // required for keyframe mixin
    
    
    // Disable all browser's private prefix.
    @mixin ea-disable-prefix-for-all() {
      $ea-prefix-for-webkit:    false;
      $ea-prefix-for-mozilla:   false;
      $ea-prefix-for-microsoft: false;
      $ea-prefix-for-opera:     false;
      $ea-prefix-for-spec:      false;
    }
    
    
    // Example usage:
    // @include ea-transition(all 2s ease 0s);
    @mixin ea-transition($value, $prefixs: webkit moz ms o spec) {
      @each $prefix in $prefixs {
        @if $prefix == webkit {
          @if $ea-prefix-for-webkit {
            -webkit-transition: $value;
          }
        }
        @else if $prefix == moz {
          @if $ea-prefix-for-mozilla {
            -moz-transition: $value;
          }
        }
        @else if $prefix == ms {
          @if $ea-prefix-for-microsoft {
            -ms-transition: $value;
          }
        }
        @else if $prefix == o {
          @if $ea-prefix-for-opera {
            -o-transition: $value;
          }
        }
        @else if $prefix == spec {
          @if $ea-prefix-for-spec {
            transition: $value;
          }
        }
        @else  {
          @warn "Unrecognized prefix: #{$prefix}";
        }
      }
    }
    
    
    // Example usage:
    // @include ea-transform(scale(1));
    @mixin ea-transform($value, $prefixs: webkit moz ms o spec) {
      @each $prefix in $prefixs {
        @if $prefix == webkit {
          @if $ea-prefix-for-webkit {
            -webkit-transform: $value;
          }
        }
        @else if $prefix == moz {
          @if $ea-prefix-for-mozilla {
            -moz-transform: $value;
          }
        }
        @else if $prefix == ms {
          @if $ea-prefix-for-microsoft {
            -ms-transform: $value;
          }
        }
        @else if $prefix == o {
          @if $ea-prefix-for-opera {
            -o-transform: $value;
          }
        }
        @else if $prefix == spec {
          @if $ea-prefix-for-spec {
            transform: $value;
          }
        }
        @else  {
          @warn "Unrecognized prefix: #{$prefix}";
        }
      }
    }
    
    
    // Example usage:
    // @include ea-animation(wrap_s0_p1, 2s, ease, 0s, infinite);
    @mixin ea-animation($name, $duration, $function: ease, $delay: 0s, $count: infinite) {
      -webkit-animation: $name $duration $function $delay $count;
         -moz-animation: $name $duration $function $delay $count;
          -ms-animation: $name $duration $function $delay $count;
           -o-animation: $name $duration $function $delay $count;
              animation: $name $duration $function $delay $count;
    }
    
    
    // Example usage:
    // @include ea-keyframes(wrap_s0_p1) {
    //   0% {
    //     opacity: 1;
    //     @include ea-transform(scale(1));
    //   }
    //   50% {
    //     opacity: 0.8;
    //     @include ea-transform(scale(0.8));
    //   }
    //   100% {
    //     opacity: 1;
    //     @include ea-transform(scale(1));
    //   }
    // }
    @mixin ea-keyframes($name) {
      $_ea-prefix-for-webkit:       $ea-prefix-for-webkit;
      $_ea-prefix-for-mozilla:      $ea-prefix-for-mozilla;
      $_ea-prefix-for-microsoft:    $ea-prefix-for-microsoft;
      $_ea-prefix-for-opera:        $ea-prefix-for-opera;
      $_ea-prefix-for-spec:         $ea-prefix-for-spec;
    
    
      @if $_ea-prefix-for-webkit {
        @include ea-disable-prefix-for-all();
        $ea-prefix-for-webkit: true;
        @-webkit-keyframes #{$name} {
          @content;
        }
      }
      @if $_ea-prefix-for-mozilla {
        @include ea-disable-prefix-for-all();
        $ea-prefix-for-mozilla: true;
        @-moz-keyframes #{$name} {
          @content;
        }
      }
      @if $_ea-prefix-for-microsoft {
        @include ea-disable-prefix-for-all();
        $ea-prefix-for-microsoft: true;
        @-ms-keyframes #{$name} {
          @content;
        }
      }
      @if $_ea-prefix-for-opera {
        @include ea-disable-prefix-for-all();
        $ea-prefix-for-opera: true;
        @-o-keyframes #{$name} {
          @content;
        }
      }
      @if $_ea-prefix-for-spec {
        @include ea-disable-prefix-for-all();
        $ea-prefix-for-spec: true;
        @keyframes #{$name} {
          @content;
        }
      }
    
    
      $ea-prefix-for-webkit:    $_ea-prefix-for-webkit;
      $ea-prefix-for-mozilla:   $_ea-prefix-for-mozilla;
      $ea-prefix-for-microsoft: $_ea-prefix-for-microsoft;
      $ea-prefix-for-opera:     $_ea-prefix-for-opera;
      $ea-prefix-for-spec:      $_ea-prefix-for-spec;
    }

    十分简洁优雅的使用:

    /* demo2.scss */
    
    @import "easy-animation.scss";
    
    .pen {
      @include ea-animation(pen, 1s, linear);
    }
    @include ea-keyframes(pen) {
      0% {
        opacity: 0;
        @include ea-transform(translate(100px, 0));
      }
      100% {
        opacity: 1;
        @include ea-transform(translate(0, 0));
      }
    }

    生成的CSS:

    /* demo2.css */
    .pen {
      -webkit-animation: pen 1s linear 0s infinite;
      -moz-animation: pen 1s linear 0s infinite;
      -ms-animation: pen 1s linear 0s infinite;
      -o-animation: pen 1s linear 0s infinite;
      animation: pen 1s linear 0s infinite;
    }
    
    @-webkit-keyframes pen {
      0% {
        opacity: 0;
        -webkit-transform: translate(100px, 0);
      }
      100% {
        opacity: 1;
        -webkit-transform: translate(0, 0);
      }
    }
    
    @-moz-keyframes pen {
      0% {
        opacity: 0;
        -moz-transform: translate(100px, 0);
      }
      100% {
        opacity: 1;
        -moz-transform: translate(0, 0);
      }
    }
    
    @-ms-keyframes pen {
      0% {
        opacity: 0;
        -ms-transform: translate(100px, 0);
      }
      100% {
        opacity: 1;
        -ms-transform: translate(0, 0);
      }
    }
    
    @-o-keyframes pen {
      0% {
        opacity: 0;
        -o-transform: translate(100px, 0);
      }
      100% {
        opacity: 1;
        -o-transform: translate(0, 0);
      }
    }
    
    @keyframes pen {
      0% {
        opacity: 0;
        transform: translate(100px, 0);
      }
      100% {
        opacity: 1;
        transform: translate(0, 0);
      }
    }

    以上.

    本文链接:http://www.cnblogs.com/maplejan/p/3659830.html

    本文作者:Maple Jan

    参考资料:

    http://bourbon.io/

    http://sass-lang.com/

    http://compass-style.org/

  • 相关阅读:
    js下拉框二级关联菜单效果代码具体实现
    js实现拉伸拖动iframe的具体代码
    mysql--Ubuntu下设置MySQL字符集为utf8
    python--使用MySQL数据库
    python--笨方法学python 习题52
    python--web.py使用
    python--flask使用
    python--类方法、对象方法、静态方法
    Python--类定义
    堆 在游戏中的运用
  • 原文地址:https://www.cnblogs.com/maplejan/p/3659830.html
Copyright © 2020-2023  润新知