写在前面:感谢腾讯课堂与妙味课堂的移动端公开课

  对于需要设置动画的元素需要提前设置css()样式,这样数据才会被记录起来。

function css(ele, attr, val) {
if (/rotate/.test(attr) || /scale/.test(attr) || /skew/.test(attr) || /translate/.test(attr)) {
return cssTransform(ele, attr, val);
}
if (arguments.length == 2) {
var val = getComputedStyle(ele)[attr];
if (attr == 'opacity') {
val = Math.round(val * 100);
}
return parseFloat(val)
}
if (attr == 'opacity') {
ele.style.opacity = val / 100;
} else {
ele.style[attr] = val + 'px'
}
}

这里需要判断属于transform的值

/*
* 设置transform 只能在这里设置 不能在css设置
* ele.transform ={
* rotate: 40,
* scale: 100,
* skew:
* translate
* }
* */
function cssTransform(ele, attr, val) {
ele.transform = ele.transform || {}
if (typeof val == "undefined") {
//get
if (typeof ele.transform[attr] == 'undefined') { //代表没有设置transform 返回默认值
switch (attr) {
case 'scale':
case 'scaleX':
case 'scaleY':
case 'scaleZ':
ele.transform[attr] = 100;
break;
default:
ele.transform[attr] = 0;
break;
}
}
return ele.transform[attr];
} else {
//set
var transformVal = '';
ele.transform[attr] = val; for (s in ele.transform) {
switch (s) {
case 'scale':
case 'scaleX':
case 'scaleY':
case 'scaleZ':
transformVal += " " + s + "(" + ele.transform[s]/100 + ")";
break;
case 'rotate':
case 'rotateX':
case 'rotateY':
case 'rotateZ':
case 'skew':
case 'skewX':
case 'skewY':
transformVal += " " + s + "(" + ele.transform[s] + "deg)";
break;
default:
transformVal += " " + s + "(" + ele.transform[s] + "px)";
break;
}
} ele.style.WebkitTransform = ele.style.transform = transformVal;
}
}

通过检测,在合适位置调用MTwen函数

/*
* @param el:控制元素 (element)
* @param target:想要达成效果的数据 例如:translateY (string)
* @param time:历时 (number)
* @param type:运动效果 (string)
* @param callIn:运动中执行的函数 (fn)
* @param callBack:运动结束执行的函数 (fn)
* */
function MTween(init) {
var t = 0;
var b = {};
var c = {};
var d = init.time / 20;
for (var s in init.target) {
b[s] = css(init.el, s);
c[s] = init.target[s] - b[s];
}
clearInterval(init.el.timer);
init.el.timer = setInterval(function () {
t++;
if (t > d) {
clearInterval(init.el.timer);
init.callBack && init.callBack.call(init.el);
} else {
init.callIn && init.callIn.call(init.el);
for (var s in b) {
var val = Number((Tween[init.type](t, b[s], c[s], d)).toFixed(2));
css(init.el, s, val)
}
}
},20)
}

先上完整的代码

