2017-05-28 127 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>