Which was is it to best declare a property in JavaScript? - javascript

If you are building a function type class in JavaScript when you declare a variable is it better to do it with
var this.variableName = variableName
var this.x = x
or is it better to just do it like this.
this.x
I tried using the var and it gave an error in Google debuger. Why would this be the case or are properties different than a variable that is set in a function "object".
Code:
function Circle(x,y,r) {
this.x = x;
this.y = y;
this.r = r;
// I've added the drawing code to the actual circle
// they can draw themselves.
this.draw = function(context){
context.beginPath();
context.arc(this.x, this.y, this.r, 0, Math.PI*2, true);
context.closePath();
context.fill();
}
}

When an object is declared, it is already declared, so doing something like this is, not only illegal, but also redundant.
// DON'T DO THIS!!!
var this.a = 'a'; // NO!!!!!!!!!
Instead, just declare your object and then just append things to that object, since it's already initialized
var obj = {};
obj.a = 'a';
obj.b = 'b';
The problem you'll probably face when declaring a function in your object is a matter of scope and how this works in Javascript.
For this, you have a couple of alternatives:
Declare a that variable that you can then use in your function:
function Circle(x,y,r) {
this.x = x;
this.y = y;
this.r = r;
// I've added the drawing code to the actual circle
// they can draw themselves.
var that = this;
this.draw = function(context){
// this refers to the global object (window)
// that refers to your Circle Object
context.beginPath();
context.arc(that.x, that.y, that.r, 0, Math.PI*2, true);
context.closePath();
context.fill();
}
}
If you're using an ECMAScript 5 supported browser (not IE8), you can bind the function to your Circle object.
function Circle(x,y,r) {
this.x = x;
this.y = y;
this.r = r;
// I've added the drawing code to the actual circle
// they can draw themselves.
this.draw = function(context){
context.beginPath();
context.arc(this.x, this.y, this.r, 0, Math.PI*2, true);
context.closePath();
context.fill();
}.bind(this);
}
If you want to support IE8 and use .bind, you can just use underscore.js and use the _.bind function.
function Circle(x,y,r) {
this.x = x;
this.y = y;
this.r = r;
// I've added the drawing code to the actual circle
// they can draw themselves.
this.draw = _.bind(function(context){
context.beginPath();
context.arc(this.x, this.y, this.r, 0, Math.PI*2, true);
context.closePath();
context.fill();
}, this);
}

Related

html canvas javascript fill and stroke methods

I am working on creating squares with HTML canvas and javascript. However, it is glitchy. I don't understand why. I have created two javascript objects, one for hollow blocks, one for filled blocks. I am iterating through both arrays to create the blocks at animate. However, I can only get one filled block at a time. I have not been able to have more than one at a time. However, I am successful creating hollow blocks. The code is the same, but it does not work the same. Why is that?
function hBlock(h,w,x,y){
this.h = h;
this.w = w;
this.x = x;
this.y = y;
this.create = function(){
ctx.rect(x,y,w,h);
ctx.stroke();
}
}
function fBlock(h,w,x,y){
this.h = h;
this.w = w;
this.x = x;
this.y = y;
this.create = function(){
ctx.fillRect(x,y,w,h);
}
}
function newblock(){
if(f==1){fBlocks.push(new fBlock(h,w,x,y));}
else{hBlocks.push(new hBlock(h,w,x,y));}
console.log(hBlocks);
console.log(fBlocks);
animate();
}
function animate(){
requestAnimationFrame(animate);
ctx.clearRect(0, 0, cw, ch);
if(hBlocks.length>1){hBlocks[hBlocks.length-1].create();}
if(fBlocks.length>1){fBlocks[fBlocks.length-1].create();}
}

making a class of shapes that know how to draw themselves

I would like to know how to get this to work. The argument
g of the function draw is to be the graphics context of a JavaScript canvas object.
What I want is to be able to say is
var c = document.getElementById("canvas");
var g = c.getContext("2d");
b = new Ball(300,200, 50, "red");
b.draw(g)
and have a red ball paint at the center (300,200) of radius 50px.
Here is the code for the class.
class Ball
{
constructor(x, y, radius, color)
{
this.x = x;
this.y = y;
this.radius = radius
this.color=color;
}
draw(g)
{
console.log(g.fillStyle);
g.fillStyle = this.color;
g.beginPath()
//g.arc(this.x, this.y, this.r, 0, 2*Math.PI);
//correct is below.....
g.arc(this.x, this.y, this.radius, 0, 2*Math.PI);
g.fill();
}
}
Thank you for any help you can supply. Please note I have enabled ECMA6 in my browser. The console is not raising any error messages.
You've got a type-o in draw(). Change this.r to this.radius to match the constructed variable.

ES6 class methods not a function

I'm messing around with Javascript "classes" and I have a paddle that has a proper method to draw, but for some reason my moveBall function is messed up. Could anyone point out why? I get an error saying that moveBall() is not a function.
Edit: I included some more code, I call init() to start it all.
class Ball {
constructor(x, y, r, sAngle, rAngle) {
this.x = x;
this.y = y;
this.r = r;
this.sAngle = sAngle;
this.rAngle = rAngle;
this.speed = null;
}
drawBall() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, this.sAngle, this.rAngle);
ctx.fillStyle = "#FF0000";
ctx.fill();
}
moveBall() {
this.x += this.speed;
}
}
function init() {
var ball = new Ball(c.height / 2, c.width / 2, 10, 0, 2 * Math.PI);
var paddleLeft = new Paddle(0, 0, 20, 100);
ball.ballPhysics = 1.0;
draw(ball, paddleLeft);
main(ball);
}
window.main = function (ball) {
window.requestAnimationFrame(main);
ball.moveBall();
window.onload = function () {
document.addEventListener('keydown', function (event) {
if (event.keyCode === 65) {
}
}, false);
}
};
If you are using it like Ball.moveBall() than it's incorrect, you must instantiate Ball class first or use static methods like
class A {
static f() {
}
}
and call like
A.f();
otherwise check the snippet below
class Ball {
constructor(x, y, r, sAngle, rAngle) {
this.x = x;
this.y = y;
this.r = r;
this.sAngle = sAngle;
this.rAngle = rAngle;
this.speed = null;
}
drawBall() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, this.sAngle, this.rAngle);
ctx.fillStyle = "#FF0000";
ctx.fill();
}
moveBall() {
this.x += this.speed;
}
}
var greenBall = new Ball(0, 0 , 10, 0, 0);
greenBall.speed = 5;
greenBall.moveBall();
document.write(greenBall.x);
make sure you have an instance of ball in the scope of the code you are trying to run, and try var moveball = function(){this.x += this.speed; }; to see if it's a compile issue, and make sure you are accessing it like ball.moveball()
You define main to accept an argument ball. But you are never calling main, so you cannot pass an argument to it.
While window.requestAnimationFrame(main); will call the function, it won't pass anything to it.
It seems you want to refer to the ball variable that is defined inside init. In that case, remove the parameter ball from the function definition so that it doesn't shadow that variable:
window.main = function() { ... };
You also don't want to assign to window.onload inside main, because that wouldn't happen over and over again.

how to make modular, oo "animations" with canvas / JavaScript?

I come from a flash animation background, and am learning to create animations with HTML5 <canvas> and plain JavaScript.
In flash, you can draw a movieclip and link it to an actionScript class file. This makes each movieclip somewhat OO / modular and allows you to more easily call and reference them in your app.
As JS has no native class support, and drawing with Canvas seems more rudimentary than in Flash, what is an example of a way to structure your javascript for a large/complex canvas animation?
You can use a pseudo-class approach by using objects.
For example, if you want to lets say move a box across the canvas you define the box as an object and update it for each frame:
Live demo
function ooRect(x, y, w, h, color, dx, dy) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
this.dx = dx;
this.dy = dy;
}
Now ooRect is an object which you can update to move around and change color etc.
You can extend it with methods which makes it self-contained update-wise so it updates itself per frame:
function ooRect(x, y, w, h, color, dx, dy) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
this.dx = dx;
this.dy = dy;
this.update = function(ctx) {
this.x += this.dx;
this.y += this.dy;
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.w, this.h);
}
}
You can now have a "host" routine (or another special object) to update all your objects stored in the array:
var objects = [
new ooRect(10, 20, 50, 70, 'blue', 2, 3),
new ooRect(200, 300, 50, 70, 'red', -3, 2) /// etc.
];
(function loop() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); /// clear canvas
for(var i = 0, o; o = objects[i++];) /// update all objects
o.update(ctx);
requestAnimationFrame(loop); /// next frame
})();
Now it is a matter of implementing different types of shape objects with its properties and methods.
If you plan to use a lot of objects you can prototype them as that allow the browser to share code-base memory:
function ooRect(x, y, w, h, color, dx, dy) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
this.dx = dx;
this.dy = dy;
}
ooRect.prototype.update = function(ctx) {
this.x += this.dx;
this.y += this.dy;
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.w, this.h);
}
Go with requirejs which is JavaScript file and module loader.
http://requirejs.org/

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