PageRenderTime 64ms CodeModel.GetById 47ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/src/path/Path.js

http://canviz.googlecode.com/
JavaScript | 154 lines | 145 code | 3 blank | 6 comment | 45 complexity | dce21f9fc7c660b708d017207e604ec9 MD5 | raw file
  1// Constructor
  2function Path(segments, options) {
  3  if (!(this instanceof Path)) return new Path(segments, options);
  4  this.segments = segments || [];
  5  this.options = {};
  6  if (options) this.setOptions(options);
  7}
  8
  9// Prototype
 10Path.prototype = {
 11  constructor: Path,
 12  x_fill: false,
 13  x_stroke: true,
 14  x_strokeType: 'solid',
 15  x_dashLength: 6,
 16  x_dotSpacing: 4,
 17  setOptions: function (options) {
 18    var keys = objectKeys(options);
 19    var keysLength = keys.length;
 20    for (var i = 0; i < keysLength; ++i) {
 21      var key = keys[i];
 22      if ('x_' == key.substr(0, 2)) {
 23        this[key] = options[key];
 24      } else {
 25        this.options[key] = options[key];
 26      }
 27    }
 28  },
 29  setupSegments: function () {},
 30  // Based on Oliver Steele's bezier.js library.
 31  addBezier: function (pointsOrBezier) {
 32    this.segments.push(pointsOrBezier instanceof Array ? Bezier(pointsOrBezier) : pointsOrBezier);
 33  },
 34  offset: function (dx, dy) {
 35    if (0 == this.segments.length) this.setupSegments();
 36    var segmentsLength = this.segments.length;
 37    for (var i = 0; i < segmentsLength; ++i) {
 38      this.segments[i].offset(dx, dy);
 39    }
 40  },
 41  getBB: function () {
 42    if (0 == this.segments.length) this.setupSegments();
 43    var l, t, r, b, p = this.segments[0].points[0];
 44    l = r = p.x;
 45    t = b = p.y;
 46    var segmentsLength = this.segments.length;
 47    for (var i = 0; i < segmentsLength; ++i) {
 48      var points = this.segments[i].points;
 49      var pointsLength = points.length;
 50      for (var j = 0; j < pointsLength; ++j) {
 51        var point = this.segments[i].points[j];
 52        l = Math.min(l, point.x);
 53        t = Math.min(t, point.y);
 54        r = Math.max(r, point.x);
 55        b = Math.max(b, point.y);
 56      }
 57    }
 58    var rect = Rect(l, t, r, b);
 59    return (this.getBB = function () {return rect;})();
 60  },
 61  isPointInBB: function (x, y, tolerance) {
 62    if (typeof tolerance == 'undefined') tolerance = 0;
 63    var bb = this.getBB();
 64    if (0 < tolerance) {
 65      bb = Object.clone(bb);
 66      bb.inset(-tolerance, -tolerance);
 67    }
 68    return !(x < bb.l || x > bb.r || y < bb.t || y > bb.b);
 69  },
 70  isPointOnPath: function (x, y, tolerance) {
 71    if (typeof tolerance == 'undefined') tolerance = 0;
 72    if (!this.isPointInBB(x, y, tolerance)) return false;
 73    var segmentsLength = this.segments.length;
 74    for (var i = 0; i < segmentsLength; ++i) {
 75      if (this.segments[i].isPointOnBezier(x, y, tolerance)) {
 76        return true;
 77      }
 78    }
 79    return false;
 80  },
 81  isPointInPath: function (x, y) {
 82    return false;
 83  },
 84  // Based on Oliver Steele's bezier.js library.
 85  makePath: function (ctx) {
 86    if (0 == this.segments.length) this.setupSegments();
 87    var segmentsLength = this.segments.length;
 88    for (var i = 0; i < segmentsLength; ++i) {
 89      this.segments[i].makePath(ctx, 0 == i);
 90    }
 91  },
 92  makeDashedPath: function (ctx, dashLength, firstDistance, drawFirst) {
 93    if (0 == this.segments.length) this.setupSegments();
 94    var info = {
 95      drawFirst: (typeof drawFirst == 'undefined') || drawFirst,
 96      firstDistance: firstDistance || dashLength
 97    };
 98    var segmentsLength = this.segments.length;
 99    for (var i = 0; i < segmentsLength; ++i) {
100      info = this.segments[i].makeDashedPath(ctx, dashLength, info.firstDistance, info.drawFirst);
101    }
102  },
103  makeDottedPath: function (ctx, dotSpacing, firstDistance) {
104    if (0 == this.segments.length) this.setupSegments();
105    if (!firstDistance) firstDistance = dotSpacing;
106    var segmentsLength = this.segments.length;
107    for (var i = 0; i < segmentsLength; ++i) {
108      firstDistance = this.segments[i].makeDottedPath(ctx, dotSpacing, firstDistance);
109    }
110  },
111  draw: function (ctx) {
112    ctx.save();
113    var keys = objectKeys(this.options);
114    var keysLength = keys.length;
115    for (var i = 0; i < keysLength; ++i) {
116      var key = keys[i];
117      ctx[key] = this.options[key];
118    }
119    if (this.x_fill) {
120      ctx.beginPath();
121      this.makePath(ctx);
122      ctx.fill();
123    }
124    if (this.x_stroke) {
125      switch (this.x_strokeType) {
126        case 'dashed':
127          ctx.beginPath();
128          this.makeDashedPath(ctx, this.x_dashLength);
129          break;
130        case 'dotted':
131          if (ctx.lineWidth < 2) ctx.lineWidth = 2;
132          ctx.beginPath();
133          this.makeDottedPath(ctx, this.x_dotSpacing);
134          break;
135        case 'solid':
136        default:
137          if (!this.x_fill) {
138            ctx.beginPath();
139            this.makePath(ctx);
140          }
141      }
142      ctx.stroke();
143    }
144    ctx.restore();
145  }
146};
147
148// Exports
149module.exports = Path;
150
151// Dependencies
152var Bezier = require('./Bezier.js');
153var objectKeys = require('./objectKeys.js');
154var Rect = require('./Rect.js');