Uniform motion

Motion is a basic operation for javascript animation. Motion can be achieved through the Transition and animation properties of CSS3. (More on this later in CSS3). But javascript motion is essential for more fine-grained manipulation.

Simple movement

Moving an element around the page is as simple as setting a timer and changing the left and top values of the positioned element

<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>* {padding: 0;
        margin: 0;
      }
      #box{
        position: relative;
        width: 200px;
        height: 200px;
        background-color: red;
        left: -200px;
      }
      #box span{
        position: absolute;
        width: 40px;
        height: 60px;
        background-color: # 000;
        color: #fff;
        right: -40px;
        top: 50%;
        margin-top: -30px;
        line-height: 60px;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <span>open</span>
    <div id="box">

    </div>
    <script>
      window.onload = function () {
        var oDiv = document.getElementById('box');
        oDiv.onmouseover = function () {
          setInterval(function () {
            oDiv.style.left = oDiv.offsetLeft + 10 + 'px';
          },30)}}</script>

  </body>
</html>

Copy the code

View the effect:

It will be found that the number of times the mouse suspension, the timer will add up. And the games will go on and on. That’s not what we want. It comes down to timers and the handling of thresholds.

Timer Management

The above code does not manage timers. When the element is in the process of movement, the suspension button for many times will start the timer, so as to speed up the movement

Two timer management modes are available

  1. Delete the old timer before starting the new timer

  2. When the timer is not stopped, a new timer cannot be started

    Note: Since the return value of the timer is a non-zero integer when it is started, you can determine whether to use the return statement by judging its return value

<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }

      #box {
        position: relative;
        width: 200px;
        height: 200px;
        background-color: red;
        left: -200px;
      }

      #box span {
        position: absolute;
        width: 40px;
        height: 60px;
        background-color: # 000;
        color: #fff;
        right: -40px;
        top: 50%;
        margin-top: -30px;
        line-height: 60px;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <div id="box">
      <span>open</span>
    </div>
    <script>
      window.onload = function() {
        var oDiv = document.getElementById('box');
        var timer = null;
        oDiv.onmouseover = function() {
          //1. Clear the timer before starting it
          // clearInterval(timer);
          //2. When the timer is not stopped, a new timer cannot be started
          if(timer) return;
          timer = setInterval(function() {
            if (oDiv.offsetLeft == 500) {
              clearInterval(timer);
            } else {
              oDiv.style.left = oDiv.offsetLeft + 5 + 'px'; }},30)}}</script>

  </body>
</html>

Copy the code

Share the results

Create an effect similar to the “Share to” sidebar

<! DOCTYPEhtml>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <style type="text/css">
      * {
        padding: 0;
        margin: 0;
      }

      #box {
        position: relative;
        width: 200px;
        height: 200px;
        background-color: red;
        left: -200px;
      }

      #box span {
        position: absolute;
        width: 40px;
        height: 60px;
        background-color: # 000;
        color: #fff;
        right: -40px;
        top: 50%;
        margin-top: -30px;
        line-height: 60px;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <div id="box">
      <span>open</span>
    </div>
    <script type="text/javascript">
      window.onload = function (){
        var oDiv = document.getElementById('box');
        oDiv.onmouseover = function (){
          oDiv.style.left = 0 + 'px';
        }
        oDiv.onmouseout = function (){
          oDiv.style.left = -200 + 'px'; }}</script>
  </body>
</html>

Copy the code

Effect display:

Move in and move out effect

<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }

      #box {
        position: relative;
        width: 200px;
        height: 200px;
        background-color: red;
        left: -200px;
      }

      #box span {
        position: absolute;
        width: 40px;
        height: 60px;
        background-color: # 000;
        color: #fff;
        right: -40px;
        top: 50%;
        margin-top: -30px;
        line-height: 60px;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <div id="box">
      <span>open</span>
    </div>
    <script>
      window.onload = function() {
        var oDiv = document.getElementById('box');
        var timer = null;
        oDiv.onmouseover = function() {
          // Clear the timer before starting the timer
          clearInterval(timer);
          timer = setInterval(function() {
            // Set the boundary and clear the timer
            if (oDiv.offsetLeft === 0) {
              clearInterval(timer);
            } else {
              oDiv.style.left = oDiv.offsetLeft + 5 + 'px'; }},30)

        }
        oDiv.onmouseout = function() {
          // Clear the timer before starting the timer
          clearInterval(timer);
          timer = setInterval(function() {
            console.log(oDiv.offsetLeft);
            // Set the boundary and clear the timer
            if (oDiv.offsetLeft === -200) {
              clearInterval(timer);
            } else {
              oDiv.style.left = oDiv.offsetLeft - 5 + 'px'; }},30)}}</script>

  </body>
