I'm trying to draw a transparent circle on the HTML Canvas. Here is the code:
const canvas = document.querySelector('#canvas');
let ctx = canvas.getContext('2d');
canvas.width = 700;
canvas.height = 700;
ctx.beginPath();
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'destination-out';
ctx.clearRect(50, 50, 200, 200);
ctx.beginPath();
ctx.fillRect(50, 50, 200, 200);
ctx.moveTo(350, 150);
ctx.beginPath();
ctx.arc(350, 150, 80, 0, 2 * Math.PI, false);
ctx.closePath();
ctx.fill();
I was able to make the rectangle transparent with globalCompositeOperation set to destination-out but it failed to make the circle fully transparent.
Here is what MDN says about destination-out operation,
The existing content is kept where it doesn't overlap the new shape.
The circle has still some opaque color applied to it. How to make it fully transparent?
Here is the live demo.
Unable to understand what's wrong with the code. Any help would be appreciated.
You are using beginpath methods but the directives you use aren't paths.
The fully transparent rectangle is created by the clearRect and not by the fillRect method.
So you should set fillStyle to white and then the code works.
const canvas = document.querySelector('#canvas');
let ctx = canvas.getContext('2d');
canvas.width = 600;
canvas.height = 400;
ctx.fillStyle = 'rgba(0, 0, 0, .5)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'destination-out';
ctx.fillStyle = 'rgba(255, 255, 255, 1)';
ctx.fillRect(25, 25, 150, 150);
ctx.arc(275, 100, 60, 0, 2 * Math.PI, false);
ctx.fill();
body {
background-color: skyblue;
position: relative;
}
img, #canvas {
position: absolute;
}
<body>
<img src="https://images.unsplash.com/photo-1635315850978-44cd0b237006?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1770&q=80" alt="" width=600 height=390>
<canvas id="canvas"></canvas>
</body>
Related
This is my code:
const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");
function draw() {
context.fillStyle = "rgb(200, 0, 0)";
context.fillRect(50, 50, 0, 0);
};
draw();
When I run it, I get no errors but it doesn't add the squares to the canvas. Can someone tell me why this happens and how to fix it?
Your second Rectangle does not have a height and width.
the function has the parameters x, y, width, height -> fillRect(x, y, width, height).
Your line context.fillRect(50, 50, 0, 0); creates a box with width and height of 0 at 50px from x and y.
const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");
const settings = {x: 50, y: 50, height: 50, width: 50};
function draw() {
if (ctx) {
ctx.fillStyle = "rgb(0, 200, 0)";
ctx.fillRect(settings.x, settings.y, settings.width, settings.height);
ctx.fillStyle = "rgb(200, 0, 0)";
ctx.fillRect(0, 0, 50, 50);
};
};
draw();
<canvas id="myCanvas"></canvas>
I have two half-ellipses and I'm trying fill the space between them. For whatever reason the "fill" is getting "twisted" in the middle:
const canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = canvas.height = 300;
ctx.ellipse(150, 0, 150, 90, 0, 0, Math.PI);
ctx.ellipse(150, 200, 150, 90, 0, 0, Math.PI);
ctx.fillStyle = "lightgreen";
ctx.fill();
ctx.stroke();
<canvas id="canvas"></canvas>
Any ideas how to make it fill so it's like a cylinder (without far side on top)
I guess all it need was rotate one of the ellipses and draw it in reverse:
const canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = canvas.height = 300;
ctx.ellipse(150, 0, 150, 90, 0, 0, Math.PI);
ctx.ellipse(150, 200, 150, 90, Math.PI, 0, Math.PI, true); //changed
ctx.fillStyle = "lightgreen";
ctx.fill();
ctx.stroke();
<canvas id="canvas"></canvas>
This question already has answers here:
Canvas flashlight effect
(1 answer)
Efficient HTML5 Canvas Glow Effect without shape
(1 answer)
HTML canvas spotlight effect
(3 answers)
Closed 4 years ago.
I want to get the effect "flash/flashlight". But with the ability to merge multiple effects.
I draw one effect like this, but can not merge them.
function createCircle( x, y ) {
var gradient = context.createRadialGradient(x, y, 0, x, y, 100);
gradient.addColorStop(0, 'rgba(0, 0, 0, 0)');
gradient.addColorStop(1, 'rgba(0, 0, 0, 1)');
context.fillStyle = gradient;
context.fillRect(0, 0, width, height);
}
I tried different types of "globalCompositeOperation". But the result was still bad.
I attached an image (example) with the desired result.
Is this what you need? I've used globalCompositeOperation as you intended. please take a look at this codepen example
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
let cw = canvas.width = 600,
cx = cw / 2;
let ch = canvas.height = 300,
cy = ch / 2;
let img = document.getElementById("img");
function grd( x, y ) {
let gradient = ctx.createRadialGradient(x, y, 0, x, y, 130);
gradient.addColorStop(.5, 'rgba(0, 0, 0, 1)');
gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
return gradient;
}
let c1={x:220,y:150}
let c2={x:380,y:150}
ctx.fillStyle = grd(c1.x,c1.y);
ctx.beginPath();
ctx.arc(c1.x, c1.y, 220, 0, 2*Math.PI);
ctx.fill();
ctx.fillStyle = grd(c2.x,c2.y);
ctx.beginPath();
ctx.arc(c2.x,c2.y, 220, 0, 2*Math.PI);
ctx.fill();
ctx.globalCompositeOperation = "source-in";
ctx.drawImage( img, -50, -50 ,cw, cw );
body {
overflow: hidden;
}
canvas {
background-color: #000;
display: block;
}
<canvas id="canvas">
<img src="your_image.jpg" id="img" />
</canvas>
Clearing ctx.fillStyle after drawing a filled rectangle doesn't work...
I've tried:
ctx.globalCompositeOperation = 'destination-out';
ctx.clearRect(0, 0, canvas.width, canvas.height); Clearing the canvas itself
ctx.fillStyle = "rgba(255, 255, 255, 1)"; Setting it to white
ctx.fillStyle = null; Maybe nulling it will work...
But I got no result other than reDrawing its previous value and not the new one.
JsFiddle: https://jsfiddle.net/q9ub0r9z/1/
Use ctx.fillRect() instead, see updated fiddle: https://jsfiddle.net/q9ub0r9z/2/
You use .fillRect function instead of .rect
function showRed(){
ctx.fillStyle = "rgba(255,0,0,1)";
ctx.fillRect(0,0, 200, 200);
}
function showGreen(){
ctx.fillStyle = "rgba(0,255,0,1)";
ctx.fillRect(200,0, 200, 200);
}
function showBlue(){
ctx.fillStyle = "rgba(0,0,255,1)";
ctx.rect(200,200, 200, 200);
}
function showBlack(){
ctx.fillStyle = "rgba(0,0,0,1)";
ctx.rect(200,200, 400, 400);
}
I'm making a game with javascript canvas. I'm drawing all the game elements, like the player, blocks and lines, but I don't want you to see all that. Instead want the whole screen to be black, expect for in some places where there is lightsources. I don't need any shadows, just a circle on the screen that is lit up with a radial gradient. I am able to achieve this for one lightsource by adding a transparent gradient after I have drawn everything else, like this: (imagine the red rectangle to be all the things in the game)
//Drawing all the game elements
ctx.fillStyle = "red";
ctx.fillRect(100, 100, 400, 300);
//adding the darkness and the lightsources
var grd = ctx.createRadialGradient(150, 100, 5, 150, 100, 100);
grd.addColorStop(0, "transparent");
grd.addColorStop(1, "black");
ctx.fillStyle = grd; ctx.fillRect(0, 0, 600, 400);
JSFiddle
But how can I achieve this with multiple lightsources? The technique showed won't work.
I have tried using the Illuminated.js api, but that was incredibly slow, and I don't need anything of the shadows and all that fancy stuff, just a circle where you can see the game.
Here's an example of my approach - create black&white mask and multiply the base with it:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
//Drawing all the game elements
ctx.fillStyle = "red";
ctx.fillRect(100, 100, 400, 300);
//adding the darkness and the lightsources
function addlight(ctx, x, y) {
var grd = ctx.createRadialGradient(x, y, 10, x, y, 150);
grd.addColorStop(0, "white");
grd.addColorStop(1, "transparent");
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 600, 400);
}
var buffer = document.createElement('canvas');
buffer.width = 600;
buffer.height = 400;
b_ctx = buffer.getContext('2d');
b_ctx.fillStyle = "black";
b_ctx.fillRect(0, 0, 600, 400);
addlight(b_ctx, 150, 100);
addlight(b_ctx, 350, 200);
addlight(b_ctx, 450, 250);
ctx.globalCompositeOperation = "multiply";
ctx.drawImage(buffer, 0, 0);
<canvas id="myCanvas" width="600" height="400" style="border:1px solid #d3d3d3;">