JavaScript的运动原理1

运动基础

  1. 在JavaScript中,如何让一个页面元素动起来?
    首先,我们需要了解的是,在JavaScript中如何让一个页面元素动起来。

我们先来实现一个简单的功能,当我们点击按钮之后,让一个元素动起来。并且到达500的边界之后立刻停止下来。

<!DOCTYPE html>
<html>
    <head> <meta charset="utf-8"> <title></title> <style> #d1 { width: 100px; height: 100px; background-color: red; position: absolute; top:100px; left: 200px; } </style> </head> <body> <button id="btn">点击运动</button> <div id="d1"></div> </body> <script> // 点击按钮,让div横向的运动起来 // 1. 获取元素 let oBtn = document.getElementById('btn'); let oDiv = document.getElementById('d1'); let iTimer = null; // 点击按钮,让元素一直运动 ,需要使用到的知识点:定时器 oBtn.onclick = ()=>{ iTimer = setInterval(()=>{ // 点击按钮之后,让div的位置在当前的基础之上每次增加10px的距离 // oDiv.style.left = oDiv.offsetLeft + 10 + 'px'; // 虽然此代码可以让div动起来,但是我们需要div在运动之后到达某个边界就立刻停止,所以需要将此句代码改为一个判断 if (oDiv.offsetLeft === 500) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDiv.style.left = oDiv.offsetLeft + 10 + 'px'; } },30); }; </script> </html> 

在上面的代码中,我们点击按钮之后,元素已经可以直接进行移动,但是却存在一个问题,什么问题呢?

当我们点击按钮之后,元素始终以10px的匀速进行运动,到达500的临界然后停止。 但是我们的问题是,速度可能会变,例如将速度变为7px,就不能够
准确的到达500的临界值。

例如:

<!DOCTYPE html>
<html>
    <head> <meta charset="utf-8"> <title></title> <style> #d1 { width: 100px; height: 100px; background-color: red; position: absolute; top:100px; left: 200px; } </style> </head> <body> <button id="btn">点击运动</button> <div id="d1"></div> </body> <script> // 点击按钮,让div横向的运动起来 // 1. 获取元素 let oBtn = document.getElementById('btn'); let oDiv = document.getElementById('d1'); let iTimer = null; // 点击按钮,让元素一直运动 ,需要使用到的知识点:定时器 oBtn.onclick = ()=>{ iTimer = setInterval(()=>{ // 点击按钮之后,让div的位置在当前的基础之上每次增加10px的距离 // oDiv.style.left = oDiv.offsetLeft + 10 + 'px'; // 虽然此代码可以让div动起来,但是我们需要div在运动之后到达某个边界就立刻停止,所以需要将此句代码改为一个判断 if (oDiv.offsetLeft === 500) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDiv.style.left = oDiv.offsetLeft + 7 + 'px'; // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动 } },30); }; </script> </html> 

出现这种情况的原因是因为运动的临界值必须能够被运动的速度(也就是oDiv.offsetLeft + 7 + 'px',表示每次执行移动的距离)整除。

上面的代码当中, 因为临界值不能够被速度整除,所以,最终元素始终达到不了临界值,那么元素就没有办法在到达临界值时停止。

同时在上面的代码中的另外一个问题是,当我们每点击一次运动按钮,元素的速度就会变得更快,原因很简单,就是我们设置的定时器发生了累加。

那么该如何解决定时器累加的问题呢?

我们可以在每次开始运动之前先清楚一次定时器。

