JavaScript OO Vector Graphics Package | 2 | WebReference

JavaScript OO Vector Graphics Package | 2

To page 1current page
[previous]

JavaScript OO Vector Graphics Package

Lastly, a clear() method iterates through the whole shapes collection and removes all of them.

Graphics.prototype.clear = function() 
{
   for ( var i in this.shapes )
      this.removeShape(this.shapes[i]);
}

Now we are ready to start implementing some Shape classes to add to the graphics package. The first one we’ll look at is the line.

There needs to be a method to call on the Graphics object to draw the line. A new Line object is created and passed to the addShape() method so that it may be drawn upon the canvas.

Graphics.prototype.drawLine = function(x1,y1,x2,y2) 
{
   return this.addShape(new Line(x1,y1,x2,y2))
}

The Line constructor records the start and end points. These will be used later in the draw() method.

function Line(x1,y1,x2,y2) 
{
   this.x1 = x1;
   this.y1 = y1;
   this.x2 = x2;
   this.y2 = y2;
}

The draw() method calculates all the points from the start to the end and creates plot-elements for each. Note that for brevity, I haven’t used the Bresenham algorithm here. In fact, it is unlikely that there would be much difference in performance, because unlike traditional graphics platforms, creating the plot-elements is an expensive operation and the extra effort to avoid floating point calculations will make little difference.

Line.prototype.draw = function() 
{
   this.plots = new Array;
   var dx = this.x2 - this.x1;
   var dy = this.y2 - this.y1;
   var x = this.x1;
   var y = this.y1;
   var n = Math.max(Math.abs(dx),Math.abs(dy));
   dx = dx / n;
   dy = dy / n;
   for ( i = 0; i <= n; i++ ) {
      this.plots.push(
         this.oGraphics.createPlotElement(Math.round(x),Math.round(y),1,1));
      x += dx;
      y += dy;
   }
   }

The undraw() method iterates through each plot-element generated in the draw() method and releases each one to the Graphics object cache.

Line.prototype.undraw = function() 
{
   while ( this.plots.length )
      this.oGraphics.releasePlotElement(this.plots.pop());
   this.plots = undefined;
}

A similar set of functions can be generated to draw circles. Once again I haven’t put much effort into optimizing the algorithm (that’s outside the scope of this article).

Graphics.prototype.drawCircle = function(x,y,r) 
{
   return this.addShape(new Circle(x,y,r))
}
function Circle(x,y,r) 
{
   this.x = x;
   this.y = y;
   this.radius = r;
}
   Circle.prototype.draw = function() 
{
   this.plots = new Array;
   var r2 = this.radius * this.radius;
   var x = 0;
   var y = this.radius;
 while ( x <= y ) {
   this.plots.push(this.oGraphics.createPlotElement(
      Math.round(this.x + x), Math.round(this.y + y), 1, 1));
   this.plots.push(this.oGraphics.createPlotElement(
      Math.round(this.x - x), Math.round(this.y + y), 1, 1));
   this.plots.push(this.oGraphics.createPlotElement(
      Math.round(this.x + x), Math.round(this.y - y), 1, 1));
   this.plots.push(this.oGraphics.createPlotElement(
      Math.round(this.x - x), Math.round(this.y - y), 1, 1));
   this.plots.push(this.oGraphics.createPlotElement(
      Math.round(this.x + y), Math.round(this.y + x), 1, 1));
   this.plots.push(this.oGraphics.createPlotElement(
      Math.round(this.x + y), Math.round(this.y - x), 1, 1));
   this.plots.push(this.oGraphics.createPlotElement(
      Math.round(this.x - y), Math.round(this.y + x), 1, 1));
   this.plots.push(this.oGraphics.createPlotElement(
      Math.round(this.x - y), Math.round(this.y - x), 1, 1));
   x++;
   y = Math.round(Math.sqrt(r2 - x*x));
 }
}
// The implementation of Circle.undraw is identical to Line.undraw
Circle.prototype.undraw = Line.prototype.undraw;

There is no real limit to the complexity that shapes can take. Shapes could even use other shapes as primitives, so long as they implement draw() and undraw() methods appropriately.

All that is left now is to demonstrate how to use the graphics package. The following code draws two lines (red and green) in the shape of an X, and a blue circle.

<html>
<head>
<script type=”text/javascript”>
   // insert the graphics code here.
</script>
<script type=”text/javascript”>
function drawShapes() 
{
   gr.penColor = "red";
   gr.drawLine(10,10,190,190);
   gr.penColor = "green";
   gr.drawLine(190,10,10,190);
   gr.penColor = "blue";
   gr.drawCircle(100,100,45);
}
</script>
</head>
<body onload="drawShapes();">
   Check out the graphics:
   <div id="theCanvas" style="position:relative; width:200px;    height:200px; overflow:hidden;"></div>
</body>
</html>

Conclusion

Since the intention of this article was to introduce the basic framework there are several omissions, which I was unable to cover here. These include but are not limited to:

• More optimal algorithms. For example, the circle algorithm above plots some points more than once.

• Merging plot-elements; plot-elements of the same color that are adjacent horizontally or vertically could be optimized by combining them together to minimize the load on the browser.

• More sophisticated graphics settings like penWidth.

• More shapes like ellipses, rectangles, filled shapes, bezier curves and text.

In this article I have introduced an object-oriented framework for drawing vector-based graphics using only JavaScript. A <DIV> element is used as a canvas and small pixel sized <DIV> elements are added as children to render the graphics shapes. The graphics package is extensible as it allows a developer to add new shapes by implementing them as JavaScript classes and inserting the appropriate JavaScript functions and methods to the Graphics prototype.

For a working example of this graphics framework, visit: http://www.silver-daggers.co.uk/demo/graphics.html

About the Author

Guyon Roche is a freelance web developer in London, Great Britain. He specializes in Windows platforms with an interest in bridging the gaps between different technologies, see www.silver-daggers.co.uk for details. He can be reached via e-mail at guyonroche@silver-daggers.co.uk.

To page 1current page
[previous]

Created: June 5, 2003
Revised: January 14, 2004

URL: http://webreference.com/programming/javascript/jf/1