Hello everyone. How about making world better? Sounds good.
Do you know that JavaScript doesn't allow drawing? I wanted to create some drawing capabilities for some reason. However, it won't be very important, if your web site is built using ASP.NET technology. There is a great way for generating images dynamically in asp.net.
A little more difficulties are met while using PHP, or no server side scripting. I remember once I had a web-site written in PHP, but a hosting server was not supporting image generating. Thus, I had no chance to draw any user friendly images to the client browser.
And of course, there is no way to generate any kind of images without server side script hosting.
Yesterday I decided to write a little JavaScript code. And today I want to consider that code with you.
My only wish was, to create some drawing capabilities, as simple as possible. Sometimes a human wants to terminate the borders, so called Rules. In the end of this article you will understand that there can be created something for drawing purposes in JavaScript.
As there is nothing for drawing in JavaScript, the first thing that I needed is something that would be a drawing board, and as long as JavaScript works well with HTML components (furthermore, it's created for working with HTML components), I decided to use them as a boards. Decision stopped on the html DIV component. So I placed the DIV on my empty HTML page.
Then the logic built itself from the scratch.
What is drawing? What means to draw a line, a circle, rectangle, etc.? Any of them contain points, right? Anything can be drawn if we can draw a point. So, let's start thinking how we can do that.
I remember my first impression, when I looked at the picture containing just a point very closely. When I zoomed into a 500%, I was surprised; point became a rectangle, great effect of the computer technologies. Think of that as a great point to start from, indeed everything placed on the HTML page is displayed like rectangles. Did you catch an idea? Yes, I mean that we can create a component on the drawing board (actually HTML DIV component), with a very little sizes, and believe me, that wouldn't be nothing else than a point. Let's see how I wrote a code:
function Graphics_DrawPoint(x,y)
{
var div = document.getElementById(DivID);
var point = document.createElement("<div>");
point.style.position="absolute";
point.style.top=document.body.offsetTop + div.offsetTop + y;
point.style.left=document.body.offsetLeft + div.offsetLeft + x;
point.style.backgroundColor=Brush_Color;
point.style.width=Brush_Size;
point.style.height=Brush_Size;
div.appendChild(point);
}
Now, as we can draw a point, we can draw a line as well. The only thing we need is to remember a formula of line from the mathematics. As a theory says, if we have two points (x0,y0) and (x1,y1), then any (x,y) point on the line will satisfy the following formula: (x-x0)/(x1-x0) = (y-y0)/(y1-y0). So how can we use that? If given two points, we must generate all the points between them. Of course it will be easier if we generate only one from the pair of coordinates, and then calculate another one using the first one. So, functions calculating x using y and vice versa will look like this:
function Graphics_CalculateLineX(y,x0,x1,y0,y1)
{
return ((y-y0)*(x1-x0)/(y1-y0))+x0;
}
function Graphics_CalculateLineY(x,x0,x1,y0,y1)
{
return ((x-x0)*(y1-y0)/(x1-x0))+y0;
}
and after these functions we can of course write a function that will draw a line (having in mind the fact we already can draw a point):
function Graphics_DrawLine(x0,y0,x1,y1)
{
var x;
var y;
if (Math.abs(x0-x1)>Math.abs(y0-y1))
{
x = Math.min(x0,x1);
while (x<x1)
{
y=Graphics_CalculateLineY(x,x0,x1,y0,y1);
Graphics_DrawPoint(x,y);
x++;
}
}
else
{
y = Math.min(y0,y1);
while (y<y1)
{
x=Graphics_CalculateLineX(y,x0,x1,y0,y1);
Graphics_DrawPoint(x,y);
y++;
}
}
}
Very easy, isn't it?
Now let's think a little about a fact, that all these functions are executed on the client machine, meaning that they are using a memory of the client machine. As more points are drawn as more memory is needed. But don't forget a fact that: in our days, when the internet network is developing and growing, this must not be a problem. Any web page, that is accessed across the web, using a simple HTML browser, parses and displays a large amount of HTML components. To prove that, you can open any average size web site and view it's HTML source. But anyway, trying to make a world better must not become a warranty of memory overflow. Yes, a developer must make a decision to make a little pressing on the client machine during execution of some code, if there's no other way to do that. My next functions will show that some drawing purposes can be achieved without crating a large amount of points dynamically.
Next step is to draw a rectangle. As mentioned above, I'm not going to draw the rectangle using lines, because in this case I consider a rectangle that is positioned so as its sides are parallel to the edges of our screens. Any other king of rectangles, or polygons, can be drawn using a line drawing functions. In my case, rectangle is the same starting point, saying that every component on an html page is a simple rectangle. So, a task of drawing rectangle becomes a task of creating a transparent component that displays only borders. Those borders will appear as a rectangle itself. It will work fast, and the solution will be the same as needed:
function Graphics_DrawRectangle(x0,y0,x1,y1)
{
var div = document.getElementById(DivID);
var rect = document.createElement("<div>");
rect.style.position="absolute";
rect.style.top=document.body.offsetTop + div.offsetTop + Math.min(y0,y1);
rect.style.left=document.body.offsetLeft + div.offsetLeft + Math.min(x0,x1);
rect.style.background="transparent";
rect.style.border=Brush_Color + " " + Brush_Size + "px solid";
rect.style.width=Math.abs(x1-x0);
rect.style.height=Math.abs(y1-y0);
div.appendChild(rect);
}
I don't want to waste a time explaining how to create a function that will allow us drawing a filled rectangle. Think a little about it.
An interesting step is to draw a circle. Let's again, remember a little mathematics. Again, a formula says that if we draw a circle with center at point with coordinates (0,0) then any point with coordinates (x,y) satisfies any of the next two formulas: 1) x*x + y*y = r*r. 2) sin(alpha) = y/r, cos(alpha) = x/r. where alpha is an angle calculated in the backward direction of a clock. First formula is a little more difficult to use, because calculating all x and y coordinates will take a little more time. It's easier to change alpha from 0 to 360 and find all the coordinates. But wait, the circle's bottom side repeats it's upper side, so we can calculate only one side from them and draw the same points as transformed to the middle line of the circle... But wait again, we can see that a part of circle contained between angles 90 and 180 repeats a part contained between angles 0 and 90, and applying the same logic we can calculate only a one-forth part of the circle and draw all other points as transformed to the middle line in horizontal or in vertical direction. And one more thing, as I found the topic in the documentation, JavaScript Math.sin() function needs a parameter in radians, not in degrees. So a function looks like this:
function Graphics_DrawCircle(x,y,r)
{
var div = document.getElementById(DivID);
var alpha = 0;
while (alpha <= (Math.PI/2))
{
var x1 = r * Math.cos(alpha);
var y1 = r * Math.sin(alpha);
Graphics_DrawPoint(x+x1,y+y1);
Graphics_DrawPoint(x+x1,y-y1);
Graphics_DrawPoint(x-x1,y+y1);
Graphics_DrawPoint(x-x1,y-y1);
alpha += (Math.PI/180);
}
}
Ok. I think I have explained a big amount of my thoughts about JavaScript drawing capabilities. All the code can be found in the attached file. I just changed a code so that callings to these functions look like object oriented, like this:
var g = new Graphics("divContainer");
g.Brush.Color='green';
g.DrawLine(10,10,200,50);
There are also added a little more functions, like displaying a string and filling a rectangle, and of course drawing an arc. You can add more and more functions as your needs request.
When you can use it?
For example, when displaying a result of user surveys on the page, and indeed without any ready images saved on the server. A simple shape can be drawn without any other tools.
I hope you found something interesting here, in this topic.
Have a good day!
Attached File: Sample.htm