Permalink
Browse files

Adding sources

  • Loading branch information...
1 parent ea5fe40 commit 85429ea34735559b4519e1d8715521603bf7d997 @w0rm committed Oct 5, 2012
Showing with 389 additions and 0 deletions.
  1. +247 −0 divcanvas.js
  2. +34 −0 style.css
  3. +108 −0 test.html
View
@@ -0,0 +1,247 @@
+/*
+
+ Drawing polygons using slanted borders technique
+
+ by Andrey Kuzmin unsoundscapes@gmail.com MIT licensed
+
+*/
+
+(function() {
+
+ function getInternetExplorerVersion()
+ // Returns the version of Internet Explorer or a -1
+ // (indicating the use of another browser).
+ {
+ var rv = -1; // Return value assumes failure.
+ if (navigator.appName == 'Microsoft Internet Explorer')
+ {
+ var ua = navigator.userAgent;
+ var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
+ if (re.exec(ua) != null)
+ rv = parseFloat( RegExp.$1 );
+ }
+ return rv;
+ }
+
+ function DivCanvas(element) {
+ this.element = element;
+ this.cache = "";
+ this.opacity = 1;
+ this.transparent = 'transparent';
+ this.filter = '';
+
+ this.ie = getInternetExplorerVersion();
+ if (this.ie > 5 && this.ie < 8) {
+ this.transparent = this.ieHackColor;
+ this.filter = ";filter: chroma(color=" + this.ieHackColor + ")";
+ }
+ }
+
+ DivCanvas.prototype = {
+ roundMethod: Math.round, // could be parseInt, but looks uglier
+ ieHackColor: 'cyan',
+ setOpacity: function(opacity) {
+ this.opacity = opacity;
+ if(this.ie>5 && this.ie<8)
+ this.filter = ";filter:chroma(color=" + this.ieHackColor + ")" +
+ (opacity==1 ? "" : " alpha(opacity=" + parseInt(opacity*100) + ")");
+ else if (this.ie>5 && this.ie<9)
+ this.filter = (opacity==1 ? "" : ";filter:alpha(opacity=" + parseInt(opacity*100) + ")");
+ else
+ this.filter = opacity==1 ? "" : ";opacity:" + opacity;
+ return this;
+ },
+ triangle: function(x, y, color) {
+ this._tri(x, y, color);
+ return this;
+ },
+ polygon: function(x, y, color) {
+ var n = x.length;
+ if (n < 3) return false;
+ var V = new Array(n);
+ /* we want a counter-clockwise polygon in V */
+ if ( 0.0 < this._area(x,y) )
+ for (var v=0; v<n; v++) V[v] = v;
+ else
+ for (var v=0; v<n; v++) V[v] = (n-1)-v;
+ var nv = n;
+ /* remove nv-2 Vertices, creating 1 triangle every time */
+ var count = 2 * nv; /* error detection */
+ for(var m=0, v=nv-1; nv>2; )
+ {
+ /* if we loop, it is probably a non-simple polygon */
+ if (0 >= (count--)) return false; //** Triangulate: ERROR - probable bad polygon!
+ /* three consecutive vertices in current polygon, <u,v,w> */
+ var u = v ; if (nv <= u) u = 0; /* previous */
+ v = u+1; if (nv <= v) v = 0; /* new v */
+ var w = v+1; if (nv <= w) w = 0; /* next */
+ if ( this._snip(x,y,u,v,w,nv,V) )
+ {
+ var a,b,c,s,t;
+ /* true names of the vertices */
+ a = V[u]; b = V[v]; c = V[w];
+ this._tri([x[c],x[a],x[b]], [y[c],y[a],y[b]], color )
+ m++;
+ /* remove v from remaining polygon */
+ for(s=v,t=v+1;t<nv;s++,t++) V[s] = V[t]; nv--;
+ /* resest error detection counter */
+ count = 2*nv;
+ }
+ }
+ return this;
+ },
+ circle: function(x, y, r, color) {
+ var dx1=r, dx2, dy1=0, dy2, da = 10;
+ for(var a = da; a <= 90; a+= da){
+ dx2 = this.roundMethod(r*Math.cos((a) * Math.PI / 180))
+ dy2 = this.roundMethod(-r*Math.sin((a) * Math.PI / 180))
+ this._trapezoid(x - dx1, y - dy1, dx1 - dx2, dx1 - dx2, dy1 - dy2, dx2 * 2, color)
+ this._trapezoid(x - dx1, y + dy1, dx1 - dx2, dx1 - dx2, dy2 - dy1, dx2 * 2, color)
+ dx1 = dx2
+ dy1 = dy2
+ }
+ return this;
+ },
+ textCircle: function(x, y, r, color) {
+ var x = parseInt(x - 1.379*r),
+ y = parseInt(y-2.61*r),
+ size = parseInt(r*4.61)
+ this.cache += "<span class='p' style='left:"+
+ x + "px;top:" + y + "px;font-family:Arial;font-size:" +
+ size + "px; color:" + color + "'>●</span>"
+ return this
+ },
+ flush: function() {
+ this.element.innerHTML += this.cache;
+ this.cache = "";
+ return this;
+ },
+ empty: function() {
+ this.element.innerHTML = "";
+ return this;
+ },
+ _area: function(x, y) {
+ var n = x.length, A = 0.0;
+ for(var p=n-1,q=0; q<n; p=q++)
+ A+= x[p] * y[q] - x[q] * y[p];
+ return A * 0.5;
+ },
+ _isInsideTriangle: function(Ax, Ay, Bx, By, Cx, Cy, Px, Py) {
+ return (Cx - Bx) * (Py - By) - (Cy - By) * (Px - Bx) >= 0 &&
+ (Bx - Ax) * (Py - Ay) - (By - Ay) * (Px - Ax) >= 0 &&
+ (Ax - Cx) * (Py - Cy) - (Ay - Cy) * (Px - Cx) >= 0;
+ },
+ _snip: function(x, y, u, v, w, n, V) {
+ var Ax, Ay, Bx, By, Cx, Cy;
+ Ax = x[V[u]]; Ay = y[V[u]];
+ Bx = x[V[v]]; By = y[V[v]];
+ Cx = x[V[w]]; Cy = y[V[w]];
+ if ( 0.0000000001 > (Bx-Ax)*(Cy-Ay) - (By-Ay)*(Cx-Ax) ) return false;
+ for (var p=0;p<n;p++){
+ if( p == u || p == v || p == w ) continue;
+ if (this._isInsideTriangle(Ax,Ay,Bx,By,Cx,Cy,x[V[p]],y[V[p]])) return false;
+ }
+ return true;
+ },
+ _tri: function(x, y, color) {
+ if(x[2]==x[1] || x[2]==x[0] || x[1]==x[0])
+ if(y[2]==y[1] || y[2]==y[0] || y[1]==y[0])
+ this._rightTri(x, y, color);
+ else
+ this._splitV(x, y, color);
+ else
+ this._splitH(x, y, color);
+ },
+ _sortOrder: function(a) {
+ if(a[0] > a[1])
+ if(a[1] > a[2])
+ return [0, 1, 2];
+ else
+ return a[0] > a[2] ? [0, 2, 1] : [2, 0, 1];
+ else
+ if(a[0] > a[2])
+ return [1, 0, 2];
+ else
+ return a[1] > a[2] ? [1, 2, 0] : [2, 1, 0];
+ },
+ _splitH: function(x, y, color) {
+ var p = this._sortOrder(x);
+ if(y[p[0]]==y[p[2]] && x[p[2]] < x[p[1]] < x[p[0]]) {
+ this._trapezoid(x[p[2]], y[p[2]], x[p[1]]-x[p[2]],x[p[0]]-x[p[1]],
+ y[p[1]]-y[p[0]], 0, color);
+ return
+ }
+ var y0 = this.roundMethod((y[p[2]] - y[p[0]]) *
+ (x[p[1]] - x[p[0]]) / (x[p[2]] - x[p[0]]) + y[p[0]]);
+ this._tri([x[p[0]], x[p[1]], x[p[1]]], [y[p[0]], y[p[1]], y0], color);
+ this._tri([x[p[2]], x[p[1]], x[p[1]]], [y[p[2]], y[p[1]], y0], color);
+ },
+ _splitV: function(x, y, color) {
+ var p = this._sortOrder(y);
+ if(x[p[0]]==x[p[2]] && y[p[2]] < y[p[1]] < y[p[0]]) {
+ this._trapezoidH(x[p[2]], y[p[2]], y[p[0]]-y[p[1]],
+ y[p[1]]-y[p[2]], x[p[1]]-x[p[0]], 0, color);
+ return
+ }
+ var x0 = this.roundMethod((x[p[2]] - x[p[0]]) *
+ (y[p[1]] - y[p[0]]) / (y[p[2]] - y[p[0]]) + x[p[0]]);
+ this._tri([x[p[0]], x[p[1]], x0], [y[p[0]], y[p[1]], y[p[1]]], color);
+ this._tri([x[p[2]], x[p[1]], x0], [y[p[2]], y[p[1]], y[p[1]]], color);
+ },
+ _rightTri: function(x, y, color)
+ /*
+ Iterates through all combinations to find
+ the position of the right corner
+ */
+ {
+ for(var i=0, c; i<6; i++) {
+ c = [[0, 1, 2], [1, 2, 0], [2, 0, 1], [1, 0, 2], [0, 2, 1], [2, 1, 0]][i];
+ if(x[c[0]]==x[c[1]] && y[c[0]]==y[c[2]])
+ return this._rightTriangle(x[c[0]], y[c[0]], x[c[2]]-x[c[0]], y[c[1]]-y[c[0]], color);
+ }
+ },
+ _rightTriangle: function(x, y, dx, dy, color)
+ /*
+ Draws right triangle based on right angle,
+ endpoint coordinates, and catheti
+ |\
+ | \
+ dy | \
+ | \
+ | \
+ (x,y) o_____\
+ dx
+ */
+ {
+ this.cache += "<div class='p' style='left:" +
+ (x + (dx<0 ? dx : 0)) + "px;top:" +
+ (y + (dy<0 ? dy : 0)) + "px;border-" +
+ (dx>0 ? "left" : "right") + ":" + Math.abs(dx) + "px solid " + color +
+ ";border-" + (dy>0 ? "bottom:" : "top:") + Math.abs(dy) + "px solid " +
+ this.transparent + this.filter +
+ "'></div>";
+ },
+ _trapezoid: function(x, y, dx1, dx2, dy, w, color) {
+ this.cache += "<div class='p' style='left:" +
+ x + "px; top: " +
+ (y + (dy < 0 ? dy : 0)) + "px; width: " + w + "px; border-left:" +
+ Math.abs(dx1) + "px solid " + this.transparent + "; border-right:" +
+ Math.abs(dx2) + "px solid " + this.transparent + "; border-" +
+ (dy < 0 ? "bottom:" : "top:") + Math.abs(dy) + "px solid " + color + this.filter +
+ "'></div>";
+ },
+ _trapezoidH: function(x, y, dy1, dy2, dx, h, color) {
+ this.cache += "<div class='p' style='left:" +
+ (x + (dx < 0 ? dx : 0)) + "px; top: " +
+ y + "px; height: " + h + "px; border-top:" +
+ Math.abs(dy2) + "px solid " + this.transparent + "; border-bottom:" +
+ Math.abs(dy1) + "px solid " + this.transparent + "; border-" +
+ (dx<0 ? "right:" : "left:") + Math.abs(dx) + "px solid " + color + this.filter +
+ "'></div>";
+ }
+ };
+
+ this.DivCanvas = DivCanvas;
+
+}).call(this)
+
View
@@ -0,0 +1,34 @@
+
+body {
+ background: gray;
+}
+
+
+/*
+ Canvas styles
+ should at least have
+ position: relative
+*/
+#divcanvas {
+ background: white;
+ width: 640px;
+ height: 480px;
+ margin: auto;
+ margin-top: 100px;
+ position: relative;
+}
+
+
+/* Basic css for generated elements */
+div.p {
+ position: absolute;
+ overflow: hidden;
+ width: 0px;
+ height: 0px;
+}
+/* Used in textCircle */
+span.p {
+ position: absolute;
+ cursor: default;
+ line-height: 1;
+}
View
108 test.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>DivCanvas</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <link rel="stylesheet" href="style.css" type="text/css" media="screen">
+ <script src="divcanvas.js" type="text/javascript"></script>
+</head>
+<body>
+ <div id="divcanvas"></div>
+ <script>
+ // Init canvas
+ var canvas = new DivCanvas(document.getElementById("divcanvas"));
+
+ // Draw triangles
+ // canvas.triangle([470, 100, 300], [70, 400, 60], "red")
+ // canvas.triangle([70, 400, 30], [270, 200, 100], "blue")
+ // canvas.triangle([620, 200, 100], [170, 400, 360], "green")
+
+ // Test different circle methods
+ //canvas.setOpacity(.5)
+ //canvas.textCircle(460, 160, 100, "#b00")
+ canvas.circle(460, 160, 100, "#b00")
+
+ // Draw crane shape
+ var k = 2, dx = 100, dy = 380, // coefficients to scale and translate shape
+ crane = [
+ {
+ x: [48, 49, -19, -32, -6],
+ y: [-44, -17, -11, -33, -103],
+ c: "#c7d7e5"
+ },
+ {
+ x: [-25, -26, -32, 55, 55, 54, 54, 57, 50, 22, 13, 5, 0, -10, -19, -75],
+ y: [-14, 11, 28, 33, 27, 22, 19, 19, -18, -21, -21, -15, -16, -18, -18, -101],
+ c: "#394e4d"
+ },
+ {
+ x: [-78, -27, -22, -22, -76],
+ y: [-100, 13, 0, -14, -103],
+ c: "#628183"
+ },
+ {
+ x: [-79, -26, -33, -77],
+ y: [-97, 12, -13, -102],
+ c: "#aac7db"
+ },
+ {
+ x: [31, 24, 21, 44, 45, 34, 87, 93],
+ y: [-57, -29, -8, 10, 7, -52, -51, -55],
+ c: "#668082"
+ },
+ {
+ x: [46, 48, 38, 34 ],
+ y: [10, 2, -51, -53],
+ c: "#344747"
+ },
+ {
+ x: [28, 32, 92, 94],
+ y: [-57, -66, -60, -55],
+ c: "#879aa3"
+ },
+ {
+ x: [35, 29, 32, 27, 25, 23, 30, 34, 93],
+ y: [-61, -59, -66, -63, -54, -22, -54, -57, -55],
+ c: "#fbfbfb"
+ },
+ {
+ x: [-24, -16, -2, 13, 42, 39, -67, -70, -54, -32],
+ y: [10, -5, -11, -10, 20, 35, 106, 103, 46, 31],
+ c: "#e1e9ee"
+ },
+ {
+ x: [-20, -11, 3, 16, 29, 34, 25, 5, -10, -30],
+ y: [10, 0, -8, -6, 9, 22, 28, 34, 33, 30],
+ c: "#b0c7d2"
+ },
+ {
+ x: [30, 41, 38, -64, -67, -70, -66, 42, 43],
+ y: [7, 22, 34, 104, 105, 105, 108, 35, 20],
+ c: "#567e7c"
+ },
+ {
+ x: [16, 0, -6],
+ y: [-77, -55, -102],
+ c: "#acbdca"
+ },
+ {
+ x: [-57, -66, -27, -28],
+ y: [68, 103, 77, 52],
+ c: "#f7f9fa"
+ }
+ ]
+
+ for (var i=0, x, y, j, n, l=crane.length; i<l; i++) {
+ x = [], y = []
+ for (j=0, n=crane[i].x.length; j<n; j++) {
+ x[j] = crane[i].x[j] * k + dx
+ y[j] = crane[i].y[j] * k + dy
+ }
+ canvas.polygon(x, y, crane[i].c)
+ }
+
+ // Show the drawing
+ canvas.flush()
+ </script>
+</body>
+</html>

0 comments on commit 85429ea

Please sign in to comment.