How do I clear the HTML canvas, Object is leaving a trail in the second canvas where it is grey?
var Xposition = 50;
var Yposition = 50;
var dx = 0.4;
var dy = 5;
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#D3D3D3";
//Draw Square
function draw() {
ctx.fillStyle = "#D3D3D3";
ctx.fillRect(0, 0, 300, 300);
ctx.save();
ctx.translate(-0.2, 0);
ctx.fillStyle = "red";
ctx.fillRect(Xposition, Yposition, 20, 20);
ctx.fillStyle = "green";
ctx.fillRect(100, 0, 2, 50);
ctx.fillStyle = "green";
ctx.fillRect(200, 30, 2, 100);
Xposition += dx;
}
setInterval(draw, 10);
//Move Square
document.addEventListener('keydown', function(event) {
Xposition += 1;
if (event.keyCode == 40 && Yposition < canvas.height - 20) {
Yposition += 10;
}
//top
else if (event.keyCode == 38 && Yposition > 0) {
Yposition -= 10;
}
});
<div id="centre">
<canvas id="myCanvas" height="200px" width="300px"></canvas>
</div>
var clearAdj = 0;
//Draw Square
function draw() {
clearAdj += 0.2;
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, 300 + clearAdj, 300);
ctx.save();
ctx.translate(-0.2, 0);
Here's a quick solution that just adds an adjustment value as you translate the canvas
The canvas is not clearing completely because the entire 300x300 entity of moving over to the left. Your call to clear a 300x300 space starts at the origin of THAT CANVAS and will translate along with it.
A more elegant fix would be to make object for each of your green bar things and just subtract the x value from them, effectively moving them to the left. This would be more efficient as you could just delete the object as they leave. Your approach requires a large canvas
Related
I'm trying to make a ball jump even in midair, but my code always just teleports to the same spot and then jumps, can anydody tell me how to fix this problem of mine? It needs to be able to jump wherever it is at that exact moment, and i've already tried something with set interval.
I'm trying to make a ball jump even in midair, but my code always just teleports to the same spot and then jumps, can anydody tell me how to fix this problem of mine? It needs to be able to jump wherever it is at that exact moment, and i've already tried something with set interval.
I'm trying to make a ball jump even in midair, but my code always just teleports to the same spot and then jumps, can anydody tell me how to fix this problem of mine? It needs to be able to jump wherever it is at that exact moment, and i've already tried something with set interval.
var canvas, ctx, container;
canvas = document.createElement('canvas');
ctx = canvas.getContext("2d");
var ball;
var touchGround = false;
var pull= 0.43;
var vy;
var gravity = pull;
var i = Math.floor(Math.random()*11)
color = ["red", "blue","green","yellow","purple","white","pink","silver","teal","turqu oise","magenta","cyan"];
console.log(color[i])
function ballMovement() {
vy += gravity;
ball.y += vy;
if (ball.y + ball.radius > canvas.height) {
ball.y = canvas.height - ball.radius;
vy = 0;
var img = document.getElementById('gameOver');
ctx.drawImage(gameOver, canvas.width/2-436, 100)
ball.radius = 0;
}
}
function init() {
setupCanvas();
var img = document.getElementById('gameOver');
img.style.visibility = 'hidden';
//how high the ball goes
vy = -19;
var y1 = 450
ball = {
x: canvas.width/2,
//where the ball starts moving upwards
y: 480, //here1
radius: 20,
status: 0,
color: color[i]};
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2, false);
ctx.fillStyle = ball.color;
ctx.fill();
ctx.closePath()
//draw a moving ball
ballMovement();
}
setInterval(draw, 1000 / 35);
function setupCanvas() {
container = document.createElement('div');
container.className = "container";
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(container);
container.appendChild(canvas);
ctx.strokeStyle = "#ffffff";
ctx.lineWidth = 2;
}
window.onclick = function(jump){
pull + 0.1;
touchGround = false;
init()
draw()
ballMovement()
setupCanvas()
vy+((canvas.height-canvas.height)-ball.y);
}
//GOAL
//Ball jumps at somewhere in screen, let it jump wherever it is.
If I got you correctly you want your ball to go higher and higher. But problem is that you got fixed position where it's starts so where's what you need to change:
var canvas, ctx, container;
canvas = document.createElement('canvas');
canvas.width = 800;
canvas.height = 800;
ctx = canvas.getContext("2d");
var ball = {
y: 480
};
var touchGround = false;
var pull= 0.43;
var vy;
var gravity = pull;
//Creating a variable to know whether our game is running
var gameRunning = 0;
var i = Math.floor(Math.random()*11);
//Adding variable for interval so we can start it with init function
var timer;
color = ["red", "blue","green","yellow","purple","pink","silver","teal","turquoise","magenta","cyan", "black"];
function ballMovement() {
vy += gravity;
ball.y += vy;
if (ball.y + ball.radius > canvas.height) {
ball.y = canvas.height - ball.radius;
vy = 0;
var img = document.getElementById('gameOver');
ctx.drawImage(gameOver, canvas.width/2-436, 100)
ball.radius = 0;
//Stoping the draw function
clearInterval(timer);
//Saying the game isn't running
gameRunning = 0;
}
}
function init() {
//Check if canvas already created
if(!document.querySelector('.container')){
setupCanvas()
}
vy = -19;
var y1 = 450
ball = {
x: canvas.width/2,
y: ball.y,
radius: 20,
status: 0,
color: color[i]
};
//Clearing previous interval if it were any and creating a new one
clearInterval(timer);
timer = setInterval(draw, 1000 / 60);
//Saying the game is running
gameRunning = 1;
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2, false);
ctx.fillStyle = ball.color;
ctx.fill();
ctx.closePath()
ballMovement();
}
function setupCanvas() {
container = document.createElement('div');
container.className = "container";
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(container);
container.appendChild(canvas);
ctx.strokeStyle = "#ffffff";
ctx.lineWidth = 2;
}
window.onclick = function(){
pull + 0.1;
touchGround = false;
//Check if the game is running or not
//If it's not running - call init
if(!gameRunning){
init();
}
else{
//If game is already running - change speed
vy = -19;
}
//I've also removed some function that were starting with init itself
vy+((canvas.height-canvas.height)-ball.y);
}
I am trying to make a simple game in JavaScript in which you move an object (circle/ball) around on canvas using arrow keys. I have spent a lot of time researching and coding, but without luck so far, so I hope you guys can help me. For now, I am simply trying to move the object/ball around using arrow keys [up, down, left, right]. Anybody able to figure out, why this doesn't work? Thank you very much in advance.
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext("2d");
canvas.width = canvas.height = 500;
//the circle
function circle() {
ctx.beginPath();
ctx.arc(50, 50, 25, 0, Math.PI * 2, true);
ctx.fillStyle = "blue";
ctx.fill();
}
circle();
//move function for going left
window.addEventListener("keydown", function(event) {
if (event.keyCode == 37) {
circle.x = 1;
}
})
You could accomplish such movement in the following way ...
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext("2d");
var x = 50,
y = 50,
radius = 15,
speed = 3;
function circle() {
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2, true);
ctx.fillStyle = "#07C";
ctx.fill();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
circle();
requestAnimationFrame(draw);
}
draw();
window.addEventListener("keydown", function(e) {
switch (e.key) {
case 'ArrowUp':
if (y > radius) y -= speed;
break;
case 'ArrowDown':
if (y < canvas.height - radius) y += speed;
break;
case 'ArrowLeft':
if (x > radius) x -= speed;
break;
case 'ArrowRight':
if (x < canvas.width - radius) x += speed;
break;
}
});
canvas {
border: 1px solid black;
}
<canvas id="mycanvas" width="200" height="200"></canvas>
apology for not giving any explanation
I'm trying to resize a rotated shape on canvas. My problem is that when I call the rendering function, the shape starts "drifting" depending on the shape angle. How can I prevent this?
I've made a simplified fiddle demonstrating the problem, when the canvas is clicked, the shape is grown and for some reason it drifts upwards.
Here's the fiddle: https://jsfiddle.net/x5gxo1p7/
<style>
canvas {
position: absolute;
box-sizing: border-box;
border: 1px solid red;
}
</style>
<body>
<div>
<canvas id="canvas"></canvas>
</div>
</body>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
canvas.width = 300;
canvas.height= 150;
var ctx = canvas.getContext('2d');
var counter = 0;
var shape = {
top: 120,
left: 120,
width: 120,
height: 60,
rotation: Math.PI / 180 * 15
};
function draw() {
var h2 = shape.height / 2;
var w2 = shape.width / 2;
var x = w2;
var y = h2;
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(75,37.5)
ctx.translate(x, y);
ctx.rotate(Math.PI / 180 * 15);
ctx.translate(-x, -y);
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, shape.width, shape.height);
ctx.restore();
}
canvas.addEventListener('click', function() {
shape.width = shape.width + 15;
window.requestAnimationFrame(draw.bind(this));
});
window.requestAnimationFrame(draw.bind(this));
</script>
In the "real" code the shape is resized when the resize-handle is clicked and moved but I think this example demonstrates the problem sufficiently.
EDIT: updated fiddle to clarify the issue:
https://jsfiddle.net/x5gxo1p7/9/
Always use local coordinates to define shapes.
When rendering content that is intended to be transformed the content should be in its own (local) coordinate system. Think of a image. the top left pixel is always at 0,0 on the image no matter where you render it. The pixels are at their local coordinates, when rendered they are moved to the (world) canvas coordinates via the current transformation.
So if you make your shape with coordinates set to its local, making the rotation point at its local origin (0,0) the display coordinates are stored separately as world coordinates
var shape = {
top: -30, // local coordinates with rotation origin
left: -60, // at 0,0
width: 120,
height: 60,
world : {
x : canvas.width / 2,
y : canvas.height / 2,
rot : Math.PI / 12, // 15deg clockwise
}
};
Now you don't have to mess about with translating forward and back... blah blah total pain.
Just
ctx.save();
ctx.translate(shape.world.x,shape.world.y);
ctx.rotate(shape.world.rot);
ctx.fillRect(shape.left, shape.top, shape.width, shape.height)
ctx.restore();
or event quicker and eliminating the need to use save and restore
ctx.setTransform(1,0,0,1,shape.world.x,shape.world.y);
ctx.rotate(shape.world.rot);
ctx.fillRect(shape.left, shape.top, shape.width, shape.height);
The local shape origin (0,0) is where the transformation places the translation.
This greatly simplifies a lot of the work that has to be done
var canvas = document.getElementById('canvas');
canvas.width = 300;
canvas.height= 150;
var ctx = canvas.getContext('2d');
ctx.fillStyle = "black";
ctx.strokeStyle = "red";
ctx.lineWidth = 2;
var shape = {
top: -30, // local coordinates with rotation origin
left: -60, // at 0,0
width: 120,
height: 60,
world : {
x : canvas.width / 2,
y : canvas.height / 2,
rot : Math.PI / 12, // 15deg clockwise
}
};
function draw() {
ctx.setTransform(1,0,0,1,0,0); // to clear use default transform
ctx.clearRect(0, 0, canvas.width, canvas.height);
// you were scaling the shape, that can be done via a transform
// once you have moved the shape to the world coordinates.
ctx.setTransform(1,0,0,1,shape.world.x,shape.world.y);
ctx.rotate(shape.world.rot);
// after the transformations have moved the local to the world
// you can ignore the canvas coordinates and work within the objects
// local. In this case showing the unscaled box
ctx.strokeRect(shape.left, shape.top, shape.width, shape.height);
// and a line above the box
ctx.strokeRect(shape.left, shape.top - 5, shape.width, 1);
ctx.scale(0.5,0.5); // the scaling you were doing
ctx.fillRect(shape.left, shape.top, shape.width, shape.height);
}
canvas.addEventListener('click', function() {
shape.width += 15;
shape.left -= 15 / 2;
shape.world.rot += Math.PI / 45; // rotate to illustrate location
// of local origin
var distToMove = 15/2;
shape.world.x += Math.cos(shape.world.rot) * distToMove;
shape.world.y += Math.sin(shape.world.rot) * distToMove;
draw();
});
// no need to use requestAnimationFrame (RAF) if you are not animation
// but its not wrong. Nor do you need to bind this (in this case
// this = window) to the callback RAF does not bind a context
// to the callback
/*window.requestAnimationFrame(draw.bind(this));*/
requestAnimationFrame(draw); // functionaly identical
// or just
/*draw()*/ //will work
body { font-family : Arial,"Helvetica Neue",Helvetica,sans-serif; font-size : 12px; color : #242729;} /* SO font currently being used */
canvas { border: 1px solid red; }
<canvas id="canvas"></canvas>
<p>Click to grow "and rotate" (I add that to illustrate the local origin)</p>
<p>I have added a red box and a line above the box, showing how using the local coordinates to define a shape makes it a lot easier to then manipulate that shape when rendering "see code comments".</p>
Try this. You had ctx.translate() used where it was not entirely necessary. That caused the problems.
<script type="text/javascript">
var canvas = document.getElementById('canvas');
canvas.width = 300;
canvas.height= 150;
var ctx = canvas.getContext('2d');
var counter = 0;
var shape = {
top: 120,
left: 120,
width: 120,
height: 60,
rotation: Math.PI / 180 * 15
};
function draw() {
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(75,37.5)
ctx.rotate(Math.PI / 180 * 15);
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, shape.width, shape.height);
ctx.restore();
}
canvas.addEventListener('click', function() {
shape.width = shape.width + 15;
window.requestAnimationFrame(draw.bind(this));
});
window.requestAnimationFrame(draw.bind(this));
</script>
This is happening because the x and y are set as the half value of the shape size, which completely changes its position.
You should set a point for the center of the shape, anyway. I set this point as ctx.canvas.[width or height] / 2, the half of the canvas.
var h2 = shape.height / 2;
var w2 = shape.width / 2;
var x = (ctx.canvas.width / 2) - w2;
var y = (ctx.canvas.height / 2) - h2;
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(x + (shape.width / 2), y + (shape.height / 2));
ctx.rotate(((shape.rotation * Math.PI) / 180) * 15);
ctx.fillStyle = '#000';
ctx.fillRect(-shape.width / 2, -shape.height / 2, shape.width, shape.height);
ctx.restore();
Fiddle.
Found a solution, problem was that I wasn't calculating the new center point coordinates.
The new fiddle with solution: https://jsfiddle.net/HTxGb/151/
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width =500;
canvas.height = 500;
var x = canvas.width/2;
var y = canvas.height/2;
var rectw = 20;
var recth = 20;
var rectx = -rectw/2;
var recty = -recth/2;
var rotation = 0;
var addedRotation = Math.PI/12;
var addedWidth = 20;
var addedHeight = 10;
var draw = function() {
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(x, y);
ctx.rotate(rotation);
ctx.fillRect(rectx, recty, rectw, recth);
ctx.restore();
}
document.getElementById('growXRight').addEventListener('click', function() {
rectx -= addedWidth/2;
x += addedWidth/2 * Math.cos(rotation);
y -= addedWidth/2 * Math.sin(-rotation);
rectw += addedWidth;
draw();
})
document.getElementById('growXLeft').addEventListener('click', function() {
rectx -= addedWidth/2;
x -= addedWidth/2 * Math.cos(rotation);
y += addedWidth/2 * Math.sin(-rotation);
rectw += addedWidth;
draw();
})
document.getElementById('growYTop').addEventListener('click', function() {
recty -= addedHeight/2;
x += addedHeight/2 * Math.sin(rotation);
y -= addedHeight/2 * Math.cos(-rotation);
recth += addedHeight;
draw();
})
document.getElementById('growYBottom').addEventListener('click', function() {
recty -= addedHeight/2;
x -= addedHeight/2 * Math.sin(rotation);
y += addedHeight/2 * Math.cos(-rotation);
recth += addedHeight;
draw();
})
document.getElementById('rotatePlus').addEventListener('click', function() {
rotation += addedRotation;
rotation = rotation % (Math.PI*2);
if(rotation % Math.PI*2 < 0) {
rotation += Math.PI*2;
}
draw();
})
document.getElementById('rotateMinus').addEventListener('click', function() {
rotation -= addedRotation;
rotation = rotation % (Math.PI*2);
if(rotation % Math.PI*2 < 0) {
rotation += Math.PI*2;
}
draw();
})
draw();
So I've recently been messing around with html5 canvas and trying to figure out how to make a particle system. While it does work I want to make vx = mouse coordinates(specifically x) but they start from the center.
What I mean by this is basically if the cursor is in the center of the canvas then vx would be equal to 0 and if the cursor is to the right from the center of the canvas it have positive mouse coordinates (and if the cursor is to the left from the center of canvas it have negative mouse coordinates).
Once that is accomplished I would just do p.speed += p.vx
Here is my javascript:
window.onload = function(){
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var W = window.innerWidth, H = window.innerHeight;
canvas.width = W;
canvas.height = H;
var particles = [];
var particle_count = 100;
for(var i = 0; i < particle_count; i++)
{
particles.push(new particle());
}
function particle()
{
this.vx = -1 + Math.random() * 2;
this.speed = {x: 0, y: -15+Math.random()*10};
this.location = {x: W/2, y: H/2};
this.radius = 5+Math.random()*10;
this.life = 20+Math.random()*10;
this.remaining_life = this.life;
this.r = Math.round(Math.random()*255);
this.g = Math.round(Math.random()*55);
this.b = Math.round(Math.random()*5);
}
function draw()
{
ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = "black";
ctx.fillRect(0, 0, W, H);
ctx.globalCompositeOperation = "lighter";
for(var i = 0; i < particles.length; i++)
{
var p = particles[i];
ctx.beginPath();
p.opacity = Math.round(p.remaining_life/p.life*100)/100
var gradient = ctx.createRadialGradient(
p.location.x, p.location.y, 0, p.location.x, p.location.y, p.radius);
gradient.addColorStop(0, "rgba("+p.r+", "+p.g+", "+p.b+", "+p.opacity+")");
gradient.addColorStop(0.5, "rgba("+p.r+", "+p.g+", "+p.b+", "+p.opacity+")");
gradient.addColorStop(1, "rgba("+p.r+", "+p.g+", "+p.b+", 0)");
ctx.fillStyle = gradient;
ctx.arc(p.location.x, p.location.y, p.radius, Math.PI*2, false);
ctx.fill();
p.remaining_life--;
p.radius--;
p.location.x += p.speed.x += p.vx;
p.location.y += p.speed.y;
if(p.remaining_life < 0 || p.radius < 0) {
particles[i] = new particle();
}
}
}
setInterval(draw, 33); }
Here is my codepen.
You need to translate context to move origin to center.
You also need to reverse the translation on the mouse coordinates as they will still be relative to the upper-left corner (assuming the coordinates are corrected to be relative to canvas).
Example:
var cx = canvas.width * 0.5;
var cy = canvas.height * 0.5;
ctx.translate(cx, cy); // translate globally once
For each mouse coordinate compensate with the translated position:
var pos = getMousePosition(evt); // see below
var x = pos.x - cx;
var y = pos.y - cy;
To adjust mouse position:
function getMousePosition(evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
}
}
I'm working on a game to play in canvas, and was wanting to add some ambiance to a background layer using javascript. To start, here is the code...
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext("2d");
var x = canvas.width/2;
var y = canvas.height-150;
var dx = Math.random() * (-5 * 5) + 15;
var dy = -15;
function drawDot() {
ctx.beginPath();
ctx.arc(x, y, 10, 0, Math.PI*2);
ctx.fillStyle = "black";
ctx.fill();
ctx.closePath();
};
function move() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawDot();
x += dx;
y += dy;
};
setInterval(move, 50);
If you run that, you can see that what I have is a black ball that moves up and off the page inside a random conal space. What I need help with is figuring out the best way to:
A. Populate it with more balls (maybe like 2-3) that are on their own random trajectory, and
B. Make it so those 2-3 balls are constantly animating inside the random cone area off the page from the same starting area (kind of like a constant spurting fountain effect).
A problem I can already see is that by using the console log, the 1 working ball I have now just keeps going off into infinity outside the canvas, so when I try to add a new one it won't run the function. I'm very new to javascript and especially canvas so apologies if this is obvious!
Thank you for any help with this!
There is a good tutorial by Seb Lee-Delisle on this exact problem here:
https://vimeo.com/36278748
Basically you have to encapsulate each Dot so it knows about its own position and acceleration.
EDIT 1
Here is an example using you own code:
document.body.innerHTML = '<canvas height="600" width="600" id="myCanvas"></canvas>';
clearInterval(interval);
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var dotArray = [];
function Dot() {
var dot = {
y : canvas.height / 2,
x : canvas.width / 2,
speedX : Math.random() * ( - 5 * 5) + 15,
speedY : Math.random() * ( - 5 * 5) + 15,
age : 0,
draw : function () {
this.x += this.speedX;
this.y += this.speedY;
ctx.beginPath();
ctx.arc(this.x, this.y, 10, 0, Math.PI * 2);
ctx.fillStyle = 'black';
ctx.fill();
ctx.closePath();
}
};
return dot;
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < dotArray.length; i++) {
dotArray[i].draw();
dotArray[i].age++;
if (dotArray[i].age > 20) {
dotArray.splice(i, 1);
}
}
dotArray.push(new Dot());
}
draw();
var interval = setInterval(draw, 1000 / 60);