写在前面:感谢腾讯课堂与妙味课堂的移动端公开课
对于需要设置动画的元素需要提前设置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; } }