簡體   English   中英

JavaScript Canvas 同時移動和動畫顏色

[英]JavaScript Canvas moving and animating color at the same time

我的腳本正在為球顏色的變化設置動畫。 1 完整序列需要 1 秒並使用漸變將顏色從綠色更改為藍色。 我正在嘗試添加一個move()方法來移動球。

但是我有一個問題,在哪里執行我的move()方法。 現在球移動的動畫是在顏色的動畫中執行的,但它不應該是。 顏色應該有不同的變化,球應該是無限移動的。 我希望球無限移動,顏色的變化必須像現在一樣需要 1 秒。

我這樣做對嗎?

<-- 編輯-我將間隔更改為 2000 毫秒,只是為了更好地可視化問題(球的移動停止但不應該)

 var canvas = document.querySelector('canvas'); var c = canvas.getContext('2d'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; var i = 0; var ec; var direction = 0; var x = 100; var dx = 10; var y = 100; var radius = 100; function move() { if(x + radius > window.innerWidth || x - radius < 0) { dx = -dx; } x += dx; } function animate() { c.clearRect(0, 0, innerWidth, innerHeight) move(); var gradient = c.createLinearGradient(0, 0, 170, 0); ec = 255 - i; gradient.addColorStop(1, "rgba(" + 0 + "," + i + "," + ec + ")", 1); c.fillStyle = gradient; c.beginPath(); c.arc(x, y, radius, 0, 2 * Math.PI); c.fill(); console.log(i, ec); if(i == 255) direction = 1; if(direction == 1 && i == 0) direction = 2; if(direction == 0 ) i+=5; else if(direction == 1 && direction != 2) i -= 5; if(direction != 2) requestAnimationFrame(animate); } setInterval(function draw() { direction = 0; animate(); }, 2000);
 canvas { border: 1px solid black; } body { margin: 0; }
 <canvas></canvas>

我讓一切都按預期工作。 但它很復雜,有什么辦法讓它更簡單嗎? 有人可以教我如何使用片段嗎?

 var canvas = document.querySelector('canvas'); var c = canvas.getContext('2d'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; var i = 0; var ec; var direction = 0; var x = 300; var y = 300; var radius = 200; var speed = 5; var dateDiff; var date1; var executedTimer = false; var executedColor = false; function draw() { c.clearRect(0, 0, innerWidth, innerHeight) c.beginPath(); c.arc(x, y, radius, 0, 2 * Math.PI); c.fill(); } function move() { if(x + radius > window.innerWidth || x - radius < 0) { speed = -speed; } x += speed; } function color() { var gradient = c.createLinearGradient(0, 0, 170, 0); ec = 255 - i; gradient.addColorStop(1, "rgba(" + 0 + "," + i + "," + ec + ")", 1); c.fillStyle = gradient; //console.log(i, ec); if(i == 255) direction = 1; if(direction == 1 && i == 0) direction = 2; if(direction == 0 ) i += 5; else if(direction == 1 && direction != 2) i -= 5; } function timerStart() { date1 = new Date(); executedTimer = true; } function timerCheck() { var date2 = new Date(); dateDiff = Math.abs(date1 - date2); if(dateDiff >= 1000)date1 = date2; } function animate() { draw(); move(); if(executedTimer == false) timerStart(); if(executedColor == false) { executedColor = true; color(); } if(dateDiff < 1000) color(); if(dateDiff >= 1000 && direction == 2) { i = 0; direction = 0; //console.log(dateDiff); color(); } timerCheck(); requestAnimationFrame(animate); } requestAnimationFrame(animate);
 canvas { border: 1px solid black; } body { margin: 0; }
 <canvas></canvas>

將位置和顏色視為兩個不同的組件,每個組件都有自己的持續時間和更新方法。

然后開始一個動畫循環,您將在其中

  • 更新顏色組件
  • 更新位置組件
  • 繪制場景

為了確保您的動畫持續您想要的持續時間,請使用增量時間,這將讓您知道相對於動畫開始的位置。
這避免了使用不同刷新率的監視器出現問題(簡單地將一個值增加一個固定的量會使您的對象在 120Hz 監視器上的移動速度比在 60Hz 監視器上快兩倍,通常不是您想要的),並且它也允許不關心關於您的動畫在屏幕外時被瀏覽器暫停的事實。

 { const canvas = document.querySelector('canvas'); const ctx = canvas.getContext('2d'); const w = canvas.width = window.innerWidth; const h = canvas.height = window.innerHeight; const radius = Math.min( w, h ) / 3; const color = { duration: 1000, update( elapsed ) { const delta = (elapsed % this.duration) / this.duration; const direction = (elapsed % (this.duration * 2)) - this.duration; const val = (direction < 0) ? 255 - (delta * 255) : delta * 255 ; this.val = `rgba(0, ${ val }, ${ 255 - val })`; } }; const position = { duration: 3000, y: h / 2, update( elapsed ) { const delta = (elapsed % this.duration) / this.duration; const direction = (elapsed % (this.duration * 2)) - this.duration; this.x = direction < 0 ? delta * w : w - (delta * w); } }; function draw() { ctx.clearRect( 0, 0, w, h ); ctx.beginPath(); ctx.arc( position.x, position.y, radius, 0, Math.PI *2 ); ctx.fillStyle = color.val; ctx.fill(); } // We record the time we started the animation // We will base our time relative animation on that const start = performance.now(); function anim( timestamp ) { const elapsed = timestamp - start; color.update( elapsed ); position.update( elapsed ); draw(); requestAnimationFrame( anim ); } requestAnimationFrame( anim ); }
 body { margin: 0; }
 <canvas></canvas>

當然,如果您要擁有很多這樣的雙向動畫,您可以編寫一個輔助函數來根據經過的時間獲取值:

 { const canvas = document.querySelector('canvas'); const ctx = canvas.getContext('2d'); const w = canvas.width = window.innerWidth; const h = canvas.height = window.innerHeight; const radius = Math.min( w, h ) / 3; function getValueAtTime( elapsed, duration, max_val ) { const delta = (elapsed % duration) / duration; const direction = (elapsed % (duration * 2)) - duration; const val = delta * max_val; return direction < 0 ? val : max_val - val; } const color = { duration: 1000, update( elapsed ) { const val = getValueAtTime( elapsed, this.duration, 255 ); this.val = `rgba(0, ${ val }, ${ 255 - val })`; } }; const position = { duration: 3000, y: h / 2, update( elapsed ) { this.x = getValueAtTime( elapsed, this.duration, w ); } }; function draw() { ctx.clearRect( 0, 0, w, h ); ctx.beginPath(); ctx.arc( position.x, position.y, radius, 0, Math.PI *2 ); ctx.fillStyle = color.val; ctx.fill(); } // We record the time we started the animation // We will base our time relative animation on that const start = performance.now(); function anim( timestamp ) { const elapsed = timestamp - start; color.update( elapsed ); position.update( elapsed ); draw(); requestAnimationFrame( anim ); } requestAnimationFrame( anim ); }
 body { margin: 0; }
 <canvas></canvas>

暫無
暫無

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

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