function css(ele, attr, val) {

    if (/rotate/.test(attr) || /scale/.test(attr) || /skew/.test(attr) || /translate/.test(attr)) {
return cssTransform(ele, attr, val);
}
if (arguments.length == 2) {
var val = getComputedStyle(ele)[attr];
if (attr == 'opacity') {
val = Math.round(val * 100);
}
return parseFloat(val)
}
if (attr == 'opacity') {
ele.style.opacity = val / 100;
} else {
ele.style[attr] = val + 'px'
}
}
/*
* @param el:控制元素 (element)
* @param target:想要达成效果的数据 例如:translateY (string)
* @param time:历时 (number)
* @param type:运动效果 (string)
* @param callIn:运动中执行的函数 (fn)
* @param callBack:运动结束执行的函数 (fn)
* */
function MTween(init) {
var t = 0;
var b = {};
var c = {};
var d = init.time / 20;
for (var s in init.target) {
b[s] = css(init.el, s);
c[s] = init.target[s] - b[s];
}
clearInterval(init.el.timer);
init.el.timer = setInterval(function () {
t++;
if (t > d) {
clearInterval(init.el.timer);
init.callBack && init.callBack.call(init.el);
} else {
init.callIn && init.callIn.call(init.el);
for (var s in b) {
var val = Number((Tween[init.type](t, b[s], c[s], d)).toFixed(2));
css(init.el, s, val)
}
}
},20)
} /*
* 设置transform 只能在这里设置 不能在css设置
* ele.transform ={
* rotate: 40,
* scale: 100,
* skew:
* translate
* }
* */
function cssTransform(ele, attr, val) {
ele.transform = ele.transform || {}
if (typeof val == "undefined") {
//get
if (typeof ele.transform[attr] == 'undefined') { //代表没有设置transform 返回默认值
switch (attr) {
case 'scale':
case 'scaleX':
case 'scaleY':
case 'scaleZ':
ele.transform[attr] = 100;
break;
default:
ele.transform[attr] = 0;
break;
}
} return ele.transform[attr];
} else {
//set
var transformVal = '';
ele.transform[attr] = val; for (s in ele.transform) {
switch (s) {
case 'scale':
case 'scaleX':
case 'scaleY':
case 'scaleZ':
transformVal += " " + s + "(" + ele.transform[s]/100 + ")";
break;
case 'rotate':
case 'rotateX':
case 'rotateY':
case 'rotateZ':
case 'skew':
case 'skewX':
case 'skewY':
transformVal += " " + s + "(" + ele.transform[s] + "deg)";
break;
default:
transformVal += " " + s + "(" + ele.transform[s] + "px)";
break;
}
} ele.style.WebkitTransform = ele.style.transform = transformVal;
}
} /*
* t : time 已过时间
* b : begin 起始值
* c : count 总的运动值
* d : duration 持续时间
* */ //Tween.linear(); var Tween = {
linear: function (t, b, c, d) { //匀速
return c * t / d + b;
},
easeIn: function (t, b, c, d) { //加速曲线
return c * (t /= d) * t + b;
},
easeOut: function (t, b, c, d) { //减速曲线
return -c * (t /= d) * (t - 2) + b;
},
easeBoth: function (t, b, c, d) { //加速减速曲线
if ((t /= d / 2) < 1) {
return c / 2 * t * t + b;
}
return -c / 2 * ((--t) * (t - 2) - 1) + b;
},
easeInStrong: function (t, b, c, d) { //加加速曲线
return c * (t /= d) * t * t * t + b;
},
easeOutStrong: function (t, b, c, d) { //减减速曲线
return -c * ((t = t / d - 1) * t * t * t - 1) + b;
},
easeBothStrong: function (t, b, c, d) { //加加速减减速曲线
if ((t /= d / 2) < 1) {
return c / 2 * t * t * t * t + b;
}
return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
},
elasticIn: function (t, b, c, d, a, p) { //正弦衰减曲线(弹动渐入)
if (t === 0) {
return b;
}
if ((t /= d) == 1) {
return b + c;
}
if (!p) {
p = d * 0.3;
}
if (!a || a < Math.abs(c)) {
a = c;
var s = p / 4;
} else {
var s = p / (2 * Math.PI) * Math.asin(c / a);
}
return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
},
elasticOut: function (t, b, c, d, a, p) { //正弦增强曲线(弹动渐出)
if (t === 0) {
return b;
}
if ((t /= d) == 1) {
return b + c;
}
if (!p) {
p = d * 0.3;
}
if (!a || a < Math.abs(c)) {
a = c;
var s = p / 4;
} else {
var s = p / (2 * Math.PI) * Math.asin(c / a);
}
return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
},
elasticBoth: function (t, b, c, d, a, p) {
if (t === 0) {
return b;
}
if ((t /= d / 2) == 2) {
return b + c;
}
if (!p) {
p = d * (0.3 * 1.5);
}
if (!a || a < Math.abs(c)) {
a = c;
var s = p / 4;
}
else {
var s = p / (2 * Math.PI) * Math.asin(c / a);
}
if (t < 1) {
return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) *
Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
}
return a * Math.pow(2, -10 * (t -= 1)) *
Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b;
},
backIn: function (t, b, c, d, s) { //回退加速(回退渐入)
if (typeof s == 'undefined') {
s = 1.70158;
}
return c * (t /= d) * t * ((s + 1) * t - s) + b;
},
backOut: function (t, b, c, d, s) {
if (typeof s == 'undefined') {
s = 3.70158; //回缩的距离
}
return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
},
backBoth: function (t, b, c, d, s) {
if (typeof s == 'undefined') {
s = 1.70158;
}
if ((t /= d / 2 ) < 1) {
return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
}
return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
},
bounceIn: function (t, b, c, d) { //弹球减振(弹球渐出)
return c - Tween['bounceOut'](d - t, 0, c, d) + b;
},
bounceOut: function (t, b, c, d) {
if ((t /= d) < (1 / 2.75)) {
return c * (7.5625 * t * t) + b;
} else if (t < (2 / 2.75)) {
return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;
} else if (t < (2.5 / 2.75)) {
return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;
}
return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;
},
bounceBoth: function (t, b, c, d) {
if (t < d / 2) {
return Tween['bounceIn'](t * 2, 0, c, d) * 0.5 + b;
}
return Tween['bounceOut'](t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
}
}

接下来说一下使用方式

