簡體   English   中英

如何用javascript制作動畫

[英]how to make animation with javascript

我的任務是使用JavaScript制作動畫。
基本上,我有兩個正方形(紅色和黃色)和兩個按鈕(按鈕1和按鈕2)。

當我單擊button1 ,紅色方塊從(左上角)到(右下角)。

我需要制作另一個按鈕( button2 ),以便當我單擊它時,我需要紅色方塊返回到開頭。

我需要它做相反的移動(從右下角移到左上角)。

我應該在第二個功能上做哪些更改?

這是代碼

 function myMove1() { var elem = document.getElementById("animate"); var pos = 0; var id = setInterval(frame, 5); function frame() { if (pos == 350) { clearInterval(id); } else { pos++; elem.style.top = pos + 'px'; elem.style.left = pos + 'px'; } } } function myMove2() { } 
 #container { width: 400px; height: 400px; position: relative; background: yellow; } #animate { width: 50px; height: 50px; position: absolute; background-color: red; } 
 <p> <button onclick="myMove1()">button 1</button> <button onclick="myMove2()">button 2</button> </p> <div id="container"> <div id="animate"></div> </div> 

我將假設老師正在嘗試教授基本的javascript,並告訴您如何使用您提供的部分解決這個問題。

也就是說,您的評論者是正確的,requestAnimationFrame是此處的正確工具。 此外,您間隔的5毫秒延遲確實很短(125fps)。 如果您輸入此數字,建議將其更改為16,大約為60fps。

  // We want each function to be able to see these vars. var pos = 0; // Either -1, 0, or 1, depending on if were moving forward, backwards or // stopped. var direction = 0; // This var now serves dual purpose, either its a number which is the // interval id or its falsy, which we can use to understand the animation // has stopped. var id = null; // Doing this here, will save the browser from having to redo this step on // each frame. var elem = document.getElementById("animate"); // Render the elem to the correct starting location. elem.style.top = pos + 'px'; elem.style.left = pos + 'px'; // A single animation function. function frame() { // Assume we are heading for 350. var goal = 350 if (direction < 0) { // unless the goal is -1, when the goal is zero. goal = 0 } if (pos != goal) { pos += direction; elem.style.top = pos + 'px'; elem.style.left = pos + 'px'; } else { // Reset all the shared vars. direction = 0; clearInterval(id); id = null; } } function myMove1() { if (id) { clearInterval(id) } direction = 1; id = setInterval(frame, 5); } function myMove2() { if (id) { clearInterval(id) } direction = -1; id = setInterval(frame, 5); } 
  #animate { position: absolute; width: 10px; height: 10px; background-color: red; } 
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <p> <button onclick="myMove1()">button 1</button> <button onclick="myMove2()">button 2</button> </p> <div id="container"> <div id="animate"></div> </div> </body> </html> 

您要問的很簡單:采用您已經編寫的函數並更改pos的增量方向。 唯一的區別是您需要分別跟蹤xy坐標,因為它們沿相反的方向移動。 我用這個對象初始化到盒子的開始位置:

pos = {x: 350, y: 0};

 function myMove1() { var elem = document.getElementById("animate"); var pos = 0; var id = setInterval(frame, 5); function frame() { if (pos == 350) { clearInterval(id); } else { pos++; elem.style.top = pos + 'px'; elem.style.left = pos + 'px'; } } } function myMove2() { var elem = document.getElementById("animate"); var pos = {x: 350, y: 0}; var id = setInterval(frame, 5); function frame() { if (pos.y >= 350 || pos.x <= 0) { clearInterval(id); } else { pos.x--; pos.y++; elem.style.top = pos.y + 'px'; elem.style.left = pos.x + 'px'; } } } 
 #container { width: 400px; height: 400px; position: relative; background: yellow; } #animate { width: 50px; height: 50px; position: absolute; background-color: red; } 
 <p> <button onclick="myMove1()">button 1</button> <button onclick="myMove2()">button 2</button> </p> <div id="container"> <div id="animate"></div> </div> 

但是,這些函數不能在沒有參數的情況下重復使用。 該代碼是WET (將所有內容寫兩次)。 動畫很脆弱,因為每次單擊都會創建新的超時(您可以向按鈕發送垃圾郵件,並觀察其崩潰)。 動畫中的實體沒有狀態。 如果要更改位置或添加另一個框,則必須重新編寫並復制所有代碼。

考慮到這一點,這里的說明有點改進版本,回味無窮的草圖。 函數和對象更為通用,不需要為您決定添加的新動作而重寫。 Box類隨時間跟蹤實體狀態。 requestAnimationFrame()用於立即更新和繪制屏幕上的所有實體,從而避免了setTimeout的許多問題。

 const lerp = (v0, v1, t) => (1 - t) * v0 + t * v1; const dist = (a, b) => ((ax - bx) ** 2 + (ay - by) ** 2) ** 0.5; class Box { constructor(elem, pos, size, color, speed) { this.elem = elem; this.speed = speed; this.from = this.to = this.pos = pos; this.t = 0; this.elem.style.position = "absolute"; this.elem.style.background = color; this.elem.style.height = `${size}px`; this.elem.style.width = `${size}px`; this.elem.style.top = `${this.pos.y}px`; this.elem.style.left = `${this.pos.x}px`; } move(to) { this.from = {x: this.pos.x, y: this.pos.y}; this.to = {x: to.x, y: to.y}; this.t = 0; } update() { if (dist(this.pos, this.to) > 1) { this.pos.x = lerp(this.from.x, this.to.x, this.t); this.pos.y = lerp(this.from.y, this.to.y, this.t); this.elem.style.top = `${this.pos.y}px`; this.elem.style.left = `${this.pos.x}px`; this.t += this.speed; } } } const data = [ {color: "red", pos: {x: 0, y: 0}, size: 10}, {color: "yellow", pos: {x: 350, y: 0}, size: 10}, ]; const elems = document.getElementsByClassName("box"); const boxes = []; for (let i = 0; i < elems.length; i++) { boxes.push(new Box(elems[i], data[i].pos, data[i].size, data[i].color, 0.01)); } function myMove1() { boxes[0].move({x: 350, y: 350}); boxes[1].move({x: 0, y: 350}); } function myMove2() { boxes[0].move({x: 0, y: 0}); boxes[1].move({x: 350, y: 0}); } (function render() { boxes.forEach(e => e.update()); requestAnimationFrame(render); })(); 
 <p> <button onclick="myMove1()">button 1</button> <button onclick="myMove2()">button 2</button> </p> <div id="container"> <div class="box"></div> <div class="box"></div> </div> 

最后,考慮使用CSS動畫JS畫布動畫框架來完成此類任務; 這些工具將抽象出動畫涉及的許多數學和狀態表示。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM