//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();
}
因此,我要做的是每次在 Canvas 上单击并使其落下时绘制一个圆圈。
我的第一个问题是我卡在如何让我的圈子留在 Canvas 上。每次点击,我都会画一个新的圆,但是之前画的圆没有了。因此,我尝试在 drawCircle 函数之外添加用于设置 Canvas 的行,因此它不会在函数调用时重置 Canvas 。现在点击根本不会画一个圆圈。将这些行放在函数之外会影响什么吗?
我的第二个问题是我想要渐变圆圈,从 100% 颜色到透明,但渐变似乎是相对于圆圈在 Canvas 中的位置。例如,如果我点击框架的左边缘,渐变会完全按照我想要的方式出现,但随着它变得更右,渐变的透明部分会变大,一旦我点击框架的中间框架,我根本看不到圆圈。渐变的透明部分对我来说似乎有点黑。我该怎么做才能修复它?
最后,一旦我完全弄清楚如何按照我想要的方式绘制多个圆圈,我最终会让它们像雪花一样落下。有没有可以促进它的功能?
非常感谢!
最佳答案
每次渲染一个可能很慢的圆时,您都可以创建一个新的渐变设置到圆的位置。或者您可以在位置 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>
关于javascript - 使用 JavaScript 在 HTML5 canvas 上绘制多个下降的圆圈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44223389/