最近因为项目缘故,勾搭上了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. Java 线程间通讯

    /* 线程间通讯: 多个线程在处理同一资源,但是任务却不同. */ package com.cwcec.test; class Input implements Runnable { Resource ...

  2. 防止DDoS攻击,每5分钟监控本机的web服务,将目前已经建立连接的IP计算出来,且实现top5。再此基础上,将并发连接超过50的IP禁止访问web服务

    netstat -lntupa | grep ":80" | grep ESTABLISHED | awk '{print $5}' | awk -F: '{print $1}' ...

  3. 远程修改VMware ESXi服务器的密码(SSH)

    1,用vSphere client登录到服务器,将SSH启用. 2,使用ssh连接工具(我用的是secureCRT)远程登录,输入passwd,键入两次新密码,OK.  

  4. 笔记之分布式文件系统(DFS)

    不知何故,老外都挺喜欢使用DFS,但是国内公司用这个的不多.一个具体的需求就是,备份服务器在国外,所以启用DFS把国内的数据同步一份到国外进行备份.最近有机会接触DFS,把一些心得体会记录一下. 1. ...

  5. [转帖] 学习一下 apache bench 的总结简介 ( LAMP的没用过..)

    PS:网站性能压力测试是性能调优过程中必不可少的一环.只有让服务器处在高压情况下才能真正体现出各种设置所暴露的问题.Apache中有个自带的,名为ab的程序,可以对Apache或其它类型的服务器进行网 ...

  6. 数组 javaScript权威指南笔记

    创建数组 var a=[1,2,3,4] var arr=new Array() var arr=new Array(10);//创建长度为10的数组   var arr=new Array(1,2, ...

  7. elasticsearch6 学习之并发控制

    环境:elasticsearch6.1.2        kibana6.1.2  并发问题无处不在 一.基于_version 的并发控制 在提交数据前先检查提交数据的version与es中存储的ve ...

  8. BZOJ5212 ZJOI2018历史(LCT)

    首先相当于最大化access的轻重边交换次数. 考虑每个点作为战场(而不是每个点所代表的国家与其他国家交战)对答案的贡献,显然每次产生贡献都是该点的子树内(包括自身)此次access的点与上次acce ...

  9. c++11 可变参数模板类

    c++11 可变参数模板类 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #inc ...

  10. 基本数据结构 —— 二叉搜索树(C++实现)

    目录 什么是二叉搜索树 二叉搜索树如何储存数值 二叉搜索树的操作 插入一个数值 查询是否包含某个数值 删除某个数值 测试代码 参考资料 什么是二叉搜索树 二叉搜索树(英语:Binary Search ...