</html>

Copy the code

Movement function

From the above code, we can see that there is a lot of repetitive code in the movement part, and it is more appropriate to encapsulate the movement as a function with parameters

<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>* {padding: 0;
        margin: 0;
      }
      #box{
        position: relative;
        width: 200px;
        height: 200px;
        background-color: red;
        left: -200px;
      }
      #box span{
        position: absolute;
        width: 40px;
        height: 60px;
        background-color: # 000;
        color: #fff;
        right: -40px;
        top: 50%;
        margin-top: -30px;
        line-height: 60px;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <div id="box">
      <span>open</span>
    </div>
    <script>
      window.onload = function () {
        var oDiv = document.getElementById('box');
        oDiv.onmouseover = function () {
          // Uniform motion begins
          startMove(this.0)
        }
        oDiv.onmouseout = function () {
          // Uniform motion begins
          startMove(this, -200)}}var timer = null,speed = 0;
      / * * *@param {Object} ODiv current target object *@param {Object} Target Indicates the target position of the movement */
      function startMove(oDiv,target) {
        // Clear the timer before starting the timer
        clearInterval(timer);
        timer = setInterval(function () {
          // We want the box to be able to move forward as well as backward, so we need to have both positive and negative steps
          // The target value is positive if greater than the current value, and negative if less than the current value
          speed  = target > oDiv.offsetLeft ? 10 : -10;
          // Set the boundary and clear the timer
          if(oDiv.offsetLeft === target){
            clearInterval(timer);

          }else{
            oDiv.style.left = oDiv.offsetLeft + speed + 'px'; }},30)}</script>

  </body>
</html>

Copy the code

Effect display:

Slow motion

What is slow motion? For example, when a train enters a station, its speed changes from fast to slow, while when the train leaves the station, its speed changes from slow to fast.

Slow animation formula: speed = (end value – start value) * slow coefficient.

The number between 0 and 1.

Basic slow animation

<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }

      #box {
        position: relative;
        width: 200px;
        height: 200px;
        background-color: red;
        left: -200px;
      }

      #box span {
        position: absolute;
        width: 40px;
        height: 60px;
        background-color: # 000;
        color: #fff;
        right: -40px;
        top: 50%;
        margin-top: -30px;
        line-height: 60px;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <div id="box">
      <span>open</span>
    </div>
    <script>
      window.onload = function() {
        var oDiv = document.getElementById('box');
        var timer = null,target = 0,target1 = -200;

        oDiv.onmouseover = function() {
          clearInterval(timer);
          timer = setInterval(function() {
            speed = (target-oDiv.offsetLeft) / 20;		
            if (oDiv.offsetLeft == target) {
              clearInterval(timer);
            } else {
              oDiv.style.left = oDiv.offsetLeft + speed + 'px'; }},30)
        }

        oDiv.onmouseout= function() {
          clearInterval(timer);
          timer = setInterval(function() {
            speed = (target1-oDiv.offsetLeft) / 20;		
            if (oDiv.offsetLeft == target1) {
              clearInterval(timer);
            } else {
              oDiv.style.left = oDiv.offsetLeft + speed + 'px'; }},30)}}</script>

  </body>
</html>


Copy the code

Slow motion function

<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }

      #box {
        position: relative;
        width: 200px;
        height: 200px;
        background-color: red;
        left: -200px;
      }

      #box span {
        position: absolute;
        width: 40px;
        height: 60px;
        background-color: # 000;
        color: #fff;
        right: -40px;
        top: 50%;
        margin-top: -30px;
        line-height: 60px;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <div id="box">
      <span>open</span>
    </div>
    <script>
      window.onload = function() {
        // Get the label
        var oDiv = document.getElementById('box');
        // Timer variable is set globally, to be dealt with later
        var timer = null;

        oDiv.onmouseover = function() {
          slowMove(this.0);
        }
        //
        oDiv.onmouseout= function() {
          slowMove(this, -200);
        }
        function slowMove(obj,target){
          clearInterval(timer);
          timer = setInterval(function() {
            speed = (target-obj.offsetLeft) / 20;
            // If the velocity is greater than 0, it is to the right, rounded up. If the velocity is less than 0, you go left and round down
            speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
            if (obj.offsetLeft == target) {
              clearInterval(timer);
            } else {
              obj.style.left = obj.offsetLeft + speed + 'px'; }},30)}}</script>

  </body>
