昨天的计划中今天去实现项目中的播放列表单独与控制条自动隐藏,但又不想采用原来控制条的隐藏方式(原来是在隐藏的时候直接将visible设置为false),想做个渐变隐藏。于是就刷刷地加上N行代码。简单地说就是在播放列表的onMouseMove处理事件检测到鼠标在它的外边时就启动一个timer(时间间隔自己设置),当timer时间到了就新建一个Tween使播放列表渐渐隐藏。当检测到鼠标移动到播放列表的范围时就停止渐隐并将播放列表设置为完全显示(_vi)。
鼠标在外面静止一定的时间后播放列表隐藏,完全隐藏后鼠标移动到播放列表范围,播放列表又自动显示,很好,但是当播放正在隐藏中,也就是说Tween正在执行时我鼠标移动到播放列表范围时播放列表却出现闪烁几次后消失。然后我就花费了大概一个小时检测我写的代码逻辑,发现少了两个逻辑:第一鼠标移到播放列表范围时应该使Tween无效。第二当开始渐隐时不能新增新的Tween(说起来简单,但是As2的调试我都不想提了,太难了,你可以想一想在C++程序里只使用MessageBox来调试)。
问题二好解决,添加一个标志变量即可,问题一看起来也好解决,查看一下其它部分的代码,发现以前负责这个项目的经理使用了a = new Tween(……); delete a;这样的代码,那也我也照着用,但是问题又来了,现在闪烁的问题更严重了。费了老大功夫在代码里加了N个trace语句,发现即使delete掉了tween结果改变alpha值的函数还在跑。 我郁闷,又检查了所加代码的逻辑并且查看了相关代码的逻辑,还是没有发现问题,研究了数小时无结果,火大,打开MSN就想向经理求救。但是问题都敲好了,还是没有发出去。冷静下来想想,先另建个小程序,里面放个二个按钮和一个剪辑,按钮用来开始和停止那个剪辑渐隐。代码如下:
import mx.transitions.Tween import mx.transitions.easing.Strong; import mx.utils.Delegate; var _imageHideTween:Tween = undefined; //图像隐藏时使用的动画对象 start_btn.onPress = Delegate.create(this, OnStartHide); stop_btn.onPress = Delegate.create(this, OnStopHide); function OnStartHide(){ trace("Start"); _imageHideTween = new Tween(test_mc, "_alpha", mx.transitions.easing.Strong.easeOut, 100, 0, 5, true); } function OnStopHide(){ trace("Stop"); //_imageHideTween.stop(); delete _imageHideTween; trace(_imageHideTween); }
发现在这里也是不能正常停止渐隐,然后想一想分别查了delete和Tween类的帮助,发现Tween里还有个stop方法用来停止Tween,就将上面代码OnStopHide中注释的那一句添上了,然后,这个实现代码就正常了。然后带着疑问去查看了Tween的源码,发现它的实现模式也是相当简单,也是启动了个定时器,定时调用一个回调函数,并且在回调里调用构造Tween时指定的用来计算新值的函数,然后对调用构造Tween时指定的对象的指定参数进行更改。在Tween类里没有显示析构函数,也就是没有在delete这个Tween时对定时器进行关闭,所以delete 这个Tween后效果依然是继续的,但是这个对象已经析构了为什么里面的回调函数还能正常执行就说不清楚了,谁让As2是个脚本语言呢。
解决了这个问题,下面的就简单了,修改一下播放列表鼠标检测策略和优化一下流程,新的功能就做好了。
但是回想一下,一个简单的函数使我足足浪费了大半天的时间来检查自己的代码,并且是如何也检测不出来问题,道理是如此简单,检查时总会放过那些自认为绝对正确的部分,那么如论如何也是检测不出错误的。似乎有句话是:“最可怕的不是无知,而是你不知道自己无知”。