ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript のリバウンド アニメーション効果はどのように実装されますか?

JavaScript のリバウンド アニメーション効果はどのように実装されますか?

零下一度
零下一度オリジナル
2017-07-16 15:25:181178ブラウズ

JavaScriptリバウンドアニメーション効果を実現するにはどうすればよいですか?コードを通して詳しく紹介していきます。

コードは次のとおりです:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    #box{
      width:200px;
      height:200px;
      position: absolute;
      top:0;
      left:200px;
      background:lightblue;
    }
    .btn{
      position:absolute;
      top:200px;
      left:100px;
      height:50px;
    }
    .btn input{
      display:inline-block;
      margin-left:50px;
      outline: none;
      width:100px;
      height:50px;
      border:1px solid green;
      cursor:pointer;
    }
  </style>
</head>
<body>
  <p id=&#39;box&#39;></p>
  <p class=&#39;btn&#39;>
    <input type="button" value=&#39;向左&#39; id=&#39;btnLeft&#39;>
    <input type="button" value=&#39;向右&#39; id=&#39;btnRight&#39;>
  </p>
  <script>
    var oBox = document.getElementById("box");
    var minLeft = 0;
    var maxLeft = utils.win(&#39;clientWidth&#39;)-oBox.offsetWidth;
    var step = 5;
    var timer = null;
    function move(target){
      //target:告诉我要运动的目标位置
      window.clearTimeout(timer);
      var curLeft = utils.css(oBox,"left");
      if(curLeft<target){//向右走
        if(curLeft+step>target){//边界
          utils.css(oBox,"left",target);
          return;
        }
        curLeft+=step;
        utils.css(oBox,"left",curLeft)
      }else if(curLeft>target){//向左走
        if(curLeft-step<target){//边界
          utils.css(oBox,"left",target);
          return;
        }
        curLeft-=step;
        utils.css(oBox,"left",curLeft)
      }else{//不需要运动
        return;
      }
      // timer = window.setTimeout(move,10)//这里有一个问题,点击按钮第一次target的值是有的,但是第二次通过setTimeout执行的时候没有给target进行传值。是undefined
      timer = window.setTimeout(function(){
        move(target);
      },10)//这样使用匿名函数包裹一下,就解决了上面的问题,但是这样写性能不好,因为每一次到达时间的时候,都需要执行一次匿名函数(形成一个私有的作用域),在匿名函数中再执行move,但是move中需要用到的数据值在第一次执行的move方法中,需要把匿名函数形成的这个私有的作用域作为跳板找到之前的,这样就导致了匿名函数形成的这个私有的作用域不能销毁
    }
    document.getElementById(&#39;btnLeft&#39;).onclick = function(){
      move(minLeft)
    }
    document.getElementById(&#39;btnRight&#39;).onclick = function(){
      move(maxLeft)
    }
  </script>
</body>
</html>

上記のパフォーマンス低下の問題を解決するために、以下は最適化されたコードです: 関数ラッパーがその中で使用されているため、move 関数によって作成されたプライベート スコープのみが非公開になります。 _move が実行されるまで破棄されます。完了すると、移動は自然に破棄されます。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    #box{
      width:200px;
      height:200px;
      position: absolute;
      top:0;
      left:200px;
      background:lightblue;
    }
    .btn{
      position:absolute;
      top:200px;
      left:100px;
      height:50px;
    }
    .btn input{
      display:inline-block;
      margin-left:50px;
      outline: none;
      width:100px;
      height:50px;
      border:1px solid green;
      cursor:pointer;
    }
  </style>
</head>
<body>
  <p id=&#39;box&#39;></p>
  <p class=&#39;btn&#39;>
    <input type="button" value=&#39;向左&#39; id=&#39;btnLeft&#39;>
    <input type="button" value=&#39;向右&#39; id=&#39;btnRight&#39;>
  </p>
  <script>
    var oBox = document.getElementById("box");
    var minLeft = 0;
    var maxLeft = utils.win(&#39;clientWidth&#39;)-oBox.offsetWidth;
    var step = 5;
    var timer = null;
    function move(target){
      //target:告诉我要运动的目标位置
      _move();
      function _move(){
        window.clearTimeout(timer);
        var curLeft = utils.css(oBox,"left");
        if(curLeft<target){//向右走
          if(curLeft+step>target){//边界
            utils.css(oBox,"left",target);
            return;
          }
          curLeft+=step;
          utils.css(oBox,"left",curLeft)
        }else if(curLeft>target){//向左走
          if(curLeft-step<target){//边界
            utils.css(oBox,"left",target);
            return;
          }
          curLeft-=step;
          utils.css(oBox,"left",curLeft)
        }else{//不需要运动
          return;
        }
        timer = window.setTimeout(_move,10);
      }
    }
    document.getElementById(&#39;btnLeft&#39;).onclick = function(){
      move(minLeft)
    }
    document.getElementById(&#39;btnRight&#39;).onclick = function(){
      move(maxLeft)
    }
  </script>
</body>
</html>

注: 現在の要素で同時に 1 つのアニメーションのみを実行するようにするには (次のアニメーションが開始するときに、最初に前のアニメーションの タイマー をクリアします): 現在の要素のすべてのアニメーションがタイマーの戻り値を受け取るようにしてください。 value 変数を共有する必要があります。方法は 2 つあります: 1. グローバル受信 (たとえば、上記のコード var timer = null) 2. 要素にカスタム属性を追加します (下の図に示すように)

概要: 上記により、アニメーションが得られます 最適化のための 4 つのルール:

1. 境界判定とステップサイズ

2. 無駄なタイマーを削除

3. 外側の関数がパラメータを渡す必要がある場合、関数の層をネストできますスコープの蓄積を避けるために内部にあります。

4. グローバル変数の競合や複数のアニメーションの同時実行を防ぐために、タイマーの戻り値を要素のカスタム属性に格納します

以上がJavaScript のリバウンド アニメーション効果はどのように実装されますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。