</html>

Copy the code

Transparency animation

Opacity is a special style, because Internet Explorer 8 does not support opacity, which can only be written as filter: alpha(opacity= opacity).

If the transparency moves, the motion function needs to be repackaged

The fading

The code is as follows:

<! DOCTYPEhtml>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <style type="text/css">
      #box{
        width: 200px;
        height: 200px;
        background-color: red; 
        opacity: 0.3;
        filter: alpha(opactity:30);
      }
    </style>
  </head>
  <body>
    <div id="box"></div>
    <script type="text/javascript">
      window.onload = function (){
        var box = document.getElementById('box');
        box.onmouseover = function (){
          opacityAnimation(box,100);
        }
        box.onmouseout = function (){
          opacityAnimation(box,30);
        }
        var alpha = 30,timer = null,speed = 0;
        function opacityAnimation(ele,target){
          clearInterval(timer);
          timer = setInterval(function(){
            // If the target value is greater than the currently changing value, it is represented as true and transparency is increasing, and vice versa
            speed = target > alpha ? 10 : -10;
            // The current change value equals the target value, clear the timer
            if(alpha == target){
              clearInterval(timer);						
            }else{
              // Otherwise, transparency changes
              alpha+=speed;
              ele.style.filter = 'alpha(opactity:'+alpha+') ';
              ele.style.opacity = alpha / 100; }},30)}}</script>
  </body>
</html>

Copy the code

Different from the movement of the object, the opacity value changes when it changes. CSS properties have no value like offsetAlpha. So we define an initial alpha = 30 variable globally to control the change in the current transparency value.

Multi-object animation

If you have multiple elements on a page that move using the motion function. Because the timer returns different values on different elements. So you want to mount the global timer on the current element.

See a BUG

<! DOCTYPEhtml>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <style>* {padding: 0;
        margin: 0;
      }
      ul{
        list-style: none;
      }
      ul li{
        margin: 20px 0;
        width: 300px;
        height: 150px;
        background-color: yellowgreen;
      }
    </style>
    <script type="text/javascript">
      window.onload = function() {
        var allLis = document.getElementsByTagName('li');
        for (var i = 0; i < allLis.length; i++) {
          allLis[i].onmouseover = function() {
          /** * The first argument is the current object, and the second argument is the target value */
            startMove(this.600);
          }
          allLis[i].onmouseout = function() {
            startMove(this.300); }}var speed = 0,
            timer = null;

        function startMove(ele, target) {
          clearInterval(timer);
          timer = setInterval(function() {
            // 1. Find the step size
            speed = (target - ele.offsetWidth) * 0.5;
            // 2. Check the speed
            speed = target > ele.offsetWidth ? Math.ceil(speed) : Math.floor(speed);
            if (ele.offsetWidth == target) {
              clearInterval(ele.timer);
            } else {
              // 3. Get moving
              ele.style.width = ele.offsetWidth + speed + 'px'; }},30)}}</script>
  </head>
  <body>
    <ul>
      <li></li>
      <li></li>
      <li></li>
    </ul>
  </body>
</html>

Copy the code

The effect is as follows:

This is clearly not what we want. That’s because we all turn on the timer when we’re levitating fast. The timer cleared by the cleartInterVal() method makes it hard for it to know which timer it cleared. Led to an unexpected effect. To solve this problem, we should mount the timer variable onto the current element

The solution code is as follows:

