2017-05-28 156 views
1
//read where the click is made 
$(document).click(function(e) { 
    var x = event.clientX; 
    var y = event.clientY; 
    drawCircle(x,y); 
}); 


//array used for random colors of circles 
var color = ["#E72B8E", "#238A9B", "#F05C3F"]; 

//setting canvas and its size 
var c = document.getElementById("canvas"); 

c.width = window.innerWidth; 
c.height = window.innerHeight; 

var ctx = c.getContext("2d"); 

//function to draw circles 
function drawCircle(x,y){ 

    //randomly chose color and size for circles 
    var randC = color[Math.floor(Math.random() * color.length)]; 
    var randS = Math.floor(Math.random() * (80 - 30)) + 30; 

    //draw circles 
    ctx.beginPath(); 
    ctx.arc(x,y,randS,0,2*Math.PI); 

    //make gradient for random color and fill 
    var grd=ctx.createLinearGradient(0,0,170,0); 
    grd.addColorStop(0,randC); 
    grd.addColorStop(1,"transparent"); 

    ctx.fillStyle=grd; 
    ctx.fill(); 
    ctx.closePath(); 
} 

所以,我試圖做的是每次單擊畫布並使其掉下時畫一個圓圈。使用JavaScript在HTML5畫布上繪製倍數下降圓圈

我的第一個問題是我被困在如何讓我的圈子留在畫布上。每次點擊時,我都會畫出一個新的圓圈,但之前繪製的圓圈已經消失。所以,我試圖在drawCircle函數外面設置畫布線,所以無論何時調用函數,它都不會重置畫布。現在點擊根本不會畫圓。功能之外的這些線是否會影響某些內容?

我的第二個問題是我想要有從100%顏色到透明的漸變圓,但似乎漸變是相對於畫布中圓的位置。例如,如果我點擊框架的左側邊緣,漸變效果會以我想要的方式完美呈現,但隨着漸變效果的變化,漸變的透明部分會變得更大,一旦我點擊了漸變的中間部分框架,我根本看不到這個圓圈。而漸變的透明部分對我來說似乎很黑。我能做些什麼來解決它?

最後,一旦我完全搞清楚如何以我想要的方式繪製多個圓,我最終會讓它們像雪花一樣掉下來。有沒有可以促進它的功能?

非常感謝!

回答

2

每次渲染可能較慢的圓時,您都可以爲圓的位置創建一個新的漸變。或者,您可以在位置0,0和固定半徑上創建漸變,然後使用變換將漸變和圓移動到正確的位置。

要爲許多對象創建動畫,請創建它們的數組,循環顯示每個項目以更新位置,然後進行繪製。你可以做更新並繪製相同的功能,但是當事情變得更加複雜時,最好將更新和繪製分開。

// get the 2D context 
 
const ctx = canvas.getContext("2d"); 
 

 
// listen to click events adding ball for each click 
 
canvas.addEventListener("click",(e)=>{ circles.add(e.pageX,e.pageY,20) }); 
 

 
// define a gradient for circles 
 
const gradientRadius = 10; 
 
const grad = ctx.createRadialGradient(0,0,0,0,0,gradientRadius); // gradient 10 pixels radius at 0,0 
 
grad.addColorStop(1,"rgba(255,0,0,0)"); 
 
grad.addColorStop(0,"rgba(0,0,0,1)"); 
 

 
const gravity = 0.9; // gravity acceleration 
 

 
// draws a circle using grad (above) 
 
function drawCircle(x,y,radius){ 
 
    var scale = radius/gradientRadius; 
 
    ctx.fillStyle = grad; 
 
    ctx.setTransform(scale, 0, 0, scale, x, y); 
 
    ctx.beginPath(); 
 
    ctx.arc(0, 0, radius/scale, 0, Math.PI * 2); 
 
    ctx.fill(); 
 
} 
 

 
// this object handles all circles. Circles are stored in the array circles.items 
 
// the function update and draw both return the circles object so that they 
 
// can be chained. 
 
const circles = { 
 
    items : [], // array of circles 
 
    add(x,y,radius){ 
 
     var circle; 
 
     circles.items.push(circle = { 
 
      x,y,radius, 
 
      dx : 0, // delta x and y (movement per frame 
 
      dy : 0, 
 
     }); 
 
     return circle; 
 
    }, 
 
    update(){ 
 
     var i,c; 
 
     for(i = 0; i < circles.items.length; i++){ 
 
      c = circles.items[i]; // get the circle 
 
      c.dy += gravity; 
 
      c.x += c.dx; 
 
      c.y += c.dy; 
 
      // simulate bounce.. This is the most basic, search SO for better methods 
 
      if(c.y + c.radius > ctx.canvas.height){ 
 
       c.y = ctx.canvas.height - c.radius; 
 
       c.dy = -Math.abs(c.dy); // window resize may cause ball to be moving up when 
 
             // it hits the bottom so need to ensure the bounce is 
 
             // away from the bottom with Math.abs 
 
      } 
 
     } 
 
     return circles; 
 
    }, 
 
    draw(){ 
 
     var i,c; 
 
     for(i = 0; i < circles.items.length; i++){ 
 
      c = circles.items[i]; // get the circle 
 
      drawCircle(c.x,c.y,c.radius); 
 
     } 
 
     return circles; 
 
    } 
 
} 
 

 
// main animation loop called once every 1/60th second (if possible) 
 
// It checks if the widow size matches the canvas and will resize it 
 
// if not. 
 
// Then clears the canvas and updates and draws the circles. 
 
// Then requests the next animation frame 
 
function mainLoop(time){ 
 
    if(canvas.width !== innerWidth || canvas.height !== innerHeight){ // resize canvas if window size has changed 
 
     canvas.width = innerWidth; 
 
     canvas.height = innerHeight; 
 
    } 
 
    ctx.setTransform(1,0,0,1,0,0); // set default transform 
 
    ctx.clearRect(0,0,canvas.width,canvas.height); // clear the canvas 
 
    circles.update().draw(); 
 
    requestAnimationFrame(mainLoop); 
 
} 
 
requestAnimationFrame(mainLoop);
canvas { 
 
    position : absolute; 
 
    top : 0px; 
 
    left : 0px; 
 
}
Click to add circle. 
 
<canvas id=canvas></canvas>