JavaScript canvas arc small angle ignore - javascript

For some reason when using small angle on arc function in canvas 2d context
It is not shown, even though angle is about 1deg, which is not even that small
How does one fix or overcomes this issue? (I'm using chrome, just in case)
Example:
var c = document.getElementById("canvas").getContext("2d");
//THIS IS SHOWN
c.beginPath();
c.moveTo(200, 200);
c.arc(200, 200, 200, 0, 0.023);
c.lineTo(200, 200);
c.fill();
//THIS IS NOT SHOWN???
c.beginPath();
c.moveTo(200, 200);
c.arc(200, 200, 200, Math.PI, Math.PI + 0.022); //change 22 to 23 to "fix"
c.lineTo(200, 200);
c.fill();
#canvas {
background-color: lightblue;
}
<canvas id="canvas" width="400" height="400"></canvas>

Related

Canvas - How to fill a square with two colors using createLinearGradient()?

I'm having problems making a square that has two colors in it. I found the functions createLinearGradient and addColorStop but it only fills the square with one color, which is blue.
How exactly do I fill this square properly? I'm having trouble understanding the parameters of the function it seems.
var c = canvas.getContext('2d'); // context object
var grad = c.createLinearGradient(0, 0, 0, 100);
grad.addColorStop(0, "red"); //
grad.addColorStop(1, "blue"); //
// Fill a square:
c.fillStyle = grad;
c.fillRect(100, 100, 100, 100);
fillStyles, like gradients and patterns are drawn relatively to the context's matrix, so your gradient is actually drawn above your rect:
var c = canvas.getContext('2d'); // context object
var grad = c.createLinearGradient(0, 0, 0, 100);
grad.addColorStop(0, "red"); //
grad.addColorStop(1, "blue"); //
c.fillStyle = grad;
// show the whole gradient
c.fillRect(0, 0, canvas.width, canvas.height);
// OP's square
c.strokeRect(100, 100, 100, 100);
<canvas id="canvas" height="300"></canvas>
To fix that you have two choices:
Set your gradients params correctly from the beginning:
var c = canvas.getContext('2d');
// move the y1 and y2 values by 100
var grad = c.createLinearGradient(0, 100, 0, 200);
grad.addColorStop(0, "red"); //
grad.addColorStop(1, "blue"); //
// Fill a square:
c.fillStyle = grad;
c.fillRect(100, 100, 100, 100);
<canvas id="canvas" height="300"></canvas>
Translate your context's matrix just before calling fill(). Indeed, path drawing and filling can be done on separate matrice.
var c = canvas.getContext('2d');
var grad = c.createLinearGradient(0, 0, 0, 100);
grad.addColorStop(0, "red"); //
grad.addColorStop(1, "blue"); //
c.fillStyle = grad;
// draw the path
c.rect(100, 100, 100, 100);
// change the filling matrix
c.translate(100, 100);
c.fill();
// reset the matrix
c.setTransform(1,0,0,1,0,0);
<canvas id="canvas" height="300"></canvas>
Your values for createLinearGradient were outside of the rectangle you were drawing in.
const canvas = document.getElementById('one');
const c = canvas.getContext('2d');
const grad = c.createLinearGradient(100, 100, 200, 200);
grad.addColorStop(0, "red");
grad.addColorStop(1, "blue");
c.fillStyle = grad;
c.fillRect(100, 100, 100, 100);
canvas {
outline: 1px solid black
}
<canvas id="one" width="300" height="300"></canvas>

deleting a circle made in HTML5 Canvas [duplicate]

