照着视频的代码实践了一次,发现没有把flag重置为true的代码,但是最后确确实实是清除了定时器,那么,flag是什么时候被重置的呢?
另外,看到有人回答,flag应该被声明在定时器里面,这个是不对的。如果声明在定时器里面,那么就会出现视频中声明flag之前的bug。
求大神解答一下。
上面的问题好像有点不清晰哈,下面说清楚一点。
flag=true是放在定时器外面的,对吧?定时器里面是没有代码把flag重置为true的,当第一次代码执行到
if(icur!=json[attr]){
flag=false;
}
这里的时候,flag就被赋值为false了,之后都没有给flag赋值为true。
那么最后是怎么判断到flag=true的呢?
在这里就很不明白,因为没有把flag重置为true的话,其实是没办法执行
if(flag){
clearInterval(obj.timer);
if(fn){
fn();
}
}和之后的fn函数的。
看完了楼主写的,完全没有毛病,教程代码确实有BUG,不过既然因为 speed = (json[attr] - icur)/8 语句, 当 speed 为0时就能自己停止,为什么教程还要加一大堆检测停止的代码,我发现把那一大段去掉之后功能正常啊,不知道我有没有想错?
把flag放外面,最后速度为0,动画是停止了,但是代码一直在运行,无限循环的运行,if(flag)永远到不了
没仔细看,原来你的代码已经解决了。。
一、var flag = true; 是放在定时器外面的。
二、每次启动定时器强制 flag = true。
三、在for循环外面,再次判断flag。
还需要把
if(flag){
clearInterval(obj.timer);
if(fn){
fn();
}
这一段放在for 循环外面。。.
-------------手动分割------------------
楼主,你看看有木有bug,或者你有其他解决方案了没有?
我去,不行。。
//同步运动函数
function move(obj, json, fn) {
//清除定时器,避免出现多个定时器
clearInterval(obj.timer);
//设定定时器
obj.timer = setInterval(function () {
//声明标杆
var flag = true;
//遍历同步运动属性
for (var attr in json) {
//获取属性值
var icur = 0;
if (attr == 'opacity') {
icur = Math.round(parseFloat(getStyle(obj,attr)) * 100);
} else {
icur = parseInt(getStyle(obj, attr));
}
//设置运动速度
var speed = (json[attr] - icur)/100;
speed = speed>0?Math.ceil(speed):Math.floor(speed);
// 判断是否所有值都达到了目标值,判定暂停定时器的指标
if (icur != json[attr]) {
flag = false;
}
if (attr == 'opacity') {
obj.style.opacity = (icur + speed) / 100;
obj.style.filter = 'alpha(opacity:' + (icur + speed) + ')';
} else {
obj.style[attr] = (icur + speed) + 'px';
}
}
// 注意,for in遍历到此结束,下面的清除定时器部分不属于for遍历里面的代码,是定时器最后面的部分
//清除定时器
if(flag){
clearInterval(obj.timer);
if(fn){
fn();
}
}
}, 1);
}
//获取任意属性
function getStyle(obj, attr) {
if (obj.currentStyle) {
return obj.currentStyle[attr]; //IE取样式
} else {
return getComputedStyle(obj, false)[attr];
}
}经过多番测试,视频中的完美运动代码存在bug,这个框架只可以实现同步动画,不可以实现链式动画。
同步动画最后会停止,不是因为
if(flag){
clearInterval(obj.timer);
if(fn){
fn();
}
}而是代码中的
speed = (json[attr] - icur)/8;
这一部分等于0了,也就是说,动画不再变化了,看起来就好像清除了定时器一样。
如果在清除定时器的判定语句中加入一个测试语句,可以发现,第一次鼠标移入目标的时候,第一次执行到这个动画,是不会执行到测试的语句的,说明定时器的判定语句并未执行。
if(flag){
alert(12345678978979); //注意这部分,第一次执行动画的时候,是不会执行到这里的。因为flag一直是false
clearInterval(obj.timer);
if(fn){
fn();
}
}如果没有onmouseout的动画,那么,第二次鼠标移进去的时候,在执行动画之前,都满足
json[attr]=icur;
也就是说speed在第二次执行动画的时候,一直是0,那么这个时候,下面这个判定就没有执行了
if(icur != json[attr]){
flag = false;
}于是flag就是第二次执行动画的初始值,也就是:
var flag = true;
自然而然的,后面的这部分代码就能够执行了。
if(flag){
alert(12345678978979);//第二次执行onmouseover动画,就会执行到这里了
clearInterval(obj.timer);
if(fn){
fn();
}
}上面讲得比较啰嗦,不知道大家有没有看懂,没看懂的可以照着一步一步去尝试一下,会得到我说的这个结果的
首先我终于找到跟我一样认为flag是放在定时器外的人了,这一节课里面用的json[attr]不是target,json[attr]就相当于json.attr; 源码:
if(itur != json[attr] ){
flag=false;
}我资质较浅,我以个人名义说说我的想法,
var flag=true;这是放在计时器外的对吧,当遇到if(itur != json[attr] )语句的时候,就把flag这个全局变量设为false, 如果if(itur != json[attr] )不成立的时候,if( flag ){}这个语句就会找到全局变量,所以这就是为什么要放在计时器外
评论在一楼的那位大哥已经误导了大家,flag放在计时器内会出现bug.
你的问题我有点看不明白啊哥们,说的明白些
。。。。。好像看错问题,你忽略我的回答吧
当最后一个目标完成后,因为setInterval,会重新初始化flag为true