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:;
@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。虽然这样的代码不会出现任何异常,但作为一个稍稍有点洁癖的程序员,估计都无法忍受这样的效果。
随后想了几个解决方法,都不能很好的解决。主要被以下几个问题困扰着:
- @keyframes所配置的属性,有可能带浏览器的prefix(-webkit-transform),也有可能不带(opacity )。
- 如何才能对不同prefix的@keyframes输出对应的属性。如@-webkit-keyframes能对应上-webkit-transform,而opacity这类非私有的属性则不带上prefix。
- 每一个@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
参考资料:
easy-animation | Animation for Sass的更多相关文章
- Android动画之二:View Animation
作为一个博客<Android其中的动画:Drawable Animation>.android动画主要分为三大部分.上一篇博客已经解说Drawable Animation的使用方法,即逐帧 ...
- Android动画三部曲之中的一个 View Animation & LayoutAnimation
转载请注明出处:http://blog.csdn.net/crazy1235/article/details/50612827 本篇文章对android的Tween动画和帧动画以及布局动画进行总结. ...
- Android Animation动画详解(二): 组合动画特效
前言 上一篇博客Android Animation动画详解(一): 补间动画 我已经为大家介绍了Android补间动画的四种形式,相信读过该博客的兄弟们一起都了解了.如果你还不了解,那点链接过去研读一 ...
- 虾扯蛋:Android View动画 Animation不完全解析
本文结合一些周知的概念和源码片段,对View动画的工作原理进行挖掘和分析.以下不是对源码一丝不苟的分析过程,只是以搞清楚Animation的执行过程.如何被周期性调用为目标粗略分析下相关方法的执行细节 ...
- Android动画效果之Tween Animation(补间动画)
前言: 最近公司项目下个版本迭代里面设计了很多动画效果,在以往的项目中开发中也会经常用到动画,所以在公司下个版本迭代开始之前,抽空总结一下Android动画.今天主要总结Tween Animation ...
- 弄清 CSS3 的 transition 和 animation
弄清 CSS3 的 transition 和 animation transition transition 属性是 transition-property, transition-duration, ...
- 构造自己的动画函数:animation,stop功能的实现
最近做一个广告项目,里面涉及很多动画效果,由于不能使用jquery,所以只能构建自己的动画方法. 数据结构: elem是DOM对象,给它设置一个属性对象,用来记录elem的动画对象,比如'left', ...
- 安卓中級教程(8):pathbutton中的animation.java研究(1)
src/geniuz/myPathbutton/myAnimations.java package geniuz.myPathbutton; import java.util.ArrayList; i ...
- 老司机带你走进Core Animation
为什么时隔这么久我又回来了呢? 回来圈粉. 开玩笑的,前段时间ipv6被拒啊,超级悲剧的,前后弄了好久,然后需求啊什么的又超多,所以写好的东西也没有时间整理.不过既然我现在回来了,那么这将是一个井喷的 ...
- android 补间动画和Animation
介绍: 补间动画是一种设定动画开始状态.结束状态,其中间的变化由系统计算补充.这也是他叫做补间动画的原因. 补间动画由Animation类来实现具体效果,包括平移(TranslateAnimation ...
随机推荐
- 字符串经过base64编码后的长度与原字符串的长度是什么关系呀?
beforeEncode为Encode之前的字符串 那么Encode后的字符串长度为: 1.如果beforeEncode.length()是3的整数倍,那么长度为 (beforeEncode.len ...
- pyqt5 eric6
1 安装Anaconda3 2 python环境变量改为Anaconda3中python 3 pip安装pyqt5 ,pip安装pyqt5-tool 其中tool中包含eric6 ui文件必须使用的d ...
- java异常处理的throw和throws的区别
1. 区别 throws是用来声明一个方法可能抛出的所有异常信息,throws是将异常声明但是不处理,而是将异常往上传,谁调用我就交给谁处理.而throw则是指抛出的一个具体的异常类型. 2.分别介绍 ...
- P4838 P哥破解密码
题目背景 P哥是一个经常丢密码条的男孩子. 在ION 8102赛场上,P哥又弄丢了密码条,笔试满分的他当然知道这可是要扣5分作为惩罚的,于是他开始破解ION Xunil系统的密码. 题目描述 定义一个 ...
- MT【149】和式变形
(2018浙江省赛14题)将$2n(n\ge2)$个不同的整数分成两组$a_1,a_2,\cdots,a_n;b_1,b_2,\cdots,b_n$.证明:$\sum\limits_{1\le i\l ...
- Virtual Table
C++对象模型——吴泰 C/C++杂记 C++中的虚函数(表)实现机制以及用C语言对其进行的模拟实现 C++ 多继承和虚继承的内存布局 [已翻译100%] (虚继承参考,推荐) 图说C++对象模型:对 ...
- 服务器启动完成执行定时任务Timer,TimerTask
由于项目需求:每隔一段时间就要调外部接口去进行某些操作,于是在网上找了一些资料,用了半天时间弄好了,代码: import java.util.TimerTask; public class Accou ...
- 【HBuilder】手机App推送至Apple App Store过程
一.前言 最近由于公司同事离职,顶替这位同事从事手机App的研发工作,BIM数据平台部门采用的是HBuilder作为手机App的制作环境.本篇介绍我是如何将HBuilder的Releas ...
- 51nod 1206 Picture 矩形周长求并 | 线段树 扫描线
51nod 1206 Picture 矩形周长求并 | 线段树 扫描线 #include <cstdio> #include <cmath> #include <cstr ...
- 【转】arm-none-linux-gnueabi-gcc下载
arm-none-linux-gnueabi-gcc是 Codesourcery 公司(目前已经被Mentor收购)基于GCC推出的的ARM交叉编译工具.可用于交叉编译ARM系统中所有环节的代码,包括 ...