I'm trying to manipulate a canvas using jquery, but no matter how I set the size something comes out different than when manipulating the html directly.
var size = 100;
var halfSize = size / 2;
drawCircle1();
drawCircle2();
drawCircle3();
// behaves as expected
function drawCircle1() {
var canvas = document.getElementById('c1');
var ctx = canvas.getContext("2d");
ctx.translate(halfSize, halfSize);
ctx.arc(0, 0, halfSize, 0, 2 * Math.PI);
ctx.fill();
}
// draws a round circle, but the canvas size is not right
function drawCircle2() {
var canvas = $('#c2')
var ctx = canvas.get(0).getContext("2d");
ctx.translate(halfSize, halfSize);
ctx.arc(0, 0, halfSize, 0, 2 * Math.PI);
ctx.fill();
}
// canvas sized correctly but circle stretched
function drawCircle3() {
var canvas = $('#c3')
canvas.height(size);
canvas.width(size);
var ctx = canvas.get(0).getContext("2d");
ctx.translate(halfSize, halfSize);
ctx.arc(0, 0, halfSize, 0, 2 * Math.PI);
ctx.fill();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id='c1' width=100 height=100 style="border:solid 1px red"></canvas>
<canvas id='c2' width=100 height=100 style="border:solid 1px green"></canvas>
<canvas id='c3' style="border:solid 1px blue"></canvas>
In the second example, I think height is just misspelled.
In the third example, jQuery is setting the CSS height and width. Doing so doesn't change the actual size of the canvas, so the canvas is distorted. Instead, set the width and height attributes, as shown below.
Also see Canvas width and height in HTML5.
var size = 100;
var halfSize = size / 2;
drawCircle1();
drawCircle2();
drawCircle3();
// behaves as expected
function drawCircle1() {
var canvas = document.getElementById('c1');
var ctx = canvas.getContext("2d");
ctx.translate(halfSize, halfSize);
ctx.arc(0, 0, halfSize, 0, 2 * Math.PI);
ctx.fill();
}
// draws a round circle, but the canvas size is not right
function drawCircle2() {
var canvas = $('#c2')
var ctx = canvas.get(0).getContext("2d");
ctx.translate(halfSize, halfSize);
ctx.arc(0, 0, halfSize, 0, 2 * Math.PI);
ctx.fill();
}
// canvas sized correctly but circle stretched
function drawCircle3() {
var canvas = $('#c3')
canvas.attr('width', size);
canvas.attr('height', size);
var ctx = canvas.get(0).getContext("2d");
ctx.translate(halfSize, halfSize);
ctx.arc(0, 0, halfSize, 0, 2 * Math.PI);
ctx.fill();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id='c1' width=100 height=100 style="border:solid 1px red"></canvas>
<canvas id='c2' width=100 height=100 style="border:solid 1px green"></canvas>
<canvas id='c3' style="border:solid 1px blue"></canvas>
Related
hello i am trying to make a white circle move across a black box in javascript my circle is not showing up the big black box does but the circle does not show up i dont know why i am loading the page in google chrome here is the code
<html>
<head>
<title>paddle</title>
</head>
<body>
<canvas id="myCanvas" width="800" height="600"></canvas>
<script>
var canvas
var canvasContext
var ballX = 5
window.onload = function() {
var fps = 30;
setInterval(updateAll, 1000)
canvas = document.getElementById("myCanvas");
canvasContext = canvas.getContext("2d")
canvasContext.fillStyle = "black"
canvasContext.fillRect(0, 0, canvas.width, canvas.height)
}
function updateAll() {
ballX++
canvasContext.fillStyle = "white";
canvasContext.beginPath()
canvasContext.arc(ballX, 100, 10, 0, Math.PI*2, true);
canvasContext.stroke()
}
</script>
</body>
</html>
The problem is that you are using stroke to draw the circle but you have not set the stroke style which is by default black. So you are drawing a black circle on a black background. Hence no see circle.
Also it is best to use requestAnimationFrame to animate rather than set interval.
Example animating a circle
requestAnimationFrame(animationLoop);
const ctx = myCanvas.getContext("2d");
var ballX = 5;
var speed = 1
const radius = 10;
const fps = 30;
var frameCount = 0;
function animationLoop() {
if (frameCount % (60 / fps) === 0) {
ctx.fillStyle = "black"
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
draw();
}
frameCount ++;
requestAnimationFrame(animationLoop);
}
function draw() {
ballX = (ballX + speed) % (ctx.canvas.width + radius * 2);
ctx.strokeStyle = "white";
ctx.lineWidth = 2;
ctx.beginPath()
ctx.arc(ballX - radius, 20, 10, 0, Math.PI * 2);
ctx.stroke()
}
<canvas id="myCanvas" width="600" height="40"></canvas>
My canvas size is 300x150. I don't want to set the measurements any bigger than this because I'd like it fit on mobile phones as well. But i'd like it to scale up on bigger phones, ipads and laptops without losing resolution. The resolution on my canvas pictures have generally been bad and when it scales up it typically gets even worse. Not sure how to solve this problem. Thanks.
https://jsfiddle.net/uwakcgv0/
Here's the HTML:
<canvas width="300" height="150" id="myCanvas"></canvas>
Here's the Javascript:
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, 300, 150);
ctx.beginPath();
ctx.moveTo(20, 20);
ctx.lineTo(20, 130);
ctx.lineTo(130, 130);
ctx.stroke();
ctx.fillText("y",18,15);
ctx.fillText("x",135,132);
Increase the canvas size by any factor and then scale the canvas by the same factor (using ctx.scale()) to get the desired result.
const SCALING_FACTOR = 2;
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.canvas.width = SCALING_FACTOR * canvas.width;
ctx.canvas.height = SCALING_FACTOR * canvas.height;
ctx.scale(SCALING_FACTOR, SCALING_FACTOR);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(20, 20);
ctx.lineTo(20, 130);
ctx.lineTo(130, 130);
ctx.stroke();
ctx.fillText("y", 18, 15);
ctx.fillText("x", 135, 132);
<canvas width="300" height="150" id="myCanvas"></canvas>
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.
I've a <canvas> with an image already loaded and all the graphics coordinates needed for a crop (x, y, w, h) in an array.
What I'm trying to do is to crop the canvas directly, without a temporary other canvas to copy to/from (as suggested in other SO answers).
My idea is to:
1) Draw the selected area on the top-left corner of the canvas
2) Shrink the canvas size to the area
$('#edit').on("click", function() {
var img = $('#canvas');
var c = img[0];
var ctx = c.getContext("2d");
//var imageData = ctx.getImageData(0, 0, 100, 100);
ctx.drawImage(c, 0, 0, 100, 100, 0, 0, 100, 100);
c.width = 100;
c.height = 100;
});
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "green";
ctx.fillRect(0, 0, 350, 350);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="350" height="350"></canvas>
<input id="edit" type="button" value="Edit" />
Seems easy to me, but I'm missing something: when I execute, I get nothing https://jsfiddle.net/qg0znpu7/
What's wrong with my code? how can I fix it to obtain an in-place canvas crop?
Changing the width or height of a canvas will clear it. For that reason you will have to copy the data first.
You can use putImageData() for that:
$('#edit').on("click", function() {
var c = $('#canvas')[0];
var ctx = c.getContext("2d");
var imageData = ctx.getImageData(0, 0, 100, 100);
c.width = 100;
c.height = 100;
ctx.putImageData(imageData, 0, 0);
});
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "green";
ctx.fillRect(0, 0, 350, 350);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="350" height="350"></canvas>
<input id="edit" type="button" value="Edit" />
The problem is demonstrated in the image below
In other words, how to exactly compute the x and y coordinates for every frame?
ctx.arc(x,y,radius,0,pi*2,false)
because after incrementing one coordinate, I have a problem how to compute the other
I tried this but doesn't work
var step=2,x=100,y=100,r=50,coordinates=[[x,y-r]];
for(var i=1;i <r;i+=step){
bx=x;
x+=step;
y=y-Math.sqrt(Math.pow(r,2)-Math.pow(bx-x,2))
coordinates[i]=[x,y];
}
a jsfiddle will be appreciated.
var canvas = document.querySelector("#c");
var ctx = canvas.getContext("2d");
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var speed = 10; // Lower is faster
function animate(t){
ctx.save();
ctx.clearRect (0 , 0 ,canvas.width ,canvas.height );
ctx.translate(canvas.width/2, canvas.height/2);
// First circle
ctx.beginPath();
ctx.arc(0, 0, 5, 0, 2 * Math.PI, false);
ctx.fillStyle = 'blue';
ctx.fill();
ctx.closePath();
// rotate + move along
ctx.rotate((t/speed)/100);
ctx.translate(100,0);
// Orbiting cirle
ctx.beginPath();
ctx.arc(0, 0, 10, 0, 2 * Math.PI, false);
ctx.fillStyle = 'red';
ctx.fill();
ctx.closePath();
ctx.restore();
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
canvas {
border: 1px solid black;
}
<canvas id="c" width="512" height="512"></canvas>