A step-by-step tour of JavaScript's perfect motion frame

Source: Internet
Author: User
Tags add filter object end execution integer string variable

The realization of motion frame

Movement, in fact, in a period of time to change the left, right, width, height, opactiy value, to reach the destination after the stop.  
now follow the steps below to carry out the package of our motion frame: uniform velocity.   Buffer movement.   Multi-Object movement.   Any change in value.   Chain type movement.   Movement at the same time.   (i) Motion speed animation basic thinking: How to let the div move? as follows: Set element as absolute positioning, only after absolute positioning, left,top equivalent is effective.   The use of the timer (dynamically changing the value), where the SetInterval () is used to execute the code at specified intervals.   Timer setinterval (function, interaction time (milliseconds)): At execution time, code is executed at the specified time after the page is loaded.   Cancels the timer clearinterval (function) method to cancel the interaction time set by SetInterval (). Get the current location, size, and so on.   Offsetleft (the current element is relative to the parent element position). Velocity-the speed of the object movement the timer interval changes the size of the value according to the above information we can begin to encapsulate the motion frame to create a changed div.
  1. /**
  2. * Motion Frame--Move Up
  3. * @param {HtmlElement} element to move the node
  4. */
  5. var timer = null;
  6. function Startmove (Element) {
  7. Timer = setinterval (function () {//Timer
  8. Element.style.left = element.offsetleft + 5 + "px";
  9. }, 30);
  10. }