This question already has answers here:
Erasing previously drawn lines on an HTML5 canvas
(5 answers)
Closed 4 years ago.
I've made a canvas where I draw shapes on. When I want to delete them, I basically create the same shape again but it's white, so I don't delete any other shapes (saved the x and y coordinate, so nothing to worry there)
ctx.fillStyle="#FFFFFF";
ctx.strokeStyle="#FFFFFF";
ctx.beginPath();
ctx.arc(x, y, 40, 0, 2 * Math.PI);
ctx.fill();
The problem is that on some shapes there is still a remaining black rest, that I can't get rid of (it's even worse on other shapes)
What Am I missing?
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(50,50 , 40, 0, 2 * Math.PI);
ctx.fill();
ctx.fillStyle="#FFFFFF";
ctx.strokeStyle="#FFFFFF";
ctx.beginPath();
ctx.arc(50,50 , 40, 0, 2 * Math.PI);
ctx.fill();
<canvas id="myCanvas" width="1000" height=600 style="border: 1px solid #000000;">
</canvas>
EDIT: https://jsfiddle.net/sfj5y091/3/
EDIT 2:
I solved this problem in the end, by completely redrawing all the shapes after one shape was deleted in the system, which even enabled the deletion of shapes that overlapped without destroying the other shape
The residue is caused by smoothing or anti-aliasing.
To draw the black circle on the initially white background, an "aura" of gray pixels is drawn at the edge of the 40-pixel-radius circle to give it a smooth appearance, and that "aura" is a tiny bit bigger than what you planned to draw.
If you then draw a white 40-pixel-radius circle on top of that, it blends the new white edge pixels with what is now a non-white background. The result is lighter gray pixels, and not white pixels.
If your only option is still to paint over old pixels, then you'll have to use a slightly bigger radius for the white circle:
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(50, 50, 40, 0, 2 * Math.PI); // radius of 40
ctx.fill();
ctx.fillStyle = "#FFFFFF";
ctx.strokeStyle = "#FFFFFF";
ctx.beginPath();
ctx.arc(50, 50, 41, 0, 2 * Math.PI); // radius of 41
ctx.fill();
<canvas id="myCanvas" width="150" height="150" style="border: 1px solid #000000;">
</canvas>
<br /> Nothing to see here ;-)
For more on anti-aliasing, see e.g. Can I turn off antialiasing on an HTML <canvas> element?
Double buffering in action
Try
step1();
setTimeout(function () {
step2();
setTimeout(function () {
step3();
}, 1000);
}, 1000);
function step1() {
clearCanvas('myCanvas1');
drawShape('myCanvas1'
,{type:"circle", strokeStyle:"#000000", fillStyle:"#000000", radious:40, x:50, y:50});
};
function step2() {
clearCanvas('myCanvas2');
showOtherCanvas('myCanvas2', 'myCanvas1');
};
function step3() {
clearCanvas('myCanvas1');
drawShape('myCanvas1'
,{type:"circle", strokeStyle:"#000000", fillStyle:"#000000", radious:40, x:50, y:50});
showOtherCanvas('myCanvas1', 'myCanvas2');
};
function drawCircle (canvasID, info) {
var canvas = document.getElementById(canvasID);
var ctx = canvas.getContext('2d');
ctx.fillStyle=info.fillStyle;
ctx.strokeStyle=info.strokeStyle;
ctx.beginPath();
ctx.arc(info.x, info.y, info.radious, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.arc(info.x, info.y, info.radious, 0, 2 * Math.PI);
ctx.stroke();
}
function showOtherCanvas(cnv1, cnv2) {
var c1 = document.getElementById(cnv1);
var c2 = document.getElementById(cnv2);
c1.style['z-index'] = 3;
c2.style['z-index'] = 1;
c1.style['z-index'] = 2;
}
function clearCanvas(canvasID) {
var canvas = document.getElementById(canvasID);
var ctx = canvas.getContext('2d');
ctx.fillStyle="#FFFFFF";
ctx.strokeStyle="#FFFFFF";
ctx.fillRect(0,0,640,400);
}
function drawShape (canvasID, info) {
switch (info.type) {
case "circle" : drawCircle(canvasID, info);
}
}
<canvas id="myCanvas2" width="640" height="400"
style="border: 1px solid #000000; position: absolute; top: 10; left: 10; z-index:1">
</canvas>
<canvas id="myCanvas1" width="640" height="400"
style="border: 1px solid #000000; position: absolute; top: 10; left: 10; z-index:2">
</canvas>
The change is so fast you won't see any flicker.

Concentric circle with random colors in JS canvas (with loop)?

I am trying to draw concentric circles with javascript canvas with a loop. The circles have to be a random color each time they are drawn. I have tried to draw the circles with the code below but it didn't work. Thanks for your help!
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
while ( i=50 ; i < 5; i=i-5 ) {
context.beginPath();
context.arc(300, 300, i, 0, 2 * Math.PI, false);
//context.fillStyle = 'green';
//context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
}
//the code below worked for one circle
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
</script>
</body>
</html>
Multiple Typos
Three typographical type errors for your consideration:
The while loop is a for loop. In
while ( i=50 ; i < 5; i=i-5 )
replace while with for
The loop condition is false, so the loop never executes after fixing 1.
for( i=50; i < 5; i=i-5)
replace i < 5 with i > 5
The circles are off canvas and can't be seen. For demonstrations purposes only, replace
context.arc(300, 300, i, 0, 2 * Math.PI, false);
with, say,
context.arc(100, 100, i, 0, 2 * Math.PI, false);
and remove, or fully comment out, the "working" code example to remove syntax errors.
A working example using a line width of 3px:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
for ( i=50 ; i > 5; i=i-5 ) {
context.beginPath();
context.arc(100, 100, i, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill()
context.lineWidth = 3;
context.strokeStyle = '#003300';
context.stroke();
}
<canvas id="myCanvas" width="578" height="200"></canvas>

Javascript canvas simple lightsource

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;">

ArcTo() not drawing arc

I've got the following HTML file:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Canvas Hello World</title>
<link href="default.css" rel="stylesheet" />
<script src="jquery-2.0.0.min.js"></script>
</head>
<body>
<h1>ArcTo</h1>
<h2>Two arcs</h2>
<canvas id="arcToNormalCanvas" width="500" height="500">HTML5 not supported
</canvas>
<hr />
<h1>Simple drawing:</h1>
<canvas id="rectangleCanvas" width="500" height="500">HTML5 not supported
</canvas>
<hr />
<script>
$(document).ready(function () {
doRectangleCanvas();
drawTwoArcs();
});
function doRectangleCanvas() {
var canvas = $('#rectangleCanvas')[0],
ctx = canvas.getContext('2d');
ctx.fillRect(50, 100, 150, 200);
ctx.stroke();
}
function drawTwoArcs() {
var canvas = $('#arcToNormalCanvas')[0],
ctx = canvas.getContext('2d');
ctx.strokeStyle = 'blue';
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.lineTo(200, 200);
ctx.moveTo(300, 200);
ctx.lineTo(400, 100);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = 'green';
ctx.moveTo(200, 200);
ctx.arcTo(200, 200, 300, 200, 100);
ctx.stroke();
}
</script>
</body>
</html>
However, the output is only the lines, with no arc!
Any ideas?
arcTo is only supported by Firefox and Safari. For full browser support, you should use arc:
ctx.beginPath();
ctx.arc(250,200,50,Math.PI,Math.PI*2,true);
ctx.strokeStyle = "green";
ctx.stroke();
Also, I have to ask, why on earth are you using $('#rectangleCanvas')[0] when you should be using document.getElementById('rectangleCanvas')?
If you want to connect the two lines, which is what I think you want, I have to change this lines...
//...
ctx.moveTo(200, 200);
ctx.arcTo(250, 250, 300, 200, 50);
// A radius of 100 is not what you want I believe.
// I used 50 for this example.
// You might want Math.cos(Math.Pi / 4) * 100, which is around 70.7
// You might also want to add here a line to actually connect with (300, 200). As if you use a too short or too long radius your arc will not be connected.
ctx.lineTo(300, 200);
ctx.stroke();
... As this function will define an arc between the two tangents not from point to point.
BTW, arcTo function is well supported in all major browsers that support the canvas element.

Categories