window.onload = function() {
  var allLis = document.getElementsByTagName('li');
  for (var i = 0; i < allLis.length; i++) {
    allLis[i].onmouseover = function() {
      /** * The first argument is the current object, and the second argument is the target value */
      startMove(this.600);
    }
    allLis[i].onmouseout = function() {
      startMove(this.300); }}var speed = 0;
  function startMove(ele, target) {
    clearInterval(ele.timer);
    ele.timer = setInterval(function() {
      // 1. Find the step size
      speed = (target - ele.offsetWidth) * 0.5;
      // 2. Check the speed
      speed = target > ele.offsetWidth ? Math.ceil(speed) : Math.floor(speed);
      if (speed == target) {
        clearInterval(ele.timer);
      } else {
        // 3. Get moving
        ele.style.width = ele.offsetWidth + speed + 'px'; }},30)}}Copy the code

Perfect effect

Get the style

We had a lot of problems with multi-object motion last time. For example, if we set the border for the li tag :4px solid #000; You might want to take a look at the effect. (We want it to hover width:600px; Left width:300px). But there are bugs. This is because offsetWidth. So let’s look at that.

Study offsetWidth’s pits

Here’s an example:

<! DOCTYPEhtml>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <style type="text/css">
      #box{
        width: 200px;
        height: 200px;
        background-color: red;
        border: 1px solid # 000;
      }
    </style>
  </head>
  <body>
    <div id="box"></div>
    <script type="text/javascript">
      window.onload = function (){
        var oBox = document.getElementById('box');
        move(oBox);
      }
      function move(obj){
        setInterval(function (){
          obj.style.width = obj.offsetWidth-1 + 'px';
        },30)}</script>
  </body>
</html>

Copy the code

I want the width of the box to decrease gradually. However, once you run the above code, you will find something strange and wonder why.

May wish to alert (obj. OffsetWidth); . You’ll see that you get 202. Width = obj.offsetwidth-1 + ‘px’; The resulting width is 201px. It is 1px larger than the width in the original CSS style. Border-left-width + padding-left + width + padding-right + border-right-width; So we cannot get the width of the current box by offsetWidth.

There are two ways to do it

1. Set the width of the in-line style for the current box and use obj.style.width to obtain the width of the current box. But we can’t write all the boxes in the line. Therefore, it is not recommended.

2. Encapsulate your own style function to get attributes

/ * * *@param {Object} Obj which object *@param {Object} Attr what attribute */
function getStyle(obj,attr){
  if(obj.currentStyle){
    // For Internet Explorer
    return obj.currentStyle[attr];
  }else{
    // For Firefox
    return getComputedStyle(obj,null)[attr]; }}Copy the code

The complete code is as follows:

<! DOCTYPEhtml>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <style type="text/css">
      #box{
        width: 200px;
        height: 200px;
        background-color: red;
        border: 1px solid # 000;
      }
    </style>
  </head>
  <body>
    <div id="box"></div>
    <script type="text/javascript">
      window.onload = function (){
        var oBox = document.getElementById('box');
        move(oBox);
      }
      function move(obj){
        setInterval(function (){
          obj.style.width = parseInt(getStyle(obj,'width')) -1 + 'px';
        },30)}/ * * *@param {Object} Obj which object *@param {Object} Attr what attribute */
      function getStyle(obj,attr){
        if(obj.currentStyle){
          // For Internet Explorer
          return obj.currentStyle[attr];
        }else{
          // For Firefox
          return getComputedStyle(obj,null)[attr]; }}</script>
  </body>
</html>

Copy the code

Multi-object motion complete edition

<! DOCTYPEhtml>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <style>* {padding: 0;
        margin: 0;
      }
      ul{
        list-style: none;
      }
      ul li{
        margin: 20px 0;
        width: 300px;
        height: 150px;
        background-color: yellowgreen;
        border: 4px solid # 000;
      }
    </style>
    <script type="text/javascript">
      window.onload = function() {
        var allLis = document.getElementsByTagName('li');
        for (var i = 0; i < allLis.length; i++) {
          allLis[i].onmouseover = function() {
            /** * The first argument is the current object, and the second argument is the target value */
            startMove(this.600);
          }
          allLis[i].onmouseout = function() {
            startMove(this.300); }}var speed = 0;

        function startMove(ele, target) {
          //1. Turn off and then on the timer
          clearInterval(ele.timer);
          ele.timer = setInterval(function() {
            // 1.1 Get style attributes
            var cur = parseInt(getStyle(ele,'width'));
            // 1.2. Find the step size
            speed = (target - cur) * 0.5;
            // 1.3 Check the speed
            speed = target > cur ? Math.ceil(speed) : Math.floor(speed);
            //1.4 Critical value judgment
            if (cur == target) {
              clearInterval(ele.timer);
            } else {
              // get moving
              ele.style.width = cur + speed + 'px'; }},30)}}</script>
  </head>
  <body>
    <ul>
      <li></li>
      <li></li>
      <li></li>
    </ul>
  </body>
