上机三 JavaScript事件处理
目的:
- 熟练掌握JavaScript事件处理机制
- 重点理解面向对象编程思想,并构建程序。
要求:
- 定义一个按钮,动态生成DIV,可以生成多个DIV;
- 实现DIV的自由拖曳,当和以生成的DIV碰撞时,弹出警告框;
- 封装自由拖曳函数,DIV作为参数传入
源代码:
Third_work
截图:
总结(遇到问题、解决方式、心得体会):
div的生成和移动相对简单,但在我完成自由拖拽div、开始写判断div碰撞时,我发现了问题。
为了移动div,我将div的position属性都设置成了absolute,但也因此生成的div都聚集在浏览器窗口左上方互相重叠,虽然可以通过拖拽将其移动到其他位置,但如果碰撞功能部分代码完成,点击div开始移动时,就会触发碰撞,弹出警告框从而阻止了div的移动这无疑是个bug。所以若要实现碰撞功能,必须在生成div时就将每个div分隔开。
由于position:absolute绝对位置,通过设置div的外边距,即margin属性,将div分隔的操作失效。我想到可以在生成div时使用静态位置position:static,这样生成的div是会自动排成一竖列,并且可用margin属性。只要在触发拖拽移动时,将position属性修改回绝对位置ele.style.position = “absolute”;这样既实现了生成分隔开的div,又可拖拽移动div!
但是!经过测试,这种通过修改position属性的方法并不可行!在理论上这种方法确实完成了生成分隔开的div和自由拖拽div两种功能。但在实践中,由于受到拖拽的div的position会由静态static转变为绝对absolute,实现了空间自由拖拽移动,但其他div仍然是静态位置position:static,他们会自动排列并置顶。也就是说在拖拽div离开其原本位置时,其他div会自动移动、占据被拖拽的div的位置。在此过程中,div之间的碰撞不可避免,之前分隔div的操作毫无意义,他们依然还是会不受鼠标控制自行发生碰撞。所以不能通过修改绝对位置position:absolute来消除bug。
为了实现拖拽移动div,position:absolute是必须的。在绝对位置下,想要分隔开div就要使用left和top等属性来对div位置进行精准定位,并设置全局变量positionCountX和positionCountY来累计上一个div的位置,和预计生成下一个div的位置。这种靠精准定位div位置生成div的方法成功地解决了自动发生碰撞且强行阻止div移动的bug。
碰撞则是在移动的基础上进行加工,让鼠标事件触发的div与其他div用循环进行两两比较,不碰撞则移动,碰撞则弹出警告框。其中也有需要注意的事项,比如要给弹框上锁(关于上锁详情看代码,解释看实验2总结),避免div重合时不停弹框;还有得在弹出警告框前清除鼠标移动事件,因为alert弹框会发生中断,导致后面的鼠标抬起事件无效,这样div会在鼠标没有按下时也一直跟随着鼠标箭头;此外最好设置在div碰撞后自动移回div碰撞前位置,避免在div碰撞后重叠,这会导致点击事件触发弹框而不是拖拽div移动碰撞触发,并因为alert弹框中断div移动导致两个div在碰撞后出现无法分开的情况。
此外关于div是否发生碰撞判定的算法,我是觉得这很有趣的。div怎么判断是否与其他div发生碰撞呢?这实际上是两个问题,一个是div与其他div比较,数据是没有自己与他人这种概念的;另一个是怎么判断碰撞。关于第一个问题,是靠鼠标拖拽事件区分目标div与所有div,用循环将目标div与所有div的比较转换为两两比较,在比较前还要用if语句避免与自身比较,发生自己与自己碰撞的乌龙;关于第二个问题怎么判断碰撞,一般直接的算法是先判断两个div是否在同一高度范围,这需要这两个目标div的top和bottom进行多次比较,然后才是判断两个目标是否重叠,即这两个div的left和right进行比较。显然直接比较算法需要比较很多次,比较同一高度至少需要比较4次,在同一高度比较是否重叠也需要4次,而且这两种比较是分先后的,也就是所有情况是4*4,共16种情况。这种算法就显得直接比较麻烦,就需要重新构思比较策略。与其分析判断两个div碰撞的情况,不如分析判断两个div不碰撞的情况,这就将所有情况减少了许多,不产生碰撞只有4种情况,其他就算发生碰撞。
解决了以上问题,我个人认为在逻辑上,我的实验源代码已经尽善尽美,但意外还是发生了。在测试中,发生了移动两个div尚未碰撞,就弹出碰撞警告框的情况。经过反复测试并在浏览器控制台输出数据进行查看,我得出结论这并不是我算法设计的问题,而是浏览器显示与计算机计算处理速度不一致,计算机计算速度太快,数据发生了变化,但浏览器还来不及更新显示内容,就被alert弹框强行中断事件。所以要在alert语句外围设置setTimeout(),让计算等待1毫秒,等窗口更新变化。加上setTimeout()语句后,成功解决移动两个div尚未碰撞,就弹出碰撞警告框的问题。
这次实验让我深刻地意识到了重复不停思考的意义。就像research(研究)由re-前缀(表重复)和search(搜索)组成,实验研究就是要不停地探索、不停地测试、不停地思考。
Original: https://www.cnblogs.com/linlinmailbox/p/16063635.html
Author: 霖霖的信箱
Title: JavaScript事件处理(三)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/606632/
转载文章受原作者版权保护。转载请注明原作者出处!