I am drawing a canvas.
I simplified my code.
There is a transparent circle.
The background is rgba 0,0,0,0.5.
I'd like to add "shadowblur" for the transparent circle. However, it's fail.
Is it possible?
I have another logic:
- Create one circle with linear-gradient (rgba 0,0,0,0.5, transparent)
However, it seems no good.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div >
<canvas id="myCanvas"></canvas>
</div>
<style>
.Preloader {
background-color: #7bf;
}
</style>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
class ball {
constructor(x, y) {
this.position = {
x: x,
y: y
}
this.r = 100
}
draw() {
ctx.beginPath();
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, c.width, c.height);
ctx.fill();
ctx.closePath();
ctx.save();
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.r, 0, 2 * Math.PI, false);
ctx.clip();
ctx.clearRect(0, 0, c.width, c.height);
ctx.shadowBlur = 0;
ctx.closePath();
ctx.restore();
}
update() {
this.draw()
this.position.x
this.position.y
}
}
var Ball = new ball(c.width / 2, c.height / 2)
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, c.width, c.height);
Ball.update();
};
animate();
</script>
</body>
</html>
CodePudding user response:
If you mean that you want the edges of the clipping-area to be smoother, then you can use compositing to use any bitmap as a mask:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
class ball {
constructor(x, y) {
this.position = {
x: x,
y: y
}
this.r = 100
}
draw() {
// fillRect doesn't need beginPath(), and it does fill()
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, c.width, c.height);
// closePath encloses the current subpath
// it doesn't "end" the path declaration
// beginPath does that
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.r, 0, 2 * Math.PI, false);
// we use compositing to create our hole, with shadow:
ctx.globalCompositeOperation = "destination-out";
ctx.shadowBlur = 30;
ctx.shadowColor = "black";
ctx.fillStyle = 'black';
ctx.fill();
// restore
ctx.shadowBlur = 0;
ctx.globalCompositeOperation = "source-over";
}
update() {
this.draw()
this.position.x
this.position.y
}
}
var Ball = new ball(c.width / 2, c.height / 2)
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, c.width, c.height);
Ball.update();
};
animate();
.Preloader {
background-color: #7bf;
}
<div >
<canvas id="myCanvas"></canvas>
</div>
This would also work with CanvasGradient instead of shadowBlur:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
class ball {
constructor(x, y) {
this.position = {
x: x,
y: y
}
this.r = 100
}
draw() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, c.width, c.height);
ctx.globalCompositeOperation = "destination-out";
ctx.fillStyle = ctx.createRadialGradient(this.position.x, this.position.y, this.r, this.position.x, this.position.y, 0);
ctx.fillStyle.addColorStop(0, "transparent");
ctx.fillStyle.addColorStop(.25, "black");
ctx.fillRect(0, 0, c.width, c.height);
// restore
ctx.globalCompositeOperation = "source-over";
}
update() {
this.draw()
this.position.x
this.position.y
}
}
var Ball = new ball(c.width / 2, c.height / 2)
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, c.width, c.height);
Ball.update();
};
animate();
.Preloader {
background-color: #7bf;
}
<div >
<canvas id="myCanvas"></canvas>
</div>
Or even in Chrome and Firefox by using CSS blur filters:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
class ball {
constructor(x, y) {
this.position = {
x: x,
y: y
}
this.r = 100
}
draw() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, c.width, c.height);
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.r, 0, 2 * Math.PI, false);
// we use compositing to create our hole, with shadow:
ctx.globalCompositeOperation = "destination-out";
ctx.filter = "blur(15px)";
ctx.fill();
// restore
ctx.filter = "none";
ctx.globalCompositeOperation = "source-over";
}
update() {
this.draw()
this.position.x
this.position.y
}
}
var Ball = new ball(c.width / 2, c.height / 2)
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, c.width, c.height);
Ball.update();
};
animate();
.Preloader {
background-color: #7bf;
}
<div >
<canvas id="myCanvas"></canvas>
</div>