Rectangle is not moving - javascript

I am trying to code a rectangle moving but it is not working and I do not understand why. I created a class for the rectangle and gave the parameters value. Then I drew the rectangle. I am trying to add the value of 5 to the rectangle's x but nothing is happening.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var width = 50;
class Rectangle{
constructor(x, y){
this.x = x;
this.y = y;
}
draw(){
ctx.beginPath();
ctx.rect(this.x, this.y, width, height);
ctx.fillStyle = "0095DD";
ctx.fill();
ctx.closePath();
}
}
function movingRectangle(){
var rect = new Rectangle(canvas.width/2 - width/2, 300);
rect.draw();
rect.x += 5;
}
function draw(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
movingRectangle();
}
var interval = setInterval(draw, 10);

You're recreating rect on each movingRectangle() call, effectively resetting its position to the initial value.
Move this:
var rect = new Rectangle(canvas.width/2 - width/2, 300);
Out of the movingRectangle() function - you only need to create the Rectangle instance once.

I managed to do a short example, based in your code, and leaving the Rectangle constructor outside:
function movingRectangle(){
let x = rect ? rect.x + 5 : canvas.width/2 - width/2;
if (!rect)
rect = new Rectangle(x, 300);
rect.x = x;
rect.draw();
}
https://jsfiddle.net/nicoavn/vc254q0a/4/

Related

How to use constructors and images in javascript?

I have the following segment of code intented to draw an image onto the canvas. This code works:
var ctx = canvas.getContext('2d');
class Rectangle {
constructor(x, y, scale, source) {
this.scale = scale;
this.source = source;
this.x = x;
this.y = y;
}
update() {
var sprite = new Image();
sprite.src = this.source;
sprite.onload = function () {
ctx.drawImage(sprite, this.x, this.y, sprite.width/3, sprite.height/3);
}
}
}
const rect = new Rectangle(0, 0, 1, 'circle.jpeg');
rect.update();
But, when I replace this line:
ctx.drawImage(sprite, this.x, this.y, sprite.width/3, sprite.height/3);
with this:
ctx.drawImage(sprite, this.x, this.y, sprite.width/this.scale, sprite.height/this.scale);
the canvas doesn't show anything at all. All this should be doing is replacing the 3 from before with the value from the constructor (which I set to 1 when I create a new instance). Why isn't it drawing anything?
I would move the sprite to the constructor that way when we call the update we don't have to create a new image, the idea behind that is the update function could be called multiple times efficiently.
See this sample below:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
class Rectangle {
constructor(x, y, scale, source) {
this.scale = scale;
this.x = x;
this.y = y;
this.sprite = new Image();
this.sprite.src = source;
this.sprite.onload = () => {
this.update()
};
}
update() {
if (this.sprite) {
ctx.drawImage(this.sprite, this.x, this.y, this.sprite.width / this.scale, this.sprite.height / this.scale);
}
}
}
const rect = new Rectangle(0, 0, 3, 'http://i.stack.imgur.com/UFBxY.png');
canvas.addEventListener("click", () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
rect.x += 5;
rect.update();
});
<canvas id="canvas"></canvas>
You can see that as suggested in the comments by #skara9 I'm using the () => instead of function() and I'm calling the update there.
On this sample I also added canvas.addEventListener("click" that shows how when the user clicks on the canvas the drawing move a little to the right, the logic is simple we increase the value of rect.x and then we call the rect.update(); that will draw the image on the new location.

How to make moving canvas objects with images in HTML with JavaScript

So I'm working on a project where I have a canvas filled with moving balls. Its an extension/inspired by this codepen project : https://codepen.io/zetyler/pen/LergVR .
It essentially runs with the same physics in place as the codepen, but now I'm trying to draw the moving and colliding balls with images instead of random colors.
The original draw() method looks like this :
var pen = canvas.getContext('2d');
const W = canvas.width;
const H = canvas.height;
var numBalls = 30;
var grav = [0,-0.1];
function Ball(x,y,dx,dy,r) {
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.r = r;
this.color = 'hsl('+(Math.random()*360)+',90%,50%)';
this.draw = function() {
pen.fillStyle = this.color;
pen.beginPath();
pen.arc(this.x,this.y,this.r,0,2*Math.PI);
pen.fill();
}
I'm refactoring the draw method to try and work with an image instead of a random color fill, and so far I can't even get an image to show up. Currently my draw method looks like this:
const canvas = document.querySelector('canvas');
const context = canvas.getContext('2d');
const width = canvas.width;
const height = canvas.height;
let numBalls = 1;
let grav = [0,-0.1];
//try feeding the ball function an object
//and destructuring the inputs
class Ball {
constructor (x, y, dx, dy, r) {
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.r = r;
//probably won't need this
//this.color = 'hsl(' + (Math.random() * 360) + ', 90%, 50%)';
}
draw() {
var thumbImg = document.createElement('img');
thumbImg.src = './svgs/javascriptIcon.svg';
thumbImg.onload = function() {
context.save();
context.beginPath();
context.arc(25, 25, 25, 0, Math.PI * 2, true);
context.closePath();
context.clip();
context.drawImage(thumbImg, 0, 0, 50, 50);
context.beginPath();
context.arc(0, 0, 25, 0, Math.PI * 2, true);
context.clip();
context.closePath();
context.restore();
};
}
It's been so long since I've used the html canvas. I can't figure out what I'm doing wrong. I thought I would at least be able to get the image to show up, but no such luck.
Thanks for checking it out! Please let me know what you think.
I am not sure why you are using ctx.clip,
but if you just want to replace the coloured balls with images try this in your draw method
this.draw = function() {
// make sure the img is loaded
//pen.fillStyle = this.color;
pen.beginPath();
pen.arc(this.x,this.y,this.r,0,2*Math.PI);
pen.drawImage(img,this.x, this.y,this.r, this.r)
pen.fill();
}
after that play with IMG x and y positions for example pen.drawImage(img,this.x + somefactor, this.y - somefactor,this.r + somefactor, this.r + somefatcor)
just to make sure that img is perfectly cover the coloured ball so it behavies just like it

How to work with timer in canvas javascript?

I need to make a rectangle appear randomly somewhere in the canvas, and then it will need to appear randomly in a new place, but I have one problem, it appears a new one but the previous rectangle stay where it was at the beginning and then there are so many rectangles in the canvas, I need to be only one, this is what I've done:
function rectangle(x,y){
var ctx
ctx.beginPath();
ctx.rect(20, 20, 15, 10);
ctx.stroke();
}
function randomMove(){
var myVar;
var x;
var y;
x = Math.floor(Math.random() * 10) + 1;
y = Math.floor(Math.random() * 10) + 1;
myVar = setInterval( ()=> {rectangle(x,y)}, 5000); // pass the rectangle function
}
You need to clear the canvas.
The easiest way is to draw a rectangle over entire canvas (assuming it's a white background)
ctx.fillStyle = "white";
ctx.fillRect(0, 0, width, height);
or if it is transparent...
ctx.clearRect(0, 0, width, height);
You will need to do this on every frame.
const ctx = window.canvas.getContext("2d");
function clearCanvas() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}
function rectangle(x, y) {
ctx.beginPath();
ctx.fillStyle = "red";
ctx.rect(x, y, 15, 10);
ctx.stroke();
}
function randomMove() {
var myVar;
var x;
var y;
x = Math.floor(Math.random() * ctx.canvas.width) + 1;
y = Math.floor(Math.random() * ctx.canvas.height) + 1;
rectangle(x, y);
}
function draw() {
clearCanvas();
randomMove();
}
myVar = setInterval(draw, 200);
draw();
<canvas id="canvas"></canvas>

Javascript canvas: Set own color for two different objects (squares)

I'm real frustrated with this problem.
So, I have following simple code:
var canvas = document.getElementById('canvasField');
var ctx = canvas.getContext('2d');
function Square(x, y, sizeOfSide) {
this.draw = function () {
ctx.beginPath();
ctx.moveTo(x,y);
ctx.lineTo(x + sizeOfSide, y);
ctx.lineTo(x + sizeOfSide, y + sizeOfSide);
ctx.lineTo(x, y + sizeOfSide);
ctx.lineTo(x,y);
ctx.closePath();
ctx.stroke();
}
this.setColor = function (color) {
ctx.fillStyle = color;
ctx.fill();
}
}
Square is my object. I can draw square and probably I can set fill-color for it. So next code works fine.
var square1 = new Square(100, 100, 100);
var square2 = new Square(250, 200, 100);
square1.draw();
square1.setColor('green');
square2.draw();
square2.setColor('yellow');
https://i.stack.imgur.com/gz50K.png
But If I change it to this:
var square1 = new Square(100, 100, 100);
var square2 = new Square(250, 200, 100);
square1.draw();
square2.draw();
square1.setColor('green');
square2.setColor('yellow');
it breaks down:
https://i.stack.imgur.com/Qeojl.png
It seems to me that I understand the reason. Two objects have the same context. And square2 sets color yellow for context and square1 loses his color. Maybe I am not right. I expected that they will be two independent objects and I'll be able to manipulate their conditions at any place in the code. I have no idea what to do next. Please help!
DEMO
var canvas = document.getElementById('canvasField');
var ctx = canvas.getContext('2d');
function Square(x, y, sizeOfSide) {
this.draw = function () {
ctx.beginPath();
ctx.moveTo(x,y);
ctx.lineTo(x + sizeOfSide, y);
ctx.lineTo(x + sizeOfSide, y + sizeOfSide);
ctx.lineTo(x, y + sizeOfSide);
ctx.lineTo(x,y);
ctx.closePath();
ctx.stroke();
}
this.setColor = function (color) {
this.draw();
ctx.fillStyle = color;
ctx.fill();
}
}
//var square1 = new Square(100, 100, 100);
//var square2 = new Square(250, 200, 100);
//square1.draw();
//square1.setColor('green');
//square2.draw();
//square2.setColor('yellow');
var square1 = new Square(100, 100, 100);
var square2 = new Square(250, 200, 100);
//square1.draw();
//square2.draw();
square1.setColor('green');
square2.setColor('yellow');
canvas {
border : 2px dotted blue;
}
<canvas id='canvasField' width=500 height=500></canvas>
Call the draw function of object inside setColor function. So it will draw the square first then will fill it using given color.
Most of time when you want to change something on a canvas, you have to draw it again. Your first block of code is good, if you want to change color of a square, use setColor then draw it again.

How to use Prototypal Pattern to make an html5 rectangle for reuse

I'm trying to understand Prototypal Inheritance using the Prototypal pattern by making a rectangle object and an instance of the rectangle. Seems easy, but I'm not getting it. The RectanglePrototype's method is not drawing the rectangle onto the canvas. If I use the same function as the method it works. Where am I going wrong? Also, I understand that I will need to make an initialization function, but I'm thinking I can do that later after I get the first basic steps down.
javascript:
window.onload = function () {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var RectanglePrototype = {
// Properties
x: 0,
y: 0,
width: 100,
height: 100,
color: "white",
// Method
get:function (x, y, width, height, color) {
context.translate(0 , 0);
context.beginPath();
context.rect(x, y, width, height);
context.fillStyle = color;
context.fill();
return this.x, this.y, this.width, this.height, this.color;
}
};
console.log(RectanglePrototype.get);
// Instance of RectanglePrototype
var rectangle1 = Object.create(RectanglePrototype);
rectangle1.x = 200;
rectangle1.y = 100;
rectangle1.width = 300;
rectangle1.height = 150;
rectangle1.color = '#DBE89B';
// Draw Rectangle Function
function rect(x, y, width, height, color) {
context.translate(0 , 0);
context.beginPath();
context.rect(x, y, width, height); // yLoc-canvas.height = -300
context.fillStyle = color;
context.fill();
};
rect(0, 450, 50, 50, '#F7F694');
}
</script>
Prototypes are extensions of objects that result from a constructor. Method lookups go through the object properties before looking into prototype.
I proper JS design, you would only add the non-function properties in your constructor.
//Your constructor
function Rectangle(){
// Properties
this.x = 0;
this.y = 0;
this.width = 100;
this.height = 100;
this.color = 'red';
}
And then put the methods in your prototype:
//I prefer the term 'draw'
Rectangle.prototype.draw = function(ctx){
ctx.save();
ctx.beginPath();
ctx.rect(this.x, this.y, this.width, this.height);
ctx.fillStyle = this.color;
ctx.fill();
ctx.restore();
};
Then, to use in your project:
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
//List of your shapes to draw on the canvas
var shapes = [];
//Instance of Rectangle
var rectangle1 = new Rectangle();
rectangle1.x = 200;
rectangle1.y = 100;
rectangle1.width = 300;
rectangle1.height = 150;
rectangle1.color = '#DBE89B';
shapes.push(rectangle1);
//Draw your shapes
function draw(){
window.requestAnimationFrame(draw); //See MDN for proper usage, but always request next fram at the start of your draw loop!
for(var i = 0; i<shapes.length; i++){
shapes[i].draw(context);
}
}
This is the 'proper' way of drawing to the canvas. For anything larger scale, please look into existing engines that do a looooot of hard work for you and have thought of everything so you don't have to. I have worked on such engines.

Categories

Resources