Javascript Canvas draw rectangles or circles - javascript

I'm searching for a way to "live" draw rectangles or circles on a canvas.
I found various ways with fillRect() to draw rectangles, but not live. What I mean is, to be able to mouseDown() on one point and move it to another point in the canvas, which defines the size of the canvas, just like for example in Microsoft Paint, OneNote and so on.
Can anybody help me out and give me an advice on how to get started? I might be thinking of a way on how to do it, without seeing the rectangle (or circle) size changing, something like:
$("canvas").mousedown(function(event){
var ctx = this.getContext("2d");
ctx.clearRect(0,0,$(this).width(),$(this).height());
var initialX = event.clientX - this.getBoundingClientRect().left;
var initialY = event.clientY - this.getBoundingClientRect().top;
$(this).mousemove(function(evt) {
ctx.strokeRect(initialX, initialY, evt.clientX - event.clientX, evt.clientY - event.clientY);
});
});
But I want to see it live, so how the rectangles size changes when the user moves the mouse.

https://jsfiddle.net/zb66mxra/2/
To do it live you need to keep a constant image of your Canvas. This is accomplished easily by keeping an array of objects to be drawn over and over again by your JavaScript.
let drawArr = [];
An example object contains an x and y coordinate to begin drawing, a width, and a height:
{ x: 100,
y: 100,
w: 10,
h: 10 }
when your mouse moves over the canvas you ONLY want it to change the array if the mouse is down. This means you need to set a flag to see if this case is either true or false:
let mousedown = false;
canvas.addEventListener('mousedown', function(e) {
mousedown = true;
...
});
canvas.addEventListener('mouseup', function(e) {
mousedown = false;
});
When your mouse is down you want to add an item to draw to the array:
canvas.addEventListener('mousedown', function(e) {
mousedown = true;
drawArr.push({
x: e.pageX,
y: e.pageY,
w: 0,
h: 0
});
});
The height and width are initially set to 0. What we want to do now, if you can imagine, is create a height and width of the rectangle while we're dragging the mouse over the canvas and the mouse is down. We want to adjust this on the fly so that when the screen is re-rendered it is seen as it's being drawn.
It's easy to manipulate the height and width because, as long as you're only able to draw one at a time, it will ALWAYS be the most recent object added to the draw array.
canvas.addEventListener('mousemove', function(e) {
if (mousedown) {
let i = drawArr.length -1;
let {
x,
y
} = drawArr[i];
drawArr[i].w = e.pageX - x;
drawArr[i].h = e.pageY - y;
}
});
Finally we use requestAnimationFrame to constantly draw any object within the draw array. We do this by calling it when the page is loaded:
requestAnimationFrame(draw);
And then recursively within the draw function:
function draw() {
...
requestAnimationFrame(draw);
}
Then we simply need to clear the previous screen render and iterate over the draw array and draw everything to the screen again.
function draw() {
ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);
for (let obj of drawArr) {
let {
x,
y,
w,
h
} = obj;
ctx.strokeRect(x, y, w, h);
}
requestAnimationFrame(draw);
}
voila.

Related

Drawing lines on canvas are dotted

I was trying to work on a rainbow-pen drawing canvas, but whenever I draw, the lines appear dotted.
Only when I move really slowly, does it appear properly.
The 'mousemove' event listener, isn't really being able to detect fast changes or is there some other issue in my code?
Also, here is the codepen link, if anyone wants a working program.
Here is the codepen!
const canvas = document.querySelector('#draw');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext("2d");
ctx.lineWidth = 50;
ctx.lineCap = "round";
ctx.lineJoin = "line";
ctx.strokeStyle = 0;
let hue = 0;
var [x, y] = [0, 0];
let paint = false;
canvas.addEventListener('mousedown', beginDraw);
function beginDraw(e) {
paint = true;
[x, y] = [e.x, e.y];
// ctx.moveTo(x, y);
}
canvas.addEventListener('mousemove', draw);
function draw(e) {
if (paint == false)
return;
ctx.strokeStyle = `hsla(${hue}, 100%, 50%, 0.5)`;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(e.x, e.y);
ctx.stroke();
[x, y] = [e.x, e.y];
hue++;
}
canvas.addEventListener('mouseup', endDraw);
function endDraw() {
paint = false;
}
<canvas id="draw"></canvas>
I think the problem is opacity in your hsla function for color. Because it is set to 0.5 you have some transparency and because you are drawing a line for each mousemove you have for each mouse move event start and end point for your drawing.
Sometimes these points overlaps each other.
You can remove transparency and keep it to 1. In such case you are no longer see places where 2 dots are drawn one above another making color more visible to others.
ctx.strokeStyle = `hsla(${hue}, 100%, 50%, 1)`;
In case you dont like to see dots when color changes you will need to make more color values also playing with other parameters not only hue parameter, because color step may be to large and you may see edges when color is changed.
The mousemove event handler fires only so many times per second. On each execution, your code draws a line from the previous mouse location to the current mouse location. Each subsequent line partially overlaps the previous line.
For slow strokes, the overlap is almost 100% so you won't see the effect, but for faster strokes, the overlap is shown as a circle. Since you're using partial transparency, the spots where the lines overlap become darker and this causes the "dotted" effect you are seeing.
If you set your opacity to 1, the effect will go away.