</html>

Copy the code

More value

What if I want to change both the width of an element and the height of a box? How to do it?

Style [‘width’] = cur + speed + ‘px’; style[‘width’] = cur + speed + ‘px’; In this way, attributes can be put into wrapped functions as parameters.

function startMove(ele,attr,target) {
  //1. Turn off and then on the timer
  clearInterval(ele.timer);
  ele.timer = setInterval(function() {
    // 1.1 Get style attributes
    var cur = parseInt(getStyle(ele,attr));
    // 1.2. Find the step size
    speed = (target - cur) * 0.5;
    // 1.3 Check the speed
    speed = target > cur ? Math.ceil(speed) : Math.floor(speed);
    //1.4 Critical value judgment
    if (cur == target) {
      clearInterval(ele.timer);
    } else {
      // get moving
      ele.style[attr] = cur + speed + 'px'; }},30)}Copy the code

So when the external is called

var allLis = document.getElementsByTagName('li');
allLis[0].onmouseover = function (){
  startMove(this.'width'.600);
}
allLis[0].onmouseout = function (){
  startMove(this.'width'.300);
}
allLis[1].onmouseover = function (){
  startMove(this.'height'.400);
}
allLis[1].onmouseout = function (){
  startMove(this.'height'.150);
}
Copy the code

Let me ask you a question: what properties in CSS can’t be implemented with getStyle?

Transparency style processing

In the last class we were left with the question, what attributes can’t getStyle get? In the last code, our motion frame is gradually taking shape, but it’s far from enough, like looking at a bug. Last time code modification

<! DOCTYPEhtml>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <style>* {padding: 0;
        margin: 0;
      }
      ul{
        list-style: none;
      }
      ul li{
        margin: 20px 0;
        width: 300px;
        height: 150px;
        background-color: yellowgreen;
        border: 4px solid # 000;
        opacity: 0.3;
        filter: alpha(opacity: 30);
      }
    </style>
    <script type="text/javascript">
      window.onload = function() {
        var allLis = document.getElementsByTagName('li');
        allLis[0].onmouseover = function (){
          startMove(this.'opacity'.100);
        }
        allLis[0].onmouseout = function (){
          startMove(this.'opacity'.30);
        }
        var speed = 0;

        function startMove(ele, attr,target) {
          //1. Turn off and then on the timer
          clearInterval(ele.timer);
          ele.timer = setInterval(function() {
            // 1.1 Get style attributes
            var cur = parseInt(getStyle(ele,attr));
            // 1.2. Find the step size
            speed = (target - cur) * 0.5;
            // 1.3 Check the speed
            speed = target > cur ? Math.ceil(speed) : Math.floor(speed);
            //1.4 Critical value judgment
            if (cur == target) {
              clearInterval(ele.timer);
            } else {
              // get moving
              ele.style[attr] = cur + speed + 'px'; }},30)}/ * * *@param {Object} Obj which object *@param {Object} Attr what attribute */
        function getStyle(obj,attr){
          if(obj.currentStyle){
            // For Internet Explorer
            return obj.currentStyle[attr];
          }else{
            // For Firefox
            return getComputedStyle(obj,null)[attr]; }}}</script>
  </head>
  <body>
    <ul>
      <li></li>
      <li></li>
      <li></li>
    </ul>
  </body>
</html>


Copy the code

The effect is as follows:

The value of opacity property does not change at all, for two reasons. Look at the picture

So, given these two reasons, let’s solve these two.

Modify the code as follows:


