JavaScript事件处理(三)

上机三 JavaScript事件处理

目的:

  1. 熟练掌握JavaScript事件处理机制
  2. 重点理解面向对象编程思想,并构建程序。

要求:

  1. 定义一个按钮,动态生成DIV,可以生成多个DIV;
  2. 实现DIV的自由拖曳,当和以生成的DIV碰撞时,弹出警告框;
  3. 封装自由拖曳函数,DIV作为参数传入

源代码:



    
    
    
    Third_work







截图:

JavaScript事件处理(三)

总结(遇到问题、解决方式、心得体会):

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/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 分区表、文件系统等计算机基础知识

    开机固件 BIOS UEFI 特别老的BIOS不支持GPT分区 目前已取代BIOS 分区表类型 MBR GPT 1.不支持2TB以上的硬盘2.主分区不能超过4个3.可以通过建立扩展…

    Linux 2023年6月7日
    089
  • Shell Step by Step (4) —— Cron & Echo

    6.脚本定时任务 <span class="hljs-preprocessor"># Example of job definition:</…

    Linux 2023年5月28日
    0114
  • 十二、启动流程

    启动流程介绍 现代计算机系统启动是硬件与软件复杂组合。从定义的端点开始,到拥有登录提示符的运行中系统,需要大量的硬件和软件配合工作。以下列表从较高层面概述了启动系统时所涉及的任务。…

    Linux 2023年6月7日
    092
  • POJ1475(Pushing Boxes)–bbffss

    假设只有一个箱子。游戏在一个R行C列的由单位格子组成的区域中进行,每一步, 你可以移动到相邻的四个格子中的一个,前提是那个格子是空的;或者,如果你在箱子旁边,你也可以推动箱子前进一…

    Linux 2023年6月7日
    099
  • centos8 redis安装

    redis的优势我就不多说了(其实我也就是跟着主流) 既然想试试redis,那么就从linux下安装redis开始。那么windows下可以安装redis吗? 答案是肯定的,但是官…

    Linux 2023年5月28日
    0104
  • 017 Linux 之啥是 ssh ?

    1 什么是 ssh?有什么用? (1)ssh 是一种协议 (2)ssh 服务 2 ssh 基于密匙的安全验证过程是怎样的? 3 对称加密与非对称加密区别是什么? (1)对称加密 (…

    Linux 2023年5月27日
    0107
  • Java高级

    抽象类和抽象方法 1.定义 随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。 类的设计应该保证父类和子类都能够共享特征。 有时候将一个父类设计的非常抽象…

    Linux 2023年6月13日
    0103
  • Linux安装管理

    Linux系列 包管理工具 单个软件包 管理工具 RedHat系列 Redhat Centos Fedora yum rpm .rpm Debian系列 Ubuntu apt-ge…

    Linux 2023年6月8日
    085
  • 搭配色轮播(CSS进阶版本)

    html;gutter:true; Color</p> <pre><code> /* 自定义颜色 */ /* :root { */ /* –t…

    Linux 2023年6月13日
    071
  • iptables快速入门

    iptables简介 在生产实践过程中,为了保证生产安全,通常需要进行数据加密,例如通过网络层面上将应用隔离成内网和公网应用,内网再分成生产、测试、开发、DMZ等区域,然后进行不同…

    Linux 2023年6月6日
    086
  • 启动springboot项目很慢的解决方案-InetAddress.getLocalHost().getHostName()

    https://blog.csdn.net/qq_39595769/article/details/119573111 Original: https://www.cnblogs….

    Linux 2023年6月13日
    084
  • 简单易用的任务队列-beanstalkd

    概述 beanstalkd 是一个简单快速的分布式工作队列系统,协议基于 ASCII 编码运行在 TCP 上。其最初设计的目的是通过后台异步执行耗时任务的方式降低高容量 Web 应…

    Linux 2023年6月7日
    094
  • 07-MyBatis中的动态标签

    MyBatis中的动态标签 1、if标签 if标签是为了判断传入的值是否符合某种条件,比如是否不为空 2、where标签 where标签可以用来做动态拼接查询条件,当和 if标签配…

    Linux 2023年6月7日
    087
  • DDoS攻击–TCP攻击概述

    https://blog.csdn.net/qq_34777600/article/details/81945594 posted @2020-12-10 18:07 珠峰之梦 阅…

    Linux 2023年6月7日
    093
  • Java — 注解

    Java 注解(Annotation)又称为 Java 标注,是 Java5 开始支持加入源代码的特殊语法元数据。 Java 语言中的类、方法、变量、参数和包等都可以被标注。 Ja…

    Linux 2023年6月8日
    089
  • CentOS 用户与群组

    Linux 系统中存在一个超级用户 root ,可以做任何操作。Linux 系统中每个用户都有自己独立的账户,有些命令运行需要切换 root 身份,用户是分组的。 1.1、切换用户…

    Linux 2023年6月8日
    077
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球