Tuesday, August 19, 2014

Drawing Line Using Javascript


Updated on 27th of August: Please use the 2nd version of my drawLine() function (scroll to the bottom of this page) if possible. The first version has a lots of flaws which may not draw the line correctly in certain situation.



With HTML5 coming hot and jQuery to be well received by web developers, Javascript is now a frozen cake from the fridge. Especially when it comes to drawing shapes on browsers, Javascript will be receiving less and less focus especially when HTML5 flocks into web applications someday.

Although Javascript is becoming less and less important, I still post my way of drawing lines on browsers using Javascript due to the fact that Javascript is still a good educational language for beginners to start with. The readability of jQuery is too low and may turn some newcomers away. That is why I still insist on posting Javascript goodies here. Hope this last piece of cake does not end up in the dumpster.

Note: The anti-alias version can be found here.

Here we go (the codes):


<html>

<script>

var spanTag,red,green,blue; // declare these as global
var colorChannel; // to save resources

function mkDot(x,y,color) {

  colorChannel = color.match(/\#(\w\w)(\w\w)(\w\w)/); // match out RGB
  red = parseInt(colorChannel[1],16);
  green = parseInt(colorChannel[2],16);
  blue = parseInt(colorChannel[3],16);

  spanTag = document.createElement("span");
  spanTag.innerHTML = '<img src="dummy1x1.png" height=1 width=1>';// You need a 1x1 dummy transparent PNG image as foreground
  spanTag.style.position = "absolute";
  spanTag.style.zIndex = 1; // In case you have other elements on the same page
  spanTag.style.left = x + "px";
  spanTag.style.top = y + "px";

  red = red>=16?red.toString(16):"0"+red.toString(16); // convert to HEX
  green = green>=16?green.toString(16):"0"+green.toString(16);
  blue = blue>=16?blue.toString(16):"0"+blue.toString(16);
  spanTag.style.backgroundColor = "#"+red+green+blue; // set background color

  document.body.appendChild(spanTag);
}

function drawLine(x1,y1,x2,y2,color) {
  var i,j,x,y,m,d,done=0;
  x=Math.abs(x1);
  y=Math.abs(y1);
  m=(y2-y1)/(x2-x1);
  d=x1>x2?"-":"+";
  c=y1-(m*x); // trigonometry

  while (!done) {
   mkDot(x,y,color);
   if (x==x2) { done = 1; }
   if (d=="-") { x--; }
   else { x++; }
   y = parseInt(m*x) + c; // trigonometry
  }
}

window.onload = function() { // only can call after the body loaded
  drawLine(10,40,1000,320,"#3388cc");
};

</script>

<body>
...
</body>

</html>


In case you need the dummy1x1.png, here it is https://drive.google.com/file/d/0B2RFpjH4zL5bTm9TdVo3UFUzRTg/edit?usp=sharing.





My second version (without discontinued steep line problem):



<script>

function drawLine3(x1,y1,x2,y2,color) {

 var x,y,i,m,steep,d,done=0;
 x1=Math.abs(x1);x2=Math.abs(x2);y1=Math.abs(y1);y2=Math.abs(y2);
// make sure no negative points

 if (x1>x2) { // swap xy if 1st point is on the right
  i=x1;x1=x2;x2=i;
  i=y1;y1=y2;y2=i;
 }
 d = y1>y2?1:0; // d = downward
 x=x1;
 y=y1;
 m=(y2-y1)/(x2-x1);
 c=y1-(m*x);
 steep=Math.abs(m)>1?1:0; // if steep, draw more y pixels, else more x pixels

 while (!done) {
  mkDot(x,y,color);
  if (steep) {
   if (y==y2||x==x2) { done = 1; }
   d?y--:y++;
   x = parseInt((y - c)/m);
  }
  else {
   if (x==x2) { done = 1; }
   x++;
   y = parseInt(m*x) + c;
  }
 }
}

</script>



I've just used this improved version to draw this! (Of course with a lots of other codes such as JSON parsers/generator... sent from mySQL chart data) Isn't it cool?



No comments:

Post a Comment