var speed = 0;
function startMove(ele, attr,target) {
  //1. Turn off and then on the timer
  clearInterval(ele.timer);
  ele.timer = setInterval(function() {
    // 1.1 Getting style attributes handles transparency issues
    var cur = 0;
    if(attr === 'opacity'){
      cur = Math.round(parseFloat(getStyle(ele,attr))*100);
    }else{
      cur = parseInt(getStyle(ele,attr));
    }
    // 1.2. Find the step size
    speed = (target - cur) * 0.5;
    // 1.3 Check the speed
    speed = target > cur ? Math.ceil(speed) : Math.floor(speed);
    //1.4 Critical value judgment
    if (cur == target) {
      clearInterval(ele.timer);
    } else {
      if(attr === 'opacity'){
        ele.style[attr]  = 'alpha(opacity:'+(cur+speed)+') ';
        ele.style[attr] = (cur + speed)/100;
      }else{
        // get moving
        ele.style[attr] = cur + speed + 'px'; }}},30)}/ * * *@param {Object} Obj which object *@param {Object} Attr what attribute */
function getStyle(obj,attr){
  if(obj.currentStyle){
    // For Internet Explorer
    return obj.currentStyle[attr];
  }else{
    // For Firefox
    return getComputedStyle(obj,null)[attr]; }}Copy the code

Note: Since transparency involves decimals, such as 0.07*100=> 7.000000000000001, you need to remove the tail with math.round ()

Chain animation

Multiple properties of an object may move simultaneously, or one property may move after another. To achieve this effect, you need to use the callback function.

Results the following

If you want to achieve the above effect. The motion frame we will now encapsulate is stored in a myAnimation.js file.

myAnimation.js

var speed = 0;
/ * * *@param {Object} Ele The current element *@param {Object} Attr An attribute * of the current element@param {Object} * / target goal
function startMove(ele, attr, target,fn) {
  //1. Turn off and then on the timer
  clearInterval(ele.timer);
  ele.timer = setInterval(function() {
    // 1.1 Get style attributes
    var cur = 0;
    if (attr === 'opacity') {
      cur = Math.round(parseFloat(getStyle(ele, attr)) * 100);
    } else {
      cur = parseInt(getStyle(ele, attr));
    }
    // 1.2. Find the step size
    speed = (target - cur) * 0.5;
    // 1.3 Check the speed
    speed = target > cur ? Math.ceil(speed) : Math.floor(speed);
    //1.4 Critical value judgment
    if (cur == target) {
      clearInterval(ele.timer);
      // Where to modify
      // Call fn at the end of the call
      if(fn){ fn(); }}else {
      if (attr === 'opacity') {
        ele.style[attr] = 'alpha(opacity:' + (cur + speed) + ') ';
        ele.style[attr] = (cur + speed) / 100;
      } else {
        // get moving
        ele.style[attr] = cur + speed + 'px'; }}},30)}/ * * *@param {Object} Obj which object *@param {Object} Attr what attribute */
function getStyle(obj, attr) {
  if (obj.currentStyle) {
    // For Internet Explorer
    return obj.currentStyle[attr];
  } else {
    // For Firefox
    return getComputedStyle(obj, null)[attr]; }}Copy the code

External references.

<! --1. Introduce external modules first -->
<script src="js/myAnimation.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
  window.onload = function() {
    //2. Get the element
    var oBox = document.getElementById('box');
    //3
    oBox.onmouseover = function() {
      // Be careful with the reference to this in the callback function. The reference to this in the callback refers to the window object
      var that = this;
      / / 3. The movement
      startMove(this.'width'.500.function(){
        startMove(that,'height'.400);
      });
    }
    oBox.onmouseout = function() {
      var that = this;
      startMove(this.'height'.200.function(){
        startMove(that,'width'.200); }); }}</script>
Copy the code

At the same time movement

If the previous motion frame, we wanted the element to be able to change both width and transparency. This is where we use JSON. We’ll talk about JSON in more detail later in the class, but let’s use it briefly for now

var json = {
  "name":"mjj"."age":29
}
for(var attr in json){
  alert(attr); // Get the attribute name
  alert(json[attr]);// Get the attribute value
}
Copy the code

With the simple JSON usage above, we’ll modify myanimation.js.

