最近因为项目缘故,勾搭上了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:;
@include translate(100px, 0);
}
100% {
opacity:;
@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:;
-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:;
-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:;
-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:;
-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:;
-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:;
-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:;
-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:;
-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:;
-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:;
-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:;
// @include ea-transform(scale(1));
// }
// 50% {
// opacity: 0.8;
// @include ea-transform(scale(0.8));
// }
// 100% {
// opacity:;
// @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:;
@include ea-transform(translate(100px, 0));
}
100% {
opacity:;
@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:;
-webkit-transform: translate(100px, 0);
}
100% {
opacity:;
-webkit-transform: translate(0, 0);
}
} @-moz-keyframes pen {
0% {
opacity:;
-moz-transform: translate(100px, 0);
}
100% {
opacity:;
-moz-transform: translate(0, 0);
}
} @-ms-keyframes pen {
0% {
opacity:;
-ms-transform: translate(100px, 0);
}
100% {
opacity:;
-ms-transform: translate(0, 0);
}
} @-o-keyframes pen {
0% {
opacity:;
-o-transform: translate(100px, 0);
}
100% {
opacity:;
-o-transform: translate(0, 0);
}
} @keyframes pen {
0% {
opacity:;
transform: translate(100px, 0);
}
100% {
opacity:;
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/

easy-animation | Animation for Sass的更多相关文章

  1. Android动画之二:View Animation

    作为一个博客<Android其中的动画:Drawable Animation>.android动画主要分为三大部分.上一篇博客已经解说Drawable Animation的使用方法,即逐帧 ...

  2. Android动画三部曲之中的一个 View Animation &amp; LayoutAnimation

    转载请注明出处:http://blog.csdn.net/crazy1235/article/details/50612827 本篇文章对android的Tween动画和帧动画以及布局动画进行总结. ...

  3. Android Animation动画详解(二): 组合动画特效

    前言 上一篇博客Android Animation动画详解(一): 补间动画 我已经为大家介绍了Android补间动画的四种形式,相信读过该博客的兄弟们一起都了解了.如果你还不了解,那点链接过去研读一 ...

  4. 虾扯蛋:Android View动画 Animation不完全解析

    本文结合一些周知的概念和源码片段,对View动画的工作原理进行挖掘和分析.以下不是对源码一丝不苟的分析过程,只是以搞清楚Animation的执行过程.如何被周期性调用为目标粗略分析下相关方法的执行细节 ...

  5. Android动画效果之Tween Animation(补间动画)

    前言: 最近公司项目下个版本迭代里面设计了很多动画效果,在以往的项目中开发中也会经常用到动画,所以在公司下个版本迭代开始之前,抽空总结一下Android动画.今天主要总结Tween Animation ...

  6. 弄清 CSS3 的 transition 和 animation

    弄清 CSS3 的 transition 和 animation transition transition 属性是 transition-property, transition-duration, ...

  7. 构造自己的动画函数:animation,stop功能的实现

    最近做一个广告项目,里面涉及很多动画效果,由于不能使用jquery,所以只能构建自己的动画方法. 数据结构: elem是DOM对象,给它设置一个属性对象,用来记录elem的动画对象,比如'left', ...

  8. 安卓中級教程(8):pathbutton中的animation.java研究(1)

    src/geniuz/myPathbutton/myAnimations.java package geniuz.myPathbutton; import java.util.ArrayList; i ...

  9. 老司机带你走进Core Animation

    为什么时隔这么久我又回来了呢? 回来圈粉. 开玩笑的,前段时间ipv6被拒啊,超级悲剧的,前后弄了好久,然后需求啊什么的又超多,所以写好的东西也没有时间整理.不过既然我现在回来了,那么这将是一个井喷的 ...

  10. android 补间动画和Animation

    介绍: 补间动画是一种设定动画开始状态.结束状态,其中间的变化由系统计算补充.这也是他叫做补间动画的原因. 补间动画由Animation类来实现具体效果,包括平移(TranslateAnimation ...

随机推荐

  1. NTP同步网络时间

    为什么要同步网络时间呢,这是由于树莓派没有RTC和后备电池,不能像PC机那样关机之后仍可以走时. NTP对时步骤: 1 安装ntpdate sudo apt-get install ntpdate s ...

  2. 正确的姿势解决IE弹出证书错误页面

    在遇到IE证书问题时,正确的解法是安装证书到受信任的储存区 1.继续浏览此网站 2.进入页面后,点击地址栏的证书错误,查看证书 3.安装,设置安装到受信任的颁发机构 4.OK  

  3. maven执行"mvn clean package" 命令报错

    昨天利用mvn打包,执行程序'mvn clean package' 命令,发现打包失败 问题描述 具体看代码 发信tomcat下的log 清除不掉.为什么呢?忽然想起来我的项目服务还起着,于是我把服务 ...

  4. IbatisNet连接oracle 报错

    提示什么 connect oracle   1.5.0.xxxx 将你本机的oracle 客户端版本重装换成32位即可

  5. Mysql向数据库插入数据时,判断是否存在,若不存在就插入数据

    表中一定要有主键  : select :id,此处的id位置处必须是主键 insert into table_name(id, name, password) select :id, :name, : ...

  6. Tomcat8.0配置JNDI多数据源

    jndi配置 :此种配置需要在Tomcat的server.xml中和context.xml中配置数据源,在项目中引用. 需要在tomcat下加入数据库连接的jar包,相关包(ojdbc14;c3p0数 ...

  7. 【转】关于在linux下清屏的几种技巧

    在windows的DOS操作界面里面,清屏的命令是cls,那么在linux 里面的清屏命令是什么呢?下面笔者分享几种在linux下用过的清屏方法. 1.clear命令.这个命令将会刷新屏幕,本质上只是 ...

  8. java多线程 -- 原子量 变量 CAS

    多线程原子性问题的产生和解决 原子变量:在 java.util.concurrent.atomic 包下提供了一些原子变量. 1. volatile 保证内存可见性,可以查看atomic中变量是使用v ...

  9. Android Studio怎么文件添加到收藏和打开收藏夹

    http://jingyan.baidu.com/article/1709ad809e608b4634c4f0b9.html 在使用Android studio编写的代码的过程中,有时会碰到有一些文件 ...

  10. supervisor "unix:///var/run/supervisor/supervisor.sock no such file" 解决方法

    如果是没有开启 supervisord 服务的情况下出现这种报错,可以先 systemctl start supervisor 试试, 如果不是,那就 sudo touch /var/run/supe ...