1.设置css(el,'translateY',) //获取translateY的值

2.处理后 css(el, 'translateY', -translateY*scale)//获设置translateY的值

3.运行动画

 MTween({
el: el,
target: {
translateY: target
},
time:3,
type: 'backOut',
callBack: function () {
(init.offBar)|| (scrollBar.style.opacity = 0);
},
callIn: function () {
var translateY = css(inner, 'translateY');
(init.offBar)|| css(scrollBar, 'translateY', -translateY*scale);
}
})

接下来的完整的代码

可以自己去尝试下

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width,user-scalable=no,initial-scale=1.0">
<title>Title</title>
<style>
body {
margin: 0;
} body, html {
height: 100%;
overflow: hidden;
position: relative;
} header {
height: 40px;
font-size: 20px;
line-height: 40px;
text-align: center;
background: #000;
color: #fff;
width: 100%;
} footer {
height: 40px;
line-height: 40px;
text-align: center;
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: #000;
color: white;
} #wrap {
position: absolute;
left: 0;
right: 0;
bottom: 40px;
top: 40px;
overflow: hidden;
} #list {
margin: 0;
padding: 0;
list-style: none;
} #list li {
height: 30px;
border-bottom: 1px solid #000;
line-height: 30px;
text-indent: 20px;
font-size: 16px;
}
</style>
</head>
<body>
<header id="header">测试滑屏动画</header>
<section id="wrap">
<ul id="list"></ul>
</section>
<footer id="footer">慢慢的干活,还是很不错</footer>
<script src="m.Tween.js"></script>
<script>
/*
* 缓冲动画
* 获取最后一次速度=位移/时间
*
* */
document.addEventListener('touchstart', function (ev) {
ev.preventDefault();
})
function setListInner() {
var list = document.querySelector('#list');
var inner = '';
for (var i = 0; i < 100; i++) {
inner += '<li>这是第' + i + '个li</li>'
}
list.innerHTML = inner
}
window.onload = function () {
setListInner();
var wrap = document.querySelector('#wrap');
mScroll({
el: wrap,
offBar : false,
start : function(e){ },
move : function(e){ },
end:function(e){ },
over:function(e){ }
})
}; //添加父级
function mScroll(init){
if(!init.el){
return;
} var inner = init.el.children[0];
var scrollBar = document.createElement('div'); var startPoint = 0;
var startEl = 0;
var lastDis = 0; //最后一次距离
var lastY = 0; //上一次距离
var lastTime = 0;
var lastTimeDis = 0;
var maxTranslate = init.el.clientHeight - inner.offsetHeight;
var scale = init.el.clientHeight / inner.offsetHeight; inner.style.minHeight = '100%'; if(!init.offBar){
scrollBar.style.cssText = 'width:6px;background:rgba(0,0,0,.5);' +
'position:absolute;right:0;top:0;border-radius:3px;opacity:0;transition:opacity .3s';
init.el.appendChild(scrollBar);
} //设置动画
css(inner, 'translateZ', 0.01); inner.addEventListener('touchstart', function (e) {
clearInterval(inner.time);
//预留后面高度被改变
maxTranslate = init.el.clientHeight - inner.offsetHeight;
//内容太少
if(!init.offBar){
if(maxTranslate >= 0){
scrollBar.style.display = 'none'
}else{
scrollBar.style.display = 'block' }
scale = init.el.clientHeight / inner.offsetHeight;
scrollBar.style.height = init.el.clientHeight * scale+'px';
} startPoint = e.changedTouches[0].pageY;
startEl = css(inner, 'translateY'); //获得点击下去的translateY 的值
lastY = startEl; //赋值每一次开始的位置
lastTimeDis = lastDis = 0;
lastTime = new Date().getTime(); (init.offBar)||(scrollBar.style.opacity = 1);
});
inner.addEventListener('touchmove', function (e) { var nowPoint = e.changedTouches[0].pageY;
var dis = nowPoint - startPoint;
var translateY = dis + startEl;
var nowTime = new Date().getTime();
css(inner, 'translateY', translateY);
(init.offBar)||css(scrollBar, 'translateY', -translateY*scale); lastDis = translateY - lastY;
lastY = translateY;
lastTimeDis = nowTime - lastTime;
lastTime = nowTime; });
inner.addEventListener('touchend', function (e) {
var type = 'easeOut';
var speed = Math.round(lastDis / lastTimeDis * 10);
speed = lastTimeDis <= 0 ? 0 : speed;
var target = Math.round(speed * 30 + css(inner, 'translateY'));//缓冲距离 if (target > 0) {
target = 0;
type = 'backOut'
} else if (target < maxTranslate) {
target = maxTranslate;
type = 'backOut'
} MTween({
el: inner,
target: {
translateY: target
},
time: Math.round(Math.abs(target - css(inner, 'translateY')) * 1.5),
type: type,
callBack: function () {
(init.offBar)|| (scrollBar.style.opacity = 0);
},
callIn: function () {
var translateY = css(inner, 'translateY');
(init.offBar)|| css(scrollBar, 'translateY', -translateY*scale);
}
}) }) } </script>
</body>
</html>