var speed = 0;
/ * * *@param {Object} Ele The current element *@param {Object} Json Current element numeric key value versus JSON data *@param {Object} Fn Current callback function */
function startMove(ele, json,fn) {
  //1. Turn off and then on the timer
  clearInterval(ele.timer);
  ele.timer = setInterval(function() {
    for(var attr in json){
      // 1.1 Get style attributes
      var cur = 0;
      if (attr === 'opacity') {
        cur = Math.round(parseFloat(getStyle(ele, attr)) * 100);
      } else {
        cur = parseInt(getStyle(ele, attr));
      }
      // 1.2. Find the step size
      speed = (json[attr] - cur) * 0.5;
      // 1.3 Check the speed
      speed = json[attr] > cur ? Math.ceil(speed) : Math.floor(speed);
      //1.4 Critical value judgment
      if (cur == json[attr]) {
        clearInterval(ele.timer);
        // Call fn at the end of the call
        if(fn){ fn(); }}else {
        if (attr === 'opacity') {
          ele.style[attr] = 'alpha(opacity:' + (cur + speed) + ') ';
          ele.style[attr] = (cur + speed) / 100;
        } else {
          // get moving
          ele.style[attr] = cur + speed + 'px'; }}}},30)}/ * * *@param {Object} Obj which object *@param {Object} Attr what attribute */
function getStyle(obj, attr) {
  if (obj.currentStyle) {
    // For Internet Explorer
    return obj.currentStyle[attr];
  } else {
    // For Firefox
    return getComputedStyle(obj, null)[attr]; }}Copy the code
<script src="js/myAnimation2.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
  window.onload = function() {
    var oBox = document.getElementById('box');
    oBox.onmouseover = function() {
      startMove(oBox,{"width":400."height":400.'opacity': 100})
    }
    oBox.onmouseout = function() {
      startMove(oBox,{"width":200."height":200.'opacity': 30}}})</script>
Copy the code

The effect is as follows:

Through the above modification, we achieved the desired effect. Really ?????? See a bug. Modify the code

<script src="js/myAnimation2.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
  window.onload = function() {
    var oBox = document.getElementById('box');
    oBox.onmouseover = function() {
      startMove(oBox,{"width":201."height":400.'opacity': 100})
    }
    oBox.onmouseout = function() {
      startMove(oBox,{"width":200."height":200.'opacity': 30}}})</script>
Copy the code

The BUG effect is as follows:

It seems that the wrapped myAnimation.js motion framework has a problem. The analysis causes are shown in the figure:

That is, the timer is turned off when all the attributes in the JSON have reached their destination value. In other words, the timer cannot be turned off until the end value of the property in the JSON is reached.

Modify the code as follows:

var speed = 0;
/ * * *@param {Object} Ele The current element *@param {Object} Json Current element numeric key value versus JSON data *@param {Object} Fn Current callback function */
function startMove(ele, json, fn) {
  //1. Turn off and then on the timer
  clearInterval(ele.timer);
  ele.timer = setInterval(function() {
    // Make a benchmark, if true, to prove that all attributes have reached their destination value
    var flag = true;
    for (var attr in json) {
      // console.log(attr,json[attr]);
      // 1.1 Get style attributes
      var cur = 0;
      if (attr === 'opacity') {
        cur = Math.round(parseFloat(getStyle(ele, attr)) * 100);
      } else {
        cur = parseInt(getStyle(ele, attr));
      }
      // 1.2. Find the step size
      speed = (json[attr] - cur) / 20;
      // 1.3 Check the speed
      speed = json[attr] > cur ? Math.ceil(speed) : Math.floor(speed);

      // 1.4 If all attributes do not reach the end value. Proceed with the following code
      if(cur ! == json[attr]){ flag =false;
      }
      //1.5 Handle property named opacity
      if (attr === 'opacity') {
        / / 1.5.1 compatible with IE
        ele.style[attr] = 'alpha(opacity:' + (cur + speed) + ') ';
        //1.5.2 W3C Browser
        ele.style[attr] = (cur + speed) / 100;
      } else {
        // 1.6 Get moving
        ele.style[attr] = cur + speed + 'px'; }}// 1.6 If flag is true, it indicates that all attributes have reached the end point. At this point, the timer is cleared and the callback function is executed
    if (flag) {
      clearInterval(ele.timer);
      if(fn) { fn(); }}},30)}/ * * *@param {Object} Obj which object *@param {Object} Attr what attribute */
function getStyle(obj, attr) {
  if (obj.currentStyle) {
    // For Internet Explorer
    return obj.currentStyle[attr];
  } else {
    // For Firefox
    return getComputedStyle(obj, null)[attr]; }}Copy the code

So far our motion frame is almost complete and can be applied to many effects on a web page. For example: infinite rotation graphics effects, linkage effects, navigation animation effects