ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

js 运动函数篇(三) (加速度运动、弹性运动、重力场运动(多方向+碰撞检测+重力加速度+能量损失运动)拖拽运动)层层深入

2020-05-02 11:00:26  阅读:259  来源: 互联网

标签:style var 碰撞检测 newTop 加速度 运动 document event newLeft


前言:

        本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽。

        本篇文章为您分析一下 原生JS写拖拽运动

        层层深入,到封装插件,请先查阅js 运动函数篇(二)


建议:


如果您是直接查看的本篇博文

请您先翻阅我上一篇关于JS运动的 【js运动函数篇(二)】 里面有详细的关于加速度运动、弹性运动、重力场运动(多方向+碰撞检测+重力加速度+能量损失运动)的解析。

- js运动函数篇(二)链接:  https://www.cnblogs.com/qq4297751/p/12812996.html

最好是能把【js运动函数篇(一)】也查看一遍,当然您不看js运动函数篇一 只看js运动函数篇二对您影响看本篇的博文影响也不大

- js运动函数篇(一)链接:  https://www.cnblogs.com/qq4297751/p/12790676.html


HTML结构


<div id="demo"></div>

CSS样式


        #demo {
            position: absolute;
            left: 0;
            top: 0;
            background-color: red;
            width: 100px;
            height: 100px;
            border-radius: 50%;
        }


页面效果如下

JS行为

JS分析
 - 我们想要鼠标按下移动小球时,再抬起鼠标,他会顺着你移动的方向滚动

 - 主要是在js运动函数篇(二)中重力场运动中改变iSpeedX和iSpeedY中的两个速度方向

 - 因此函数还是那个startMove函数,只是我们现在需要给他传入两个方向的速度值(iSpeedX,iSpeedY),而不是直接写死

function startMove(dom) {
            clearInterval(dom.timer);
            // 第一步: 定义横向运动速度
            // var iSpeedX = 6;
            // 1.1 定义纵向运动速度
            // var iSpeedY = 8;
            // 第五步: 定义一个重力加速度
            var g = 3;
            // 第六步: 定义一个损耗
            var u = 0.8;
            // 开启定时器
            dom.timer = setInterval(function () {
                // 第五步: 5.1 纵向速度每次加当前的重力
                iSpeedY += g;
                // 第二步: 新newLeft的位置 = 物体offsetLeft的当前位置 + 横向速度
                var newLeft = dom.offsetLeft + iSpeedX;
                // 2.1 新newLeft的位置 = 物体offsetLeft的当前位置 + 横向速度
                var newTop = dom.offsetTop + iSpeedY;
                // 第四步: 判断边界
                // 如果当前的 newTop值 >= 浏览器窗口 - 当前元素的高度 (触碰到界面边框)
                if (newTop >= document.documentElement.clientHeight - dom.clientHeight) {
                    // 4.1 方向要改变
                    iSpeedY *= -1;
                    // 第七步: 每次碰撞都会受到能量的损耗   不管横向纵向都会受到能量损耗
                    iSpeedY *= u;
                    iSpeedX *= u;
                    // 4.2 设置当前的newTop值      如果不设置,它会超出一些边界
                    newTop = document.documentElement.clientHeight - dom.clientHeight;
                }
                if (newTop <= 0) {
                    // 4.3 方向要改变
                    iSpeedY *= -1;
                    // 第七步: 每次碰撞都会受到能量的损耗   不管横向纵向都会受到能量损耗
                    iSpeedY *= u;
                    iSpeedX *= u;
                    // 4.4 设置当前的newTop值      如果不设置,它会超出一些边界
                    newTop = 0;
                }
                // 4.5 如果当前的 newTop值 >= 浏览器窗口 - 当前元素的宽度 (触碰到界面边框)
                if (newLeft >= document.documentElement.clientWidth - dom.clientWidth) {
                    // 4.6 方向要改变
                    iSpeedX *= -1;
                    // 第七步: 每次碰撞都会受到能量的损耗   不管横向纵向都会受到能量损耗
                    iSpeedY *= u;
                    iSpeedX *= u;
                    // 4.7 设置当前的newLeft值      如果不设置,它会超出一些边界
                    newLeft = document.documentElement.clientWidth - dom.clientWidth;
                }
                if (newLeft <= 0) {
                    // 4.8 方向要改变
                    iSpeedX *= -1;
                    // 第七步: 每次碰撞都会受到能量的损耗   不管横向纵向都会受到能量损耗
                    iSpeedY *= u;
                    iSpeedX *= u;
                    // 4.9 设置当前的newLeft值      如果不设置,它会超出一些边界
                    newLeft = 0;
                }
                // 第三步: 设置当前的位置
                console.log(iSpeedX, iSpeedY);
                dom.style.left = newLeft + 'px';
                dom.style.top = newTop + 'px';
            }, 30);
        }