oBtn.onclick = ()=>{
            /*
            * 为了防止定时器累加,在每次开始定时器之前,先清楚掉一个定时器  
            * */
            clearInterval(iTimer);
            
            iTimer = setInterval(()=>{ // 点击按钮之后,让div的位置在当前的基础之上每次增加10px的距离 // oDiv.style.left = oDiv.offsetLeft + 10 + 'px'; // 虽然此代码可以让div动起来,但是我们需要div在运动之后到达某个边界就立刻停止,所以需要将此句代码改为一个判断 if (oDiv.offsetLeft === 500) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDiv.style.left = oDiv.offsetLeft + 7 + 'px'; // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动 } },30); };

总结:在上面的代码中,是我们一般让一个元素运动起来的基本流程。下面进行一个简单的总结:

  1. 首先是存在的问题:处于匀速运动的元素没有办法进行在不整除的情况下在临界点停止。
  2. 在上面的代码中,可以将整个过程大致分为三个步骤:
    • 清除定时器,保证只有一个定时器在执行
    • 开启定时器
    • 开始运动(需要同时加入一个判断,以便在需要的时候或者满足某个要求时停止运动)

简单运动的封装

为了让我们上面的代码可以具备更高的复用性,下面我们把上面的代码进行一个简单的封装。

扫描二维码关注公众号,回复: 7233919 查看本文章

示例:

<!DOCTYPE html>
<html>
    <head> <meta charset="utf-8"> <title></title> <style> #d1 { width: 100px; height: 100px; background-color: red; position: absolute; top:100px; left: 200px; } </style> </head> <body> <button id="btn">点击运动</button> <div id="d1"></div> </body> <script> // 点击按钮,让div横向的运动起来 // 1. 获取元素 let oBtn = document.getElementById('btn'); let oDiv = document.getElementById('d1'); let iTimer = null; // 点击按钮,让元素一直运动 ,需要使用到的知识点:定时器 oBtn.onclick = ()=>{ startMove(); // 将运动相关的内容全部放到startMove这个函数中,然后调用既可以让元素进行运动 function startMove() { clearInterval(iTimer); iTimer = setInterval(()=>{ if (oDiv.offsetLeft === 500) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDiv.style.left = oDiv.offsetLeft + 10 + 'px'; // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动 } },30); } }; </script> </html> 

在上面的代码中,我们将运动相关的内容放到了一个函数startMove中,并且调用了这个函数,下面来根据这个函数进行案例的开发。

案例1:分享到功能

首先,先来实现基本的功能:

<!DOCTYPE html>
<html>
    <head> <meta charset="utf-8"> <title></title> <style> #div1 { width: 100px; height: 200px; background:red; position: absolute; left: -100px; top: 200px; } #div2 { width: 30px; height: 70px; background: black; position:absolute; right:-30px; top: 70px;; color:#fff; text-align: center; } </style> </head> <body> <div id="div1"> <div id="div2">分享到</div> </div> </body> <script> // 1. 首先获取两个元素 let oDiv1 = document.getElementById('div1'); let oDiv2 = document.getElementById('div2'); let iTimer = null; // 给为父级的div绑定mouseover 和 mouseout事件 oDiv1.onmouseover = function() { this.style.left = 0 + 'px'; // 鼠标移入,让div元素出现 }; oDiv1.onmouseout = function() { this.style.left = -100 + 'px'; // 鼠标移出,让div隐藏 }; </script> </html> 

上面的代码中,我们鼠标移入,元素出现。鼠标移出,元素消失。
下面我们来使用我们的startMove函数,给元素出现和消失加上一个过渡的效果。

我们的startMove函数如下:

function startMove() {
    clearInterval(iTimer);
    iTimer = setInterval(()=>{ if (oDiv.offsetLeft === 500) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDiv.style.left = oDiv.offsetLeft + 10 + 'px'; // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动 } },30); }

我们想要在分享到功能里使用这个函数,我们需要对我们的函数根据分享到的需求进行一定程度的更改。
首先是,将我们函数中的oDvi更改为oDiv1

其次是我们分享到案例的需求在鼠标移入时需要将元素逐渐的显示,而鼠标移出时,需要将元素逐渐的隐藏。所以我们需要将startMove函数创建两个
,并且当鼠标移出时,速度应该将函数中的+10变为-10

当然,也别忘了去更该元素边界的值。当移出时,边界为0,移入时,边界为-100.

如下:

鼠标移入时调用的startMove1函数:

function startMove1() {
    clearInterval(iTimer);
    iTimer = setInterval(()=>{ if (oDiv1.offsetLeft === 0) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDiv1.style.left = oDiv.offsetLeft + 10 + 'px'; // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动 } },30); }

鼠标移出时调用的startMove2函数:

function startMove() {
    clearInterval(iTimer);
    iTimer = setInterval(()=>{ if (oDiv1.offsetLeft === -100) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDiv1.style.left = oDiv.offsetLeft - 10 + 'px'; // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动 } },30); }

我们先来将这两个函数放在代码中,进行测试。

<!DOCTYPE html>
<html>
    <head> <meta charset="utf-8"> <title></title> <style> #div1 { width: 100px; height: 200px; background:red; position: absolute; left: -100px; top: 200px; } #div2 { width: 30px; height: 70px; background: black; position:absolute; right:-30px; top: 70px;; color:#fff; text-align: center; } </style> </head> <body> <div id="div1"> <div id="div2">分享到</div> </div> </body> <script> // 1. 首先获取两个元素 let oDiv1 = document.getElementById('div1'); let oDiv2 = document.getElementById('div2'); let iTimer = null; // 给为父级的div绑定mouseover 和 mouseout事件 oDiv1.onmouseover = function() { // this.style.left = 0 + 'px'; // 鼠标移入,让div元素出现 startMove1(); }; oDiv1.onmouseout = function() { // this.style.left = -100 + 'px'; // 鼠标移出,让div隐藏 startMove2(); }; function startMove1() { clearInterval(iTimer); iTimer = setInterval(()=>{ if (oDiv1.offsetLeft === 0) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDiv1.style.left = oDiv1.offsetLeft + 10 + 'px'; // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动 } },30); } function startMove2() { clearInterval(iTimer); iTimer = setInterval(()=>{ if (oDiv1.offsetLeft === -100) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDiv1.style.left = oDiv1.offsetLeft - 10 + 'px'; // 一旦将每次的移动距离变为7px ,那么将不能停的下来.元素会一直运动 } },30); } </script> </html> 

上面的代码中,我们通过创建两个startMove函数,并且对相应的参数进行修改,从而实现了给我们的分享到功能添加了过渡效果。

进一步升级:
当然,我们上面的代码中使用的函数其实是非常不灵活的,所以我们下面要做到事就是对之前的函数进行升级,从而让我们的函数具备更强的实用性。

首先我们再回过头来看下我们刚才写的两个函数,你会发现,大部分的代码其实都是相同的,只有个别的值是不同的,例如元素移动的边界,例如元素
单位时间内移动的距离。

我们将上面的两个函数合并成一个函数,只需要将不一样的值提取出来当做参数即可。

下面是合并之后的函数:

function startMove(iTarget,iSpeed) {
    clearInterval(iTimer);
    iTimer = setInterval(()=>{ if (oDiv1.offsetLeft === iTarget) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDiv1.style.left = oDiv1.offsetLeft + iSpeed + 'px'; } },30); }

上面的函数升级完成之后,我们在重新的将这个函数应用到我们的分享到功能的代码当中去。

<!DOCTYPE html>
<html>
    <head> <meta charset="utf-8"> <title></title> <style> #div1 { width: 100px; height: 200px; background:red; position: absolute; left: -100px; top: 200px; } #div2 { width: 30px; height: 70px; background: black; position:absolute; right:-30px; top: 70px;; color:#fff; text-align: center; } </style> </head> <body> <div id="div1"> <div id="div2">分享到</div> </div> </body> <script> // 1. 首先获取两个元素 let oDiv1 = document.getElementById('div1'); let oDiv2 = document.getElementById('div2'); let iTimer = null; // 给为父级的div绑定mouseover 和 mouseout事件 oDiv1.onmouseover = function() { // this.style.left = 0 + 'px'; // 鼠标移入,让div元素出现 startMove(0,10); }; oDiv1.onmouseout = function() { // this.style.left = -100 + 'px'; // 鼠标移出,让div隐藏 startMove(-100,-10); }; function startMove(iTarget,iSpeed) { clearInterval(iTimer); iTimer = setInterval(()=>{ if (oDiv1.offsetLeft === iTarget) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDiv1.style.left = oDiv1.offsetLeft + iSpeed + 'px'; } },30); } </script> </html>

上面的代码中,我们顺利的通过我们的startMove函数给分享到功能添加了过渡的效果。

图片的淡入淡出效果:

下面我们再来看另外的一个效果,图片的淡入淡出,还是通过我们上面定义好的startMove函数来实现效果。

首先,我们上面的函数当中,只是针对oDiv1,为了让我们的函数可以处理任意的元素,我们将oDiv1替换成函数的形参。

例如:

function startMove(oDom,iTarget,iSpeed) {
    clearInterval(iTimer);
    iTimer = setInterval(()=>{ if (oDom.offsetLeft === iTarget) { // 清除定时器 clearInterval(iTimer); }else { // 没有到达边界才能继续运动 oDom.style.left = oDom.offsetLeft + iSpeed + 'px'; } },30); }

上面的代码当中,我们将函数操作的元素提取出来,变成了函数的形参,这样做之后,我们就可以让我们的函数针对任意的元素。

猜你喜欢

转载自www.cnblogs.com/jhflyfish/p/11488850.html