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

  对于需要设置动画的元素需要提前设置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. 在eclipse中安装html编辑器插件

    1.下载插件( 点击下载)                 解压后得到GEF-ALL-3.4.1.zip和tk.eclipse.plugin.htmleditor_2.2.0.jar   2.安装GE ...

  2. bnuoj25660 Two Famous Companies

    题目链接:https://www.bnuoj.com/v3/problem_show.php?pid=25660 这个二分真的是烧脑QAQ,想了一晚上才懂了一个大概. 首先,整体思路是二分,直观上感受 ...

  3. Naive Operations HDU多校(线段树上线段果)

    Problem Description In a galaxy far, far away, there are two integer sequence a and b of length n.b ...

  4. git 回退

    回退命令: $ git reset --hard HEAD^ 回退到上个版本$ git reset --hard HEAD~3 回退到前3次提交之前,以此类推,回退到n次提交之前 $ git rese ...

  5. linux下bash脚本语法

    1.shell中的变量定义和引用(1)变量定义和初始化.shell是弱类型语言(语言中的变量如果有明确的类型则属于强类型语言:变量没有明确类型就是弱类型语言),和C语言不同.在shell编程中定义变量 ...

  6. RotateAnimation 详解

    RotateAnimation 详解 看看新闻网>看引擎>开源产品 其他构造器的旋转也可参考这副图. RotateAnimation旋转坐标系为以旋转点为坐标系(0,0)点.x轴为0度,顺 ...

  7. 使用 html2canvas 实现浏览器截图

    基于上一篇<h5 本地上传图片预览 源码下载>,今天分享一个图片上传后, 根据所上传的图片颜值随机生成一个答案, 并且可以生成一张专属于自己的名片. 首先上传预览我们已经实现了, 所以接下 ...

  8. css 常用苹方字体

    // 苹方-简 常规体 font-family: PingFangSC-Regular, sans-serif; // 苹方-简 极细体 font-family: PingFangSC-Ultrali ...

  9. sqlserver xml转表 及(cross apply与outer apply)

    一. 需求是需要把','分割的字符串转为表,便于做关联查询,于是发现可以通过xml转为表,如下: declare @XXX xml set @XXX = ' <v> <aa>1 ...

  10. windows修改文件的修改或者创建时间

    https://www.online-tech-tips.com/computer-tips/how-to-change-the-last-modified-date-creation-date-an ...