下面为它注册事件

大致原理

1.鼠标按下事获取当前鼠标位置

2.鼠标移动时获取当前元素距离浏览器窗口左边和上边的距离

3.鼠标抬起时,将获取到的元素位置传入startMove函数中


        var oDiv = document.getElementById('demo');
        // 新第一步: 定义初始iSpeedX值
        var iSpeedX = 0;
        // 新第一步: 定义初始iSpeedY值
        var iSpeedY = 0;
        // 新第二步: 注册鼠标按下事件,传入事件参数e
        oDiv.onmousedown = function (e) {
            var event = event || e;
            // clientX 事件属性返回当事件被触发时鼠标指针向对于浏览器页面(或客户区)的水平坐标。alert("X 坐标: " + x + ", Y 坐标: " + y)
            // offsetLeft 总结一下: 就是子盒子到定位的父盒子边框到边框的距离
            // 新第四步: 事件兼容获取当前元素位置
            // disX就是你鼠标当前点击元素的位置到你这个元素左边边的位置
            var disX = event.clientX - this.offsetLeft;
            // disY就是你鼠标当前点击元素的位置到你这个元素上边边的位置
            var disY = event.clientY - this.offsetTop;
            // 新第十步: 10.1 保存当前的this
            var self = this;
            // 新第五步: 注册鼠标移动事件  传入事件参数e
            document.onmousemove = function (e) {
                // 新第五步: 事件兼容
                var event = event || e;
                // 新第六步: 最新的newLeft距离 = 当前元素距离浏览器左边框的距离
                var newLeft = event.clientX - disX;
                // 新第六步: 最新的newTop距离 = 当前元素距离浏览器上边框的距离
                var newTop = event.clientY - disY;
                // 新第七步: 设置最新的left值
                self.style.left = newLeft + 'px';
                // 新第七步: 设置最新的top值
                self.style.top = newTop + 'px';
            }

            // 新第八步: 注册鼠标抬起事件  
            document.onmouseup = function () {
                // 新第九步: 移动事件设为null
                document.onmousemove = null;
                // 新第九步: 抬起事件设为null
                document.onmouseup = null;
                // 新第十步: 鼠标抬起之后传入参数
                startMove(self, iSpeedX, iSpeedY);
            }
        }


页面效果如下


接下来就是最关键一点
如何获取鼠标抬起时的点
为了看清楚小球移动的轨迹,下面在小球移动时模拟一个小球的运动轨迹
在小球移动事件中添加下面的代码
为了能更清楚看清小球的运动轨迹,我们可以把小球暂时设置为正方形

            // 第十一步
            document.onmousemove = function (e) {
                // 新第五步: 事件兼容
                var event = event || e;
                // 新第六步: 最新的newLeft距离 = 当前元素距离浏览器左边框的距离
                var newLeft = event.clientX - disX;
                // 新第六步: 最新的newTop距离 = 当前元素距离浏览器上边框的距离
                var newTop = event.clientY - disY;
                iSpeedX = newLeft - lastX;
                iSpeedY = newTop - lastY;
                lastX = newLeft;
                lastY = newTop;
                // 第十一步 开始: 模拟实现小球运动的轨迹
                var oSpan = document.createElement('span');
                oSpan.style.position = 'absolute';
                oSpan.style.left = newLeft + 'px';
                oSpan.style.top = newTop + 'px';
                oSpan.style.width = '5px';
                oSpan.style.height = '5px';
                oSpan.style.backgroundColor = 'black';
                oSpan.style.borderRadius = '50%';
                document.body.appendChild(oSpan);
                // 第十一步 结束: 模拟实现小球运动的轨迹
                // 新第七步: 设置最新的left值
                self.style.left = newLeft + 'px';
                // 新第七步: 设置最新的top值
                self.style.top = newTop + 'px';
            }


