Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I am doing some tests with html5 Canvas object. At the same time I am trying to make my javascript code more modular. In the following code, where/how should I declare canvas and context, so that it can be shared with other objects? Please provide general comments/improvements?

Output:

enter image description here

Code:

$( document ).ready(function() {

    var axis = {
        LEFT_INDENT : 100,  
        START_WORK_HOUR : 8,
        END_WORK_HOUR : 17,
        HOURS_IN_WORKDAY : 0,
        CANVAS_WIDTH : 0,
        CANVAS_HEIGHT : 0,
        AXIS_SIDE_MARGIN : 20,
        AXIS_TOP_MARGIN : 40,
        AXIS_ORIGIN : new Array(),  
        AXIS_RIGHT : 0,
        TICK_INCREMENT :  0,

        setup: function(){

            // assumes that I have <canvas id="myCanvas" width="800" height="300"></canvas>  in the HTML
            this.canvas = document.getElementById('myCanvas');
            this.context = this.canvas.getContext('2d');

            this.HOURS_IN_WORKDAY = this.END_WORK_HOUR - this.START_WORK_HOUR;
            this.CANVAS_WIDTH = this.canvas.width;
            this.CANVAS_HEIGHT = this.canvas.height;

            this.AXIS_ORIGIN = { x: this.AXIS_SIDE_MARGIN,
                            y: this.AXIS_TOP_MARGIN };

            this.AXIS_RIGHT = this.canvas.width-this.AXIS_SIDE_MARGIN;

            this.TICK_INCREMENT = (this.CANVAS_WIDTH-this.LEFT_INDENT-(2*this.AXIS_SIDE_MARGIN))/this.HOURS_IN_WORKDAY; 
            this.AXIS_RIGHT = this.canvas.width-this.AXIS_SIDE_MARGIN;
        },

        draw_lines: function(){
            this.context.beginPath();
            this.context.moveTo(this.LEFT_INDENT, this.AXIS_ORIGIN.y);
            this.context.lineTo(this.AXIS_RIGHT,  this.AXIS_ORIGIN.y)
            this.context.stroke();
            this.counter = this.START_WORK_HOUR;

            for(x=this.AXIS_SIDE_MARGIN+this.LEFT_INDENT ; x < this.AXIS_RIGHT ; x = x + this.TICK_INCREMENT){
                // grid lines
                this.context.beginPath();
                this.context.moveTo(x,30);
                this.context.lineTo(x,50)
                this.context.stroke();

                // background line - top to bottom
                this.context.save();   
                this.context.fillStyle = "#F0F8FF";
                this.context.beginPath();
                this.context.lineWidth = .1;
                this.context.moveTo(x,30);
                this.context.lineTo(x,this.CANVAS_HEIGHT-20)
                this.context.stroke();
                this.context.restore();   

                // text     
                this.context.font = "14px Arial";
                this.context.fillStyle = "#011f5b";     
                this.counter++;
                this.context.fillText(this.counter+":00",x-7,20);       
            }   
        }
    }
    axis.setup();
    axis.draw_lines();
});
share|improve this question

migrated from stackoverflow.com Jul 7 '13 at 1:25

This question came from our site for professional and enthusiast programmers.

    
I'm not sure this will be helpful, but I created a github project called brushes.js which somewhat tries to encapsulate brushes to draw on a canvas. There are unit tests and examples. –  Jim Schubert Jul 5 '13 at 6:33
add comment

1 Answer

You can wrap the functionality in an object. You instantiate it with a canvas element and some configuration options.

(function($) {

// config defaults    
var defaults = {
    LEFT_INDENT: 100,
    START_WORK_HOUR: 8,
    END_WORK_HOUR: 17,
    AXIS_SIDE_MARGIN: 20,
    AXIS_TOP_MARGIN: 40
};

// constructor
axis = function(canvas, config)
{
    this.config = $.extend({}, defaults, config);
    this.canvas = canvas;

    this.setup();
}

// define prototype functions
axis.prototype.setup = function() {
    this.context = this.canvas.getContext('2d');

    this.HOURS_IN_WORKDAY = this.config.END_WORK_HOUR - this.config.START_WORK_HOUR;
    this.CANVAS_WIDTH = this.canvas.width;
    this.CANVAS_HEIGHT = this.canvas.height;

    this.AXIS_ORIGIN = {
        x: this.config.AXIS_SIDE_MARGIN,
        y: this.config.AXIS_TOP_MARGIN
    };

    this.AXIS_RIGHT = this.canvas.width - this.config.AXIS_SIDE_MARGIN;

    this.TICK_INCREMENT = (this.CANVAS_WIDTH - this.config.LEFT_INDENT - 2*this.config.AXIS_SIDE_MARGIN)) / this.HOURS_IN_WORKDAY;
}

axis.prototype.draw_lines = function() {
    this.context.beginPath();
    this.context.moveTo(this.LEFT_INDENT, this.AXIS_ORIGIN.y);
    this.context.lineTo(this.AXIS_RIGHT,  this.AXIS_ORIGIN.y)
    this.context.stroke();
    this.counter = this.config.START_WORK_HOUR;

    for(x = this.config.AXIS_SIDE_MARGIN + this.config.LEFT_INDENT ; x < this.AXIS_RIGHT ; x = x + this.TICK_INCREMENT) {
        // grid lines
        this.context.beginPath();
        this.context.moveTo(x,30);
        this.context.lineTo(x,50)
        this.context.stroke();

        // background line - top to bottom
        this.context.save();   
        this.context.fillStyle = "#F0F8FF";
        this.context.beginPath();
        this.context.lineWidth = .1;
        this.context.moveTo(x,30);
        this.context.lineTo(x, this.CANVAS_HEIGHT - 20)
        this.context.stroke();
        this.context.restore();   

        // text     
        this.context.font = "14px Arial";
        this.context.fillStyle = "#011f5b";     
        this.counter++;
        this.context.fillText(this.counter+":00",x-7,20);       
    }   
}

}(jQuery));

To use it:

var a = new axis(document.getElementById('myCanvas'), {
     // whatever you want to override
});
a.draw_lines();
share|improve this answer
    
my god, there are so many ways of doing things in javascript! If I understand you group variables in its own array. The "axis" methods and properties do not have to be wrapped and grouped together. You are instantiating the axis object with the "new" verb then run the constructor within the object. Code is a bit neater, and setup is done within the class. What other advantages does this way offer? –  Abe Jul 5 '13 at 3:30
    
@Abe With the encapsulation, it also allows to have multiple axis objects which are tied to canvas objects. –  Jack Jul 5 '13 at 6:29
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.