you are not wrong, it is so simple. But wait, what? Why won't you stop?   WTF? That's because we don't have sports to terminate the condition. Well, it's still easier. Directly in the timer inside, judge to reach the target value, clear the timer on the line pull!
  1. /** 
  2.  *  Motion Frame-motion termination  
  3.  *  @param  {HTMLElement} element  moving node  
  4.  *  @param  {number}      iTarget  movement termination conditions.  
  5.  */ 
  6.  var timer = null; 
  7. function startmove (element, itarget)  { 
  8.     timer =  setinterval (function  ()  { 
  9.          element.style.left = element.offsetLeft + 5 +  "px";  
  10.          if  (element.offsetleft === itarget)  {//stop condition  
  11.              Clearinterval (timer);  
  12.         } 
  13.     },& NBSP;30);  
So is it done?  It's OK now? No   There are also some bugs to deal with. the bug in the motion speed to some value can not stop the arrival of the position and then click on the motion repeated click speed can not be changed resolution of the bug speed to some values will not stop ( This bug is resolved later, naturally resolved during evolution) to move and stop (If/else) when starting a motion, close an existing timer and save the speed with a variable
  1. /** 
  2.  *  Motion Framework-Solution bug 
  3.  */ 
  4. var timer = null; 
  5. function  Startmove (Element, itarget)  { 
  6.     clearinterval (timer); Close existing timer  
  7.     timer = setinterval (function  ()   { 
  8.         var ispeed = 5;//saves the speed with a variable  
  9.         //Move and Stop (If/else)  
  10.          if  (Element.offsetleft === itarget)  {//end motion  
  11.             clearinterval (timer);  
  12.         } ELSE&NBsp { 
  13.             element.style.left  = element.offsetLeft + iSpeed +  "px";  
  14.          } 
  15.     }, 30);  
Such a simple frame of motion is done. But wait a second. Just go right? Don't worry, we're not defining speed as a variable? Just have to do some processing on it!   var ispeed = 5;
  1. To determine the distance from the target position, to achieve automatic change speed or positive
  2. var ispeed = 0;
  3. if (Element.offsetleft < ITarget) {
  4. Ispeed = 5;
  5. } else {
  6. Ispeed =-5;
  7. }
Transparency Animation stores current transparency with variable alpha.   Change the above element.offsetleft to variable alpha. The motion and stop conditions section are changed. As follows:
  1. Transparency Browser Compatibility implementation
  2. if (alpha = = ITarget) {
  3. Clearinterval (time);
  4. } else {
  5. Alpha + speed;
  6. Element.style.filter = ' alpha (opacity: ' + alpha + ') '; Compatible IE
  7. Element.style.opacity = alpha/100;//Standard
  8. }

(ii) Buffering animation

think: What is the buffer animation? Should have the following: Gradually slow, the last stop distance the greater the speed of the speed determined by the distance = (target-current value)/scaling factor Bug: Speed rounding (using the math method), otherwise it will flash upward rounding. Math.ceil (ispeed) is rounded down. Math.floor (ispeed) or the speed of the article:
  1. /**&NBSP;
  2.  *  Motion Frame-buffer animation  
  3.  */ 
  4. function startmove (element, itarget)  { 
  5.     timer =  SetInterval (function  ()  { 
  6.     //must be placed in the timer because the speed is changing dynamically  
  7.         var iSpeed =  (itarget -  element.offsetleft)  / 10; //(target-current value)/scaling factor = speed  
  8.          ispeed = ispeed > 0 ? math.ceil (ISpeed)  : math.floor (ispeed);  //speed rounding  
  9.         if   (Element.offsetleft === itarget)  {//End motion  
  10.  &nbsP;          clearinterval (timer);  
  11.          } else { 
  12.              element.style.left = element.offsetLeft +  ispeed +  "px";  
  13.         } 
  14.     }, 30);  
Do this, (speed to some value will not be able to stop) the bug is automatically resolved! Example: Buffer menu follow page scrolling sidebar online Demo: Codepen potential problem target value is not an integer

(iii) Multi-object movement

thinking: How to achieve the movement of multiple objects? Single timer, there are problems.   Each div a timer timer acts as an object's property directly using Element.timer to turn the timer into an attribute on the object. Transfer of parameters: Object/target value is simpler the above frame is changed as follows: Timer--&gt;element.timer it's all right!

(iv) changes in arbitrary values

cough. Let's add a 1px border to the Div. boder:1px Solid #000 Then try the following code
  1. SetInterval (function () {
  2. ODiv.style.width = odiv.offsetwidth-1 + "px";
  3. }, 30)
Well, something magical has happened! What Do I not set the width in the minus? How the NI increased!   No, Big Brother.   What has gone wrong?   Look for information together, see the document, the original offset this series of properties will exist, by other attributes interfere with the problem.   Well, since it can't be used, then we'll just have to do the change of any value. First step: Get the actual style &nbsp; Use offsetleft ... When you get a style, a bug occurs when you set a border, padding, and so on to change the properties of the element's width height. &nbsp; Find Element.currentstyle (attr) to get the properties after the calculation. &nbsp; But because of compatibility issues, you need to encapsulate the GetStyle function. (Evil IE) &nbsp; of course with CSS Box-sizing property set to Border-box can achieve the same effect? (self-considered, not validated). &nbsp;
  1. /**&NBSP;
  2.  *  get actual style function  
  3.  *  @param    {HTMLElement}   element   HTML node for the style to look for  
  4.  *  @param    {String]} attr  style properties found in Objects  
  5.  *  @returns  {String}  acquired property  
  6.  */ 
  7. function  getstyle (element, attr)  { 
  8.     //ie writing  
  9.     if  (Element.currentstyle)  { 
  10.          return element.currentstyle[attr]; 
  11.      //Standard  
  12.     } else { 
  13.          return getcomputedstyle (Element, false) [attr]; 
  14.     } 
  15. }&NBSP;
Step Two: Transform the original function add parameters, attr represent the value of the property that needs to be changed.   Change Element.offsetleft to GetStyle (element, attr).   Note that getstyle (element, attr) cannot be used directly because it gets the string, example: 10px.   Variable icurrent use parseint () to convert a style to a number.   Element.style.left for Element.style[attr].
  1. /**
  2. * Arbitrary value change of motion frame
  3. * @param {HtmlElement} Element motion Object
  4. * @param {string} attr properties that need to be changed.
  5. * @param {Number} ITarget target value
  6. */
  7. function Startmove (element, attr, ITarget) {
  8. Clearinterval (Element.timer);
  9. Element.timer = setinterval (function () {
  10. Because the speed has to be changed dynamically, it must be placed in the timer.
  11. var icurrent=0;
  12. Icurrent = parseint (GetStyle (element, attr))//Actual style size
  13. var ispeed = (itarget-icurrent)/10; (target value-current value)/scaling factor = speed
  14. Ispeed = ispeed > 0? Math.ceil (ispeed): Math.floor (Ispeed); Speed rounding
  15. if (icurrent = = ITarget) {//End Motion
  16. Clearinterval (Element.timer);
  17. } else {
  18. ELEMENT.STYLE[ATTR] = icurrent + ispeed + "px";
  19. }
  20. }, 30);
  21. }
give it a try, is it OK? Do you remember the transparency changes we wrote above? Try again true or not, (nonsense, you have seen the transparency of "PX" unit?) --supercilious eyes) Third step: transparency compatibility processingThinking: Do you need to modify those attributes?   Determine if attr is a transparency property opacity.   For speed processing. For transparency, you need * 100 because the transparency you get is decimal, and you need to round the decimal number to an integer because the computer stores floating point numbers.   Use: Math.Round (parsefloat (GetStyle (element, attr)) * 100).   Otherwise, continue using the default speed.   Make changes to the result output section.   Judgment is the transparency property, use the transparency method otherwise, use the default output format.
  1. /**
  2. * Motion Frame-compatible transparency
  3. * @param {HtmlElement} Element motion Object
  4. * @param {string} attr properties that need to be changed.
  5. * @param {Number} ITarget target value
  6. */
  7. function Startmove (element, attr, ITarget) {
  8. Clearinterval (Element.timer);
  9. Element.timer = setinterval (function () {
  10. Because the speed has to be changed dynamically, it must be placed in the timer.
  11. var icurrent = 0;
  12. if (attr = = "opacity") {//is executed for transparency.
  13. Icurrent = Math.Round (parsefloat (GetStyle (element, attr)) * 100);
  14. } else {//default
  15. Icurrent = parseint (GetStyle (element, attr)); Actual style size
  16. }
  17. var ispeed = (itarget-icurrent)/10; (target value-current value)/scaling factor = speed
  18. Ispeed = ispeed > 0? Math.ceil (ispeed): Math.floor (Ispeed); Speed rounding
  19. if (icurrent = = ITarget) {//End Motion
  20. Clearinterval (Element.timer);
  21. } else {
  22. if (attr = = "opacity") {//For transparency, perform
  23. Element.style.filter = "Alpha (opacity:" + (Icurrent + ispeed) + ")"; Ie
  24. Element.style.opacity = (icurrent + ispeed)/100; Standard
  25. } else {//default
  26. ELEMENT.STYLE[ATTR] = icurrent + ispeed + "px";
  27. }
  28. }
  29. }, 30);
  30. }
here, the movement framework is basically complete. But we're in pursuit of perfection, aren't we?

continue to evolve!

(v) Chain-type animation

chain Animation: As the name suggests, is to start the next movement when the movement stops.   How to achieve it?   Use the callback function: When the motion stops, the execution function adds the Func parameter (the callback function).   Icurrent = = ITarget when the current attribute arrives at the destination, to determine if there is a callback function, and to execute it.     if (icurrent = = ITarget) {//End movement Clearinterval (Element.timer); if (func) {func ();//callback function}} good, the chain animation completes! The perfect distance is still one step away!

(vi) Simultaneous movement

Thinking: How to achieve simultaneous movement?   Use JSON to pass multiple values using a for in loop, traversing the property, and the value. Timer problem! (Motion stopped early) sets the variable outside the loop, suppose all the values have reached the destination value is true in the loop to detect whether to reach the target value, if no value is not yet, false at the end of the loop, detect whether all the target values are reached. Yes then clear Timer implementation: Delete attr and ITarget two parameter, change to JSON when the function starts, set a tag var flag = true;   Let's say all the movements arrive at the end. In the timer, use for in, traverse the properties and targets, rewrite the original attr and ITarget, modify the motion termination condition for the properties and values of the JSON, and flag true only if the actual property value of each item is icurrent equal to the target value json[attr].   Clear the timer to determine if the callback.   Otherwise, continue executing the code until all the property values are equal to the target value. Perfect Motion Frame
  1. /**
  2. * Get the actual style function
  3. * @param {htmlelement} element HTML node for the style to look for
  4. * @param {String]} attr The style properties found in the object
  5. * @returns the properties obtained by {String}
  6. */
  7. function GetStyle (element, attr) {
  8. IE notation
  9. if (Element.currentstyle) {
  10. return element.currentstyle[attr];
  11. Standard
  12. } else {
  13. return getComputedStyle (element, false) [attr];
  14. }
  15. }
  16. /**
  17. * Perfect Motion Frame
  18. * @param {HtmlElement} Element motion Object
  19. * @param {JSON} JSON attribute: Target value
  20. * @property {String} attr property value
  21. * @config {Number} target destination value
  22. * @param {function} func optional, callback function, chain animation.
  23. */
  24. function Startmove (element, JSON, func) {
  25. var flag = true; Let's say all the movements arrive at the end.
  26. Clearinterval (Element.timer);
  27. Element.timer = setinterval (function () {
  28. for (Var attr in JSON) {
  29. 1. Take the current property value.
  30. var icurrent = 0;
  31. if (attr = = "opacity") {//is executed for transparency.
  32. Icurrent = Math.Round (parsefloat (GetStyle (element, attr)) * 100);
  33. } else {//default
  34. Icurrent = parseint (GetStyle (element, attr)); Actual style size
  35. }
  36. 2. Calculate the movement speed, the animation buffering effect
  37. var ispeed = (json[attr]-icurrent)/10; (target value-current value)/scaling factor = speed
  38. Ispeed = ispeed > 0? Math.ceil (ispeed): Math.floor (Ispeed); Speed rounding
  39. 3. Execute code when the target value is not reached
  40. if (icurrent!= json[attr]) {
  41. Flag = false; Termination condition
  42. if (attr = = "opacity") {//For transparency, perform
  43. Element.style.filter = "Alpha (opacity:" + (Icurrent + ispeed) + ")"; Ie
  44. Element.style.opacity = (icurrent + ispeed)/100; Standard
  45. } else {//default
  46. ELEMENT.STYLE[ATTR] = icurrent + ispeed + "px";
  47. }
  48. } else {
  49. Flag = true;
  50. }
  51. 4. Motion terminated, whether callback
  52. if (flag) {
  53. Clearinterval (Element.timer);
  54. if (func) {
  55. Func ();
  56. }
  57. }
  58. }
  59. }, 30);
  60. }
  61. Summary of
motion frameMotion frame Evolution Process Framework Change startmove (Element) movement Startmove (Element,itarg      ET) uniform--&gt; buffer--&gt; Startmove (ELEMENT,ATTR,ITARGRT) arbitrary value startmove (Element,attr,itargrt,func) Chain Motion Startmove (ELEMENT,JSON,FUNC) multi-value (simultaneous)--&gt; Perfect motion frame

Related Article

Cloud Intelligence Leading the Digital Future

Alibaba Cloud ACtivate Online Conference, Nov. 20th & 21st, 2019 (UTC+08)

Register Now >

Starter Package

SSD Cloud server and data transfer for only $2.50 a month

Get Started >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.