原生js实现jq的animate效果(有一定bug未修复,有时间补上)
//原生js实现jq的animate效果
/**
*@param obj 执行动画的元素
*@param css JSON数值对,形式为“{属性名: 属性值}",指要执行动画的书序及其对应值
*@param interval 属性每执行一次改变的时间间隔
*@param speedFactor 速度因子,使动画具有缓冲效果,而不是匀速不变(speedFactor为1)
*@param func 执行完动画后的回调函数
*/
// 必须为每一个元素分别添加一个定时器,否则会互相影响。
// cur != css[arr]判断是否每一个属性已经达到目标值。
// 只有所有属性都达到目标值,才会清除定时器,flag的作用是防止某个属性第一个达到目标值但还有其他属性没有达到目标值的情况下清除定时器。
// 因此,在每次改变前初始化flag为true,只要遇到一个没有达到目标的属性,就将flag置为false,直至所有属性达到目标值才清除定时器。
// 属性值opacity的值有小数,所以需要特殊处理: Math.ceil(speed)和Math.floor(speed)以及* 100和 / 100操作。
function animate(obj, css, interval, speedFactor, func) {
clearInterval(obj.timer);
function getCss(obj, prop) {
if (obj.currentStyle) return obj.currentStyle[prop]; // ie
else return document.defaultView.getComputedStyle(obj, null)[prop]; // 非ie
}
obj.timer = setInterval(function(){
var flag = true;
for (var prop in css) {
var cur = 0;
if(prop == "opacity"){
cur = Math.round(parseFloat(getCss(obj, prop)) * 100)
}else cur = parseInt(getCss(obj, prop));
var speed = (css[prop] - cur) * speedFactor;
speed = speed > 0 ? Math.ceil(speed): Math.floor(speed);
if (cur != css[prop]) flag = false;
if (prop == "opacity") {
obj.style.filter = "alpha(opacity:'+(cur + speed)+' )";
obj.style.opacity = (cur + speed) / 100;
} else obj.style[prop] = cur + speed + "px";
}
if (flag){
clearInterval(obj.timer);
if (func) func();
}
}, interval);
}
// 原生js实现jq的 css addClass removeClass toggleClass
// css(name):访问第一匹配元素的样式属性
// css(name,value):在所有匹配的元素中,设置一个样式属性的值
// css(properties):把一个“名/值对”对象设置为所有匹配元素的样式属性
// css(name,function(index,value)):在所有匹配的元素中,设置一个样式属性的值
function css(obj, attr, value) {
switch (arguments.length) {
case 2:
if (typeof arguments[1] == "object") { //批量设置属性
for (var i in attr) obj.style[i] = attr[i]
}
else { // 读取属性值
return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj, null)[attr]
}
break;
case 3:
//设置属性
obj.style[attr] = value;
break;
default:
return "";
}
}
// addClass(class):为每个匹配的元素添加指定的类名
// removeClass(class):从所有匹配的元素中删除全部或者指定的类
// toggleClass(class):如果存在(不存在)就删除(添加)一个类
function addClass(obj, cls){
var obj_class = obj.className, //获取 class 内容.
blank = (obj_class != '') ? ' ' : '', //判断获取到的 class 是否为空, 如果不为空在前面加个'空格'.
added = obj_class + blank + cls; //组合原来的 class 和需要添加的 class.
obj.className = added; //替换原来的 class.
}
function removeClass(obj, cls){
var obj_class = ' '+obj.className+' ', //获取 class 内容, 并在首尾各加一个空格. ex) 'abc bcd' -> ' abc bcd '
obj_class = obj_class.replace(/(\s+)/gi, ' '), //将多余的空字符替换成一个空格. ex) ' abc bcd ' -> ' abc bcd '
removed = obj_class.replace(' '+cls+' ', ' '), //在原来的 class 替换掉首尾加了空格的 class. ex) ' abc bcd ' -> 'bcd '
removed = removed.replace(/(^\s+)|(\s+$)/g, ''); //去掉首尾空格. ex) 'bcd ' -> 'bcd'
obj.className = removed; //替换原来的 class.
}
function hasClass(obj, cls){
var obj_class = obj.className, //获取 class 内容.
obj_class_lst = obj_class.split(/\s+/), //通过split空字符将cls转换成数组.
x = 0;
for(x in obj_class_lst) {
if(obj_class_lst[x] == cls) return true; //循环数组, 判断是否包含cls
}
return false;
}