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)

大家都在看

  • 个人学习-STL:Set前置-tree

    参考资料: [1]程杰.大话数据结构[M]. [2][美]Robert Sedgewic,Jevin Wayne. 算法Algorithms[M].谢路云译 1.基本脉络: 树实际…

    Linux 2023年6月6日
    0102
  • OrchardCore Headless建站

    说到CMS系统,可能大家都能想起 WordPress和 Drupal之类的框架,作为.NET爱好者,一般也是知道一些基于.NET的CMS框架的,典型的比如 DNN、 Umbraco…

    Linux 2023年6月6日
    0104
  • 6.20(HTML和CSS–>练习案例)

    HTML脑图:how2j找的阶段性练习,话说VScode编辑器确实比DW好用,简洁免费(不是打广告哈哈) #0 <head> <meta charset=&quo…

    Linux 2023年6月7日
    0110
  • Docker部署

    部署Docker 1.部署docker相关 此章描述在新的服务器上安装docker容器。 1.1 概述 Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apach…

    Linux 2023年6月7日
    0144
  • Unit 1 Computer hardware【石家庄铁道大学-专业英语课 】

    Unit 1 Computer hardware 1、Introduction of computer A computer is a machine that can be in…

    Linux 2023年6月14日
    097
  • sftp配置

    有很多方法,可实现在网络上分享文件。其中之一为FTP协议。但FTP通过明文传输数据,不安全。幸运的是,SSH协议族中包含了用于传输文件的SFTP协议。 事实上,任何远程主机的用户,…

    Linux 2023年6月14日
    0112
  • Jenkins,8080端口无法修改问题

    今天安装了 Jenkins 。想把8080 端口修改为 6699 。 出现以下状况。 一:找到 jenkins.xml 文件。 vi /usr/lib/firewalld/serv…

    Linux 2023年6月13日
    086
  • Redis安装及HA(High Availability)配置

    Redis是一种内存数据库,以KEY-VALUE(即键值对)的形式存储数据。这篇文章主要介绍的是Redis安装及配置,所以不对Redis本身作详细介绍了。 下 载: 解 压: 以r…

    Linux 2023年5月28日
    082
  • 面试题:Java序列化与反序列化

    序列化和反序列化的概念 应用场景? 序列化实现的方式 继承Serializable接口,普通序列化 继承Externalizable接口,强制自定义序列化 serialVersio…

    Linux 2023年6月6日
    0122
  • SLF4J 日志门面

    SLF4J( Simple Logging Facade For Java),即 简单日志门面。主要是为了给 Java 日志访问提供一套标准、规范的 API 框架,其主要意义在于提…

    Linux 2023年6月8日
    095
  • 什么是虚拟计算机集群

    这个问题来自近期几位网友的私信,他们不约而同问到一个问题:什么是虚拟计算机集群?Laxcus分布式操作系统是如何做的?下面就正式回答一下这个问题。 在我们传统的认知里,或者大家平常…

    Linux 2023年6月6日
    0107
  • 订阅消息组件由 redis 改为 rabbitmq

    刚开始测试 dapr 时为了图省事,使用了 pubsub.redis,现在准备上生产环境,改用支持消息持久化的 pubsub.rabbitmq。 之前使用的 pubsub.redi…

    Linux 2023年5月28日
    084
  • 【Example】C++ STL 常用容器概述

    前排提醒: 由于 Microsoft Docs 全是机翻。所以本文表格是我人脑补翻+审校。 如果有纰漏、模糊及时反馈。 了解每一种容器的特性、知道什么情况下用什么容器就可以。 序列…

    Linux 2023年6月13日
    085
  • 什么是进程

    进程:是指计算机中已运行的程序。进程本身不是基本的运行单位,而是线程的容器。程序本身只是指令、数据及其组织形式的描述,进程才是程序(那些指令和数据)的真正运行实例。 进程是程序动态…

    Linux 2023年6月7日
    0110
  • 安装win10和ubuntu双系统

    2019-06-22 ​ 最近找了一份新的工作,要用到linux,由于之前基本上没有接触过这方面的东西,所以今天捣鼓一下,安装win10和linux双系统,办公研发双不误。如果在安…

    Linux 2023年6月14日
    0109
  • 玩转redis-简单消息队列

    使用 go语言基于 redis写了一个简单的消息队列源码地址使用demo redis的 list 非常的灵活,可以从左边或者右边添加元素,当然也以从任意一头读取数据 添加数据和获取…

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