4
\$\begingroup\$

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();
});
asked Jul 5, 2013 at 2:57
\$\endgroup\$
1
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Jul 5, 2013 at 6:33

1 Answer 1

2
\$\begingroup\$

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();
answered Jul 5, 2013 at 3:13
\$\endgroup\$
2
  • \$\begingroup\$ 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? \$\endgroup\$ Commented Jul 5, 2013 at 3:30
  • \$\begingroup\$ @Abe With the encapsulation, it also allows to have multiple axis objects which are tied to canvas objects. \$\endgroup\$ Commented Jul 5, 2013 at 6:29

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.