封装CSS动画的更多相关文章

  1. amazeui学习笔记--css(常用组件15)--CSS动画Animation

    amazeui学习笔记--css(常用组件15)--CSS动画Animation 一.总结 1.css3动画封装:CSS3 动画封装,浏览器需支持 CSS3 动画. Class 描述 .am-anim ...

  2. 原生Js封装的动画类

    算法用的是Tween类,需要研究的参考这篇文章: http://www.cnblogs.com/cloudgamer/archive/2009/01/06/Tween.html 网页里常用的动画 放大 ...

  3. CSS 动画一站式指南

    CSS 动画一站式指南 目录 CSS 动画一站式指南 1. CSS 动画 1.1 变换 1.1.1 变换属性介绍 1.1.2 变换动画实践 1.2 过渡 1.2.1 过渡属性介绍 1.2.2 过渡动画 ...

  4. 梅须逊雪三分白,雪却输梅一段香——CSS动画与JavaScript动画

    CSS动画并不是绝对比JavaScript动画性能更优越,开源动画库Velocity.js等就展现了强劲的性能. 一.两者的主要区别 先开门见山的说说两者之间的区别. 1)CSS动画: 基于CSS的动 ...

  5. Css 动画的回调

    在做项目中经常会遇到使用动画的情况.以前的情况是用js写动画,利用setTimeout函数或者window.requestAnimationFrame()实现目标元素的动画效果.虽然后者解决了刷新频率 ...

  6. 【译】css动画里的steps()用法详解

    原文地址:http://designmodo.com/steps-c... 原文作者:Joni Trythall 我想你在css 动画里使用steps()会和我一样有很多困惑.一开始我不清楚怎样使用它 ...

  7. css动画属性性能

    性能主要表现:流量.功耗与流畅度 在现有的前端动画体系中,通常有两种模式:JS动画与CSS3动画. JS动画是通过JS动态改写样式实现动画能力的一种方案,在PC端兼容低端浏览器中不失为一种推荐方案. ...

  8. Css动画形式弹出遮罩层,内容区上下左右居中于不定宽高的容器中

    <!DOCTYPE html> <html> <head> </head> <body id="body"> <! ...

  9. css动画与js动画的区别

    CSS动画 优点: (1)浏览器可以对动画进行优化.   1. 浏览器使用与 requestAnimationFrame 类似的机制,requestAnimationFrame比起setTimeout ...

随机推荐

  1. HDU 2852 主席树

    KiKi's K-Number Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  2. redis缓存在项目中的使用

    关于redis为什么能作为缓存这个问题我们就不说了,直接来说一下redis缓存到底如何在项目中使用吧: 1.redis缓存如何在项目中配置? 1.1redis缓存单机版和集群版配置?(redis的客户 ...

  3. [mysql]深入Mysql字符集设置[转载]

    http://www.laruence.com/2008/01/05/12.html 基本概念 • 字符(Character)是指人类语言中最小的表义符号.例如’A'.’B'等: • 给定一系列字符, ...

  4. C#学习目录处理

    目录获取和处理: string path = ".";//表明要在当前所在的目录 //先定义目录信息变量 DirectoryInfo dir = new DirectoryInfo ...

  5. HDU1530 最大团 模板

    Maximum Clique Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  6. gitlab 的使用策略和简单介绍

    gitlab 作为版本控制器,基本使用和github 相同,以下是一些策略和介绍: Git 分支管理策略可以参考下面三个链接: http://www.ruanyifeng.com/blog/2012/ ...

  7. 通过反射获取T.class代码片段

    说明 持久化框架MyBatis和Hibernate中我们多多少少都会自己取写工具类!但是我们一般都会处理结果集转换成持久化对象,但是我们都要使用类! 代码片段 abstract public clas ...

  8. [技巧篇]01.Servlet的优化模版代码

    Servlet.java的模版 #---------------------------------------------# # <aw:description>Template for ...

  9. springboot以jar包方式启动、关闭、重启脚本

    springboot以jar包方式启动.关闭.重启脚本 启动 编写启动脚本startup.sh #!/bin/bash echo Starting application nohup java -ja ...

  10. 51Nod 1083 矩阵取数问题 | 动态规划

    #include "bits/stdc++.h" using namespace std; #define LL long long #define INF 0x3f3f3f3f3 ...