页面效果如下


因为我们时时刻刻要记录最新的 newLeft 和 newTop
所以我们也要时刻记录一下上一个点的位置
先来看看分析图


下面进行代码编写

        // 新第十二步  到  新第十四步
        var oDiv = document.getElementById('demo');
        // 新第十二步: 记录上一个点的位置,默认是0; (跟你初始的定位left值一样)
        var lastX = 0;
        // 新第十二步: 记录上一个点的位置,默认是0; (跟你初始的定位top值一样)
        var lastY = 0;
        // 新第一步: 定义初始iSpeedX值
        var iSpeedX = 0;
        // 新第一步: 定义初始iSpeedY值
        var iSpeedY = 0;
        // 新第二步: 注册鼠标按下事件,传入事件参数e
        oDiv.onmousedown = function (e) {
            clearInterval(this.timer);
            // 新第三步: 事件兼容
            var event = event || e;
            // clientX 事件属性返回当事件被触发时鼠标指针向对于浏览器页面(或客户区)的水平坐标。alert("X 坐标: " + x + ", Y 坐标: " + y)
            // offsetLeft 总结一下: 就是子盒子到定位的父盒子边框到边框的距离
            // 新第四步: 事件兼容获取当前元素位置
            // disX就是你鼠标当前点击元素的位置到你这个元素左边边的位置
            var disX = event.clientX - this.offsetLeft;
            // disY就是你鼠标当前点击元素的位置到你这个元素上边边的位置
            var disY = event.clientY - this.offsetTop;
            var self = this;
            // clientX 事件属性返回当事件被触发时鼠标指针向对于浏览器页面(或客户区)的水平坐标。alert("X 坐标: " + x + ", Y 坐标: " + y)
            // console.log(event.clientX, event.clientY);
            // offsetLeft 总结一下: 就是子盒子到定位的父盒子边框到边框的距离
            // console.log(this.offsetLeft, this.offsetTop);
            // console.log(disX, disY);
            // 新第五步: 注册鼠标移动事件  传入事件参数e
            document.onmousemove = function (e) {
                // 新第五步: 事件兼容
                var event = event || e;
                // 新第六步: 最新的newLeft距离 = 当前元素距离浏览器左边框的距离
                var newLeft = event.clientX - disX;
                // 新第六步: 最新的newTop距离 = 当前元素距离浏览器上边框的距离
                var newTop = event.clientY - disY;
                // 新第十三步: 获取当前的横向速度
                iSpeedX = newLeft - lastX;
                // 新第十三步: 获取当前的纵向速度
                iSpeedY = newTop - lastY;
                // 新第十四步: 保存上一个点(更新一下,并不一定会用到)
                lastX = newLeft;
                // 新第十四步: 保存上一个点(更新一下,并不一定会用到)
                lastY = newTop;
                // 第十一步 开始: 模拟实现小球运动的轨迹
                var oSpan = document.createElement('span');
                oSpan.style.position = 'absolute';
                oSpan.style.left = newLeft + 'px';
                oSpan.style.top = newTop + 'px';
                oSpan.style.width = '5px';
                oSpan.style.height = '5px';
                oSpan.style.backgroundColor = 'black';
                oSpan.style.borderRadius = '50%';
                document.body.appendChild(oSpan);
                // 第十一步 结束: 模拟实现小球运动的轨迹
                // 新第七步: 设置最新的left值
                self.style.left = newLeft + 'px';
                // 新第七步: 设置最新的top值
                self.style.top = newTop + 'px';
            }


            document.onmouseup = function () {
                document.onmousemove = null;
                document.onmouseup = null;
                startMove(self, iSpeedX, iSpeedY);
                console.log(self)
            }
        }



页面效果如下


但是当我们在他运动的过程中再次点击他时,会发现有两股力量驱动它的运动
BUG缠身


直接在onmousedown事件里添加clearInter(this.timer)
BUG缠身

结语

整完!!!

标签:style,var,碰撞检测,newTop,加速度,运动,document,event,newLeft
来源: https://www.cnblogs.com/qq4297751/p/12814248.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有