How to rotate one object at another (slowly)

I have been looking around for this function and thus far I just can't find any I can make any sense of. I already have a rotating function to make it equal to the position but slowly is proving to be a bit harder with 0-360 and all.
I am using a html canvas 2d context to render the objects on a Cartesian coordinate system .
I would like object1 to face at positionX and positionY at a turn rate (R) , fairly straightforward.
there is no need for me to supply any code since your likely going to make your own anyways. But I will anyways here you go:
let faceAt = function (thisObject,positionX,positionY) {
let desiredLocationX = positionX - thisObject.transform.x;
let desiredLocationY = positionY -thisObject.transform.y;
thisObject.transform.rotation = Math.degrees(Math.atan2(desiredLocationY, desiredLocationX));
};
The (Math.degrees) function converts radians to degrees.
This thread says it all : https://www.google.ca/amp/s/jibransyed.wordpress.com/2013/09/05/game-maker-gradually-rotating-an-object-towards-a-target/amp/
This question is quite unclear. But, I'm assuming you essentially just want to rotate an element around an arbitrary point on a HTML5 canvas.
On a canvas, you can only draw one element at a time. You can't really manipulate singular elements - for example, you can't rotate an element by itself. Instead, you'd need to rotate the entire canvas. This will always rotate around the centre of the canvas, but if you move the canvas origin, then you will draw on a different part of the canvas; thus allowing you to rotate around a point.
Check out the following example. You can click anywhere on the canvas to make the square rotate around that point. Hopefully this is what you are after:
let cv = document.getElementById("cv");
let ctx = cv.getContext("2d");
let angle = 0;
//Variables you can change:
let speed = 1; //Degrees to rotate per frame
let pointX = 250; //The x-coord to rotate around
let pointY = 250; //The y-coord to rotate around
ctx.fillStyle = "#000";
setInterval(()=>{ //This code runs every 40ms; so that the animation looks smooth
angle = (angle + speed) % 360; //Increment the angle. Bigger changes here mean that the element will rotate faster. If we go over 360deg, reset back to 0.
ctx.clearRect(0, 0, 400, 400); //Clear away the previous frame.
//Draw the point we are rotating around
ctx.beginPath();
ctx.arc(pointX,pointY,5,0,2*Math.PI);
ctx.fill();
ctx.closePath();
ctx.save(); //Save the state before we transform and rotate the canvas; so we can go back to the unrotated canvas for the next frame
ctx.translate(pointX, pointY); //Move the origin (0, 0) point of the canvas to the point to rotate around. The canvas always rotates around the origin; so this will allow us to rotate around that point
ctx.rotate(angle*Math.PI/180); //Rotate the canvas by the current angle. You can use your Math.degrees function to convert between rads / degs here.
ctx.fillStyle = "#f00"; //Draw in red. This is also restored when ctx.restore() is called; hence the point will always be black; and the square will always be red.
ctx.fillRect(0, 0, 50, 50); //Draw the item we want rotated. You can draw anything here; I just draw a square.
ctx.restore(); //Restore the canvas state
}, 40);
//Boring event handler stuff
//Move the point to where the user clicked
//Not too robust; relys on the body padding not changing
//Really just for the demo
cv.addEventListener("click", (event)=>{
pointX = event.clientX - 10;
pointY = event.clientY - 10;
});
#cv {
border:solid 1px #000; /*Just so we can see the bounds of the canvas*/
padding:0;
margin:0;
}
body {
padding:10px;
margin:0;
}
<canvas id="cv" width="400" height="400"></canvas><br>
Click on the canvas above to make the rectangle rotate around the point that was clicked.

Make canvas line show

Ok, here is something simple, I hope. I've a div container in which I can click and what I'm trying to do is to create two perpendicular lines which cross each other where I've clicked. So far I've written those:
#fr{
float: right;
margin-top: 5%;
height: 720px;
width: 1280px;
position: relative;
background-image: url(blueboard.jpg);
border: 1px solid black;
clear:none;
}
canvas{
border:1px solid red;
float: right;
height: 720px;
width: 1280px;
clear:none;
}//css part, I actually place the canvas on top of my div
//and on html...
<canvas id="line"></canvas>
//js
function saveOO(e){
var xo, yo;
xo=e.clientX;
yo=e.clientY;
...
document.getElementById("saved").innerHTML="The (0;0) = " +"("+xo+";"+yo+")";
document.getElementById("ball").style.left=xo+'px';
document.getElementById("ball").style.top=yo+'px';
xylines(xo, yo);
...;
}
function lines(xo, yo){
var xo, yo, xl, xline, yl, yline, Dx, Dy, a, b, c, d, e;
xo=xo;
yo=yo;
a=$("#fr").position();
b=$("#fr").width();
c=$("#fr").height();
Dy=a.top+100;
Dx=a.left;
d=Dx+b;
e=Dy+c;
xline = document.getElementById("line");
xl=xline.getContext("2d");
xl.beginPath();
xl.moveTo(Dx,yo);
xl.lineTo(d,yo);
xl.lineWidth = 15;
xl.stroke();
yline = document.getElementById("line");
yl=yline.getContext("2d");
yl.beginPath();
yl.moveTo(xo,Dy);
yl.lineTo(xo,e);
yl.lineWidth = 15;
yl.stroke();}
I have, as well, checked whether all variables assign a value and everything is good with that. The crossing point should be exactly where the blue ball is, it also positions on the place where it's clicked. As you can see on the image no lines show, even if I remove the blue background. Please, help me, maybe something is missing. I'm looking forward to your answers.
:)
P.S. Dy is Y of the top left corner, Dx respectively X of the top left corner
Update 2
A slightly amended fiddle where the lines span the entire width/height of the canvas:
https://jsfiddle.net/0y37qwvw/5/
This is by using 0 as the starting point for each and canvas.width/canvas.height as the ending point.
Update
Here is a fiddle demonstrating the use of a canvas overlay and responding to a click events.
https://jsfiddle.net/0y37qwvw/4/
The important thing is to get the relative x and y co-ordinates right, which I have done using event.offsetX and event.offsetY and a fallback for when they are not implemented:
document.getElementById("canvas-overlay").addEventListener("click", function( event ) {
var x, y, clientRect;
clientRect = event.target.getBoundingClientRect();
x = (typeof event.offsetX !== 'undefined' ? event.offsetX : (event.clientX - clientRect.left));
y = (typeof event.offsetY !== 'undefined' ? event.offsetY : (event.clientY - clientRect.top));
lines(x, y, 50, 50);
}, false);
Original answer
Your code is incomplete, so it is hard to be sure what the exact problems are.
One problem though is that you have not directly set the width and height of the canvas element, which will result in the canvas being scaled.
You can do this on the canvas element:
<canvas id="line" height="720" width="1280"></canvas>
Demonstrated at:
https://jsfiddle.net/0y37qwvw/1/
You could also set the width and height programmatically:
var canvas = document.getElementById("line");
canvas.width = 1280;
canvas.height = 720;
https://jsfiddle.net/0y37qwvw/3/
Compare to what happens if the width and height are only set by CSS:
https://jsfiddle.net/0aph7yno/
If you still can't get it to work, set up a plunker/fiddle with the broken code.
Here is some code I have written, I tried to use as much as OOP style so it's easier to expand it. But still simple and clear.
http://jsfiddle.net/eeqhc2tn/2/
var canvas = document.getElementById('can');
var ctx = canvas.getContext('2d');
var drawThese = [];
canvas.width = 500;
canvas.height = 500;
render();
//Line Code
function Line(sx, sy, ex, ey) {
this.sx = sx;
this.sy = sy;
this.ex = ex;
this.ey = ey;
}
Line.prototype.draw = function () {
ctx.beginPath();
ctx.moveTo(this.sx, this.sy);
ctx.lineTo(this.ex, this.ey);
ctx.stroke();
};
Line.drawCrossLines = function (x, y) {
var horizontal = new Line(0, y, canvas.width, y);
var vertical = new Line(x, 0, x, canvas.height);
drawThese.push(horizontal);
drawThese.push(vertical);
}
canvas.addEventListener('click', function (e) {
Line.drawCrossLines(e.offsetX, e.offsetY);
});
//Circle code
function Circle(x, y, r) {
this.x = x;
this.y = y;
this.r = r;
}
Circle.prototype.draw = function () {
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
ctx.fill();
};
//Moving Circle Code that extends Circle
function MovingCircle() {
Circle.call(this,0,0,10);
}
MovingCircle.prototype = Object.create(Circle.prototype);
MovingCircle.prototype.constructor = MovingCircle;
MovingCircle.prototype.move = function (x, y) {
this.x = x;
this.y = y;
}
var pointer = new MovingCircle();
drawThese.push(pointer);
canvas.addEventListener('mousemove',function(e){
pointer.move(e.offsetX, e.offsetY);
});
//Rendering and animation code
function render() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawThese.forEach(function (e) {
e.draw();
});
requestAnimationFrame(render);
}
I've found a working solution on my own, of course inspired by rpn. If you would like to make same or similar thing to what I this topic is about, a system including a container, canvas and a mouse event (click, in this case) you will have to follow this steps.
1. You cannot draw directly to a div, you've to create something like an invisible overlay for canvas and to place it perfectly over the div.
2. An important part is getting the proper coordinates, take into account that there are some tad but important differences between the various coords get methods. (`clientX/Y`, `offsetX/Y` and so on). It matters a lot.
3. Last but not at least, you should carefully consider how you get container's dimensions, as you'll need them later. Remember! We are in a container, a.k.a. working with an area which is just part of the whole window (your browser).
At first I was receiving my coordinates with clientX/Y but maybe due to some mismatches between the get method for coordinates and the one for div's dimensions I was hammered by bugs. To solve this, I've created a method from which I take mouse click coordinates with offsetX/Y. This way you have to think of you container as if it is a separate coordinate system, different from your window's(which by default is general). This means that now the top left corner of this div has x:y = (0;0);
function getcooords(){
xo = e.offsetX;
yo = e.offsetY;
DrawLines(x0, y0); //invoke func DrawLines
}
Now we go to the moment where we should draw our lines.
function DrawLines(x0,y0){
//your variables here...
w=$("#yourcontainer").width();
h=$("#yourcontainer").height();
Dy=0;
Dx=0;
}
That's the second step, Dx and Dy are the top and left properties of the div. Hence, from the what I've just said above, they will be equal to 0, both. Width and height of the container I take simply with jq but you can do it on another preferred way.
Generally speaking, that's the core of your drawing algorithm after we've taken needed dimensions and coordinates:
xl.beginPath();
xl.moveTo(b,yo);//start point of line
xl.lineTo(Dx,yo);//end point of line
xl.stroke(); //DRAW IT :)
Now, I've forgot to tell you that you have to define your lines at first, where should they be, what properties, styles should they have, etc..:
var xline = document.getElementById("line");
xl=xline.getContext("2d");
Remember! If you would like to delete, to erase the what you've drawn you'd have to define your lines FIRST and delete them after their definition. I'm saying definition, not drawing and you can draw the next 1, 2, 3... n lines and delete them over and over again if you follow this principle.
That's it guys, I hope I've explained it well, sorry for my English, probably I've made some tad mistakes but I hope you understand me. If you have any questions, please feel free to ask me, I'll try to do my best in order to help you.
:)

Multiple canvas polygon detection map using isPointInPath() and responsive design

I have an array of canvas objects that draw correctly. i have three problems:
Offset. I have tested the code below in JS fiddle and it works, but when i export it my web page, the variables get skewed. The detection happens, but not in the right place. the page width is set in CSS, and the actual canvas area is centered using a margin:0 auto call, however it is smaller than the page width.
<canvas id="canvas" width="780" height="690" style="position:absolute;"></canvas>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var scrollX = $canvas.scrollLeft();
var scrollY = $canvas.scrollTop();
var $results = $("#results");
// define the polygon items
var polyArray = new Array (6);
polyArray [0] =[{x:50,y:236}, {x:200,y:115}, {x:350,y:50}, {x:350,y:300}, {x:232,y:325}, {x:75,y:300}];
polyArray [1] =[{x:350,y:55}, {x:350,y:300}, {x:510,y:300}, {x:510,y:205}, {x:578,y:172}, {x:690,y:96}, {x:650,y:17}];
polyArray [2] =[{x:510,y:300}, {x:510,y:200}, {x:715,y:113}, {x:780,y:200}, {x:780,y:485}, {x:625,y:468}, {x:605,y:456}, {x:605,y:428}];
polyArray [3] =[{x:0,y:446}, {x:284,y:320}, {x:255,y:540}, {x:240,y:566}, {x:73,y:600}, {x:0,y:565}];
polyArray [4] =[{x:355,y:305}, {x:510,y:305}, {x:604,y:423}, {x:604,y:460}, {x:628,y:484}, {x:610,y:513}, {x:587,y:468}, {x:537,y:426}, {x:500,y:400}, {x:447,y:424}, {x:312,y:365}, {x:307,y:314 }];
polyArray [5] =[{x:350,y:425}, {x:415,y:421}, {x:455,y:434}, {x:495,y:411}, {x:550,y:444}, {x:618,y:590}, {x:570,y:616}, {x:359,y:597}, {x:333,y:522}];
// call the function to draw all the objects in the array
define(polyArray);
// call through the array to draw the objects
function define(polygon) {
ctx.beginPath();
for (var i = 0; i < polygon.length; i++) {
ctx.moveTo(polygon[i][0].x, polygon[i][0].y);
for (var j = 1; j < polygon[i].length; j++) {
ctx.lineTo(polygon[i][j].x, polygon[i][j].y);
}
ctx.fill();
}
ctx.closePath();
}
function hitTest(polygon) {
// redefine the polygon
define(polygon);
// ask isPointInPath to hit test the mouse position
// against the current path
return (ctx.isPointInPath(mouseX, mouseY));
}
function handleMouseMove(e) {
e.preventDefault();
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
// check if the mouse is inside the polygon
var isInside = hitTest(polyArray);
if (isInside) {
canvas.style.cursor = 'pointer';
$results.text("Mouse is inside the area);
} else {
canvas.style.cursor = 'default';
$results.text("Outside");
}
}
$("#canvas").mousemove(function (e) {
handleMouseMove(e);
});
Detecting which object has been hovered over. What needs to happen is on hover of one the array shapes should effect some CSS/JS. How can i assign an ID variable and detect it?
when i bring responsive design into the equation i'm a bit stuck for how to incorporate this offset and the poly co-ords to scale appropriately.
Any point in the right direction would be greatly appreciated.
Question#1: Getting accurate mouse position after the canvas has moved
Whenever you move your canvas (fex: margin: 0 auto), you must recalculate your offsetX and offsetY values:
If you manually change the canvas element's CSS (fex: canvas.style.margin='50px' inside javascript), then you must also manually call reOffset().
// cache the canvas's offset positions since the
// offset positions are used often
var offsetX,offsetY;
// call this once at the beginning of your app
// and whenever you change the canvas's position on the page
// (eg call when you change margins, scroll, etc)
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
// have the browser auto-reset offsetX & offsetX when
// the viewport scrolls or resizes
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
Question#2 Detecting hovers & blurs over your polygons
Your hitTest function will test if the mouse is currently inside a specified polygon. So inside handleMousemove you could call hitText for each of the polygons inside your polyArray.
Keep a flag variable indicating the index# of the last polygon the mouse was inside (or -1 to indicate the mouse was outside all polygons. When your flag variable value changes, you know there has been either a hover-event or a blur-event. Compare the last and current flag variables to determine which polygon is now hovered or blurred.
Question#3 Incorporating a responsive design
Mouse coordinates reported by the browser into e.clientX and e.clientY are always in unscaled values relative to the browser viewport.
So if you:
Click the mouse and use e.clientX/e.clientY to determine the mouse is at [100,100],
Scale your canvas: context.scale(2,2),
And reclick without moving the mouse from its original [100,100] position,
Then:
Using e.clientX/e.clientY to detect the mouse coordinates will still report the position as [100,100] even if the canvas has been scaled and the mouse is at [200,200] relative to the scaled canvas.
The fix:
You must scale the browser's reported mouse position to match the scaling factor of the canvas:
// Determine how much you want to scale the canvas
var scaleFactor=2.00;
// scale the canvas
context.scale(scaleFactor,scaleFactor);
// also scale the mouse position reported by the browser
mouseX=parseInt(e.clientX-offsetX)*scaleFactor;
mouseY=parseInt(e.clientY-offsetY)*scaleFactor;

Use setInterval to infinitely draw rectangles

I'm trying to learn how to learn basic animation using ONLY canvas with the setInterval function.
I'm trying to draw a simple rectangle to the screen and move it to the right 1 pixel every 100 milliseconds. However when I do it paints over the previous rectangle. I called clearRect() but that doesn't seem to do anything.
How can I make this rectangle smoothly travel across the screen without leaving a trail?
Also if there is a better way to do this rather than using clearRect() and translate() please do share.
var ctx = document.getElementById('mycanvas').getContext('2d');
var a = setInterval(draw,100);
var x = 50;
function draw()
{
ctx.clearRect(0,0,300,300);
ctx.translate(1,0);
ctx.rect(x,50,50,50);
ctx.stroke();
}
You can do it two different ways:
You can continue to use rect() and stroke(), but you need to call beginPath() beforehand. When you call methods like rect(), a list, called the "path," is kept of all of the shapes, or "subpaths," that you've created. Then, when you call stroke(), the entire path is drawn. Thus, even if you clear the screen, all of the past rectangles are still remembered in the path, and drawn again. beginPath() clears that list.
var x = 50;
function draw() {
ctx.clearRect(0, 0, 300, 300);
ctx.beginPath();
ctx.rect(x, 50, 50, 50);
ctx.stroke();
x++;
}
Or, you can combine the rect() and stroke() into one line, and not need to call beginPath(). That's because the rectangle is both created and drawn at the same time, and isn't put in the list.
var x = 50;
function draw() {
ctx.clearRect(0, 0, 300, 300);
ctx.strokeRect(x, 50, 50, 50);
x++;
}
Either way, I advise incrementing x instead of using translate(), because translate() basically moves the imaginary "pen" that is drawing on the canvas. So if you translate(50, 50), and then you try to draw a rectangle at (0, 0) on the canvas, it will actually be at (50, 50).
As Microsoft puts it on MSDN, "The translate method effectively remaps the (0,0) origin on a canvas."
If you repeatedly do that, it will become difficult to keep track of where you're actually drawing.
Your x variable never changes, so your shape will not move. You need to increment x to get movement:
var x = 50;
function draw(){
ctx.clearRect(0,0,300,300);
ctx.translate(1,0);
ctx.rect(x,50,50,50);
ctx.stroke();
x++;
}
In order to get a smooth animation with shapes and other sprites moving across the screen (or even staying still) it would be better to make a clearScreen method that will basically draw over the entire canvas in whatever background color the canvas is. It is basically just a function that will draw a white (or whatever background color you are using) rectangle over the entire canvas. Then, you call the draw function that will make all the necessary drawings. That way, there won't be any trail or anything of the past movements and you won't have to call clearRect() on every single rectangle you make.
Basically, the function will erase the canvas and you can redraw whatever you need to in order to make the animation of the box moving across the screen.
Does that make sense?
EDIT:
Also, to be clear, you would make your own clearScreen method based on what size your canvas is and what color your background is. Its not hard, all it does is draw a rectangle over the screen.
Simply increment x on every call:
var canvas = document.getElementById('mycanvas')
var ctx = canvas.getContext('2d');
var a = setInterval(draw,100);
var x = 50;
function draw(){
canvas.width = canvas.width; // clears the canvas
ctx.rect(x++,50,50,50);
ctx.stroke();
if (x > 250) // resets the position
x = 50;
}
<canvas id="mycanvas"></canvas>
I also removed that translation since there's no need to do it just for the square animation.
Try beginPath() and closePath():
var maxX, x = 0,
s = 50,
maxY;
var repaint = function(ctx) {
if (x + s >= maxX) { //reached end of the canvas
return;
}
ctx.clearRect(0, 0, maxX, maxY); //clear previous
ctx.beginPath(); //start drawing
ctx.rect(x, s, s, s);
ctx.stroke();
ctx.closePath(); //stop drawing
x++;
setTimeout(function() {
repaint(ctx); //continue here
}, 100);
};
var cnvs = document.getElementById('canvas');
maxX = cnvs.width;
maxY = cnvs.height;
repaint(cnvs.getContext('2d'));
canvas {
border: 1px solid grey;
}
<canvas width="360" height="180" id='canvas'>HTML5 canvas not supported</canvas>

Categories