0

I have created 2 object. One creates a canvas object and append it to the body of the html and another one should draw a rectangle which isn't. What am I doing wrong?

window.onload = function(){


    var oCanvas = {

        canvas : document.createElement("canvas"),
        ctx : document.createElement("canvas").getContext("2d"),

        create : function(){
            oCanvas.canvas.id = "canvas";
            oCanvas.canvas.width = 350;
            oCanvas.canvas.height = 350;
            oCanvas.canvas.style.background = "yellow";
            document.body.appendChild(oCanvas.canvas);

        }
    };
    var oMap = {
        createGrid : function(){
            oCanvas.ctx.fillRect(50, 25, 150, 100);
        }
    };

    oCanvas.create();
    oMap.createGrid();

};
Jack
  • 2,750
  • 2
  • 27
  • 36
Artskee
  • 59
  • 1
  • 4

4 Answers4

2

To use methods that self-references you can do it this way instead -

  • Create an object with an constructor instead - otherwise you won't be able to reference its definitions until after the object has been assigned to a variable causing errors.
  • Create a new instance of the object using the new keyword.

Now you can further improve it by using for example prototypes, but for simplicity:

function myCanvas() {

    /// create a reference to ourselves (saves us some headache later)
    var me = this;

    /// create a canvas as a property on this instance
    this.canvas = document.createElement("canvas");

    /// now this.canvas exists and we can get the context
    this.ctx = this.canvas.getContext("2d"),

    /// metod create which references 'me'
    this.create = function(){
        me.canvas.id = "canvas";
        me.canvas.width = 350;
        me.canvas.height = 350;
        me.canvas.style.background = "yellow";
        document.body.appendChild(me.canvas);
    }
};

/// create an instance (you can create several of this)
var oCanvas = new myCanvas();

Now it will work as you can see in this demo.

  • Well, that's what I was trying to achieve with the object notation as you could see, with bad results. I also though about doing it your way but didn't want to confuse the OP with the `new Canvas()` stuff etc. + for your answer. I would pick this one. – matewka Nov 15 '13 at 20:23
  • Thanks @matewka. I added some more comments to hopefully make the changes a bit more clear for OP. –  Nov 15 '13 at 20:26
1

You're creating two separate canvases. When defining ctx property, you should refer to the canvas property, created before. Remove the ctx from the object definition and add it below, once the object is already defined:

var oCanvas = {

    canvas : document.createElement("canvas"),
    ...
}
oCanvas.ctx = oCanvas.canvas.getContext("2d");
matewka
  • 9,912
  • 2
  • 32
  • 43
  • This won't work as `this.canvas` is not defined at this point. http://jsfiddle.net/AbdiasSoftware/42qrA/ –  Nov 15 '13 at 20:11
  • @KenFyrstenberg I also didn't expect it to work but tested it on jsfiddle and it worked for the first time. Strange. – matewka Nov 15 '13 at 20:13
  • I get `TypeError: this.canvas is undefined` in console FF, `Uncaught TypeError: Cannot call method 'getContext' of undefined ` in Chrome, no errors in yours? –  Nov 15 '13 at 20:13
  • Now I also have errors but when I run the code for the first time, everything went fine. Maybe jsFiddle cached it somehow. I don't know. I'll fix the answer ASAP. – matewka Nov 15 '13 at 20:15
  • The reason is that the assigned object to the var is not defined yet so we cannot self-reference it as it is undefined. We could always add it after the object had been assigned to the var (oCanvas). –  Nov 15 '13 at 20:17
  • @KenFyrstenberg I'm completely aware of that what you say. I just wanted to test it first in the jsFiddle to make sure it won't work. But somehow it worked (only once). Anyway, I updated the code. – matewka Nov 15 '13 at 20:19
0

UPDATE: Seems I was beat, and this is a better solution: https://stackoverflow.com/a/20009730/1634430

You are creating 2 elements, and drawing in the wrong one. Solution is here: http://codepen.io/zshift/pen/gxoEA.

instead of

...
canvas : document.createElement("canvas"),
ctx : document.createElement("canvas").getContext("2d"),
...

you should write

var element = document.createElement("canvas");

...
canvas: element,
ctx: element.getContext("2d"),
...
Community
  • 1
  • 1
zshift
  • 341
  • 5
  • 10
0

If this is a single object you can leave it as a object literal but if you were to create multiple instances then you can use constructor functions and prototype. An introduction to constructor functions and prototype can be found here.

Assuming there is only one oCanvas instance in use you can change your code to:

var oCanvas = {

    canvas : document.createElement("canvas"),
    ctx : null,/can't set it to anything yet
          //oCanvas doesn't exist yet here

    create : function(){
        oCanvas.canvas.id = "canvas";
        oCanvas.canvas.width = 350;
        oCanvas.canvas.height = 350;
        oCanvas.canvas.style.background = "yellow";
        document.body.appendChild(oCanvas.canvas);
        //set the context now
        this.ctx = this.canvas.getContext("2d");
    }
};
var oMap = {
    createGrid : function(){
        oCanvas.ctx.fillRect(50, 25, 150, 100);
    }
};

oCanvas.create();
oMap.createGrid();
Community
  • 1
  • 1
HMR
  • 37,593
  • 24
  • 91
  • 160