/src/path/Path.js
http://canviz.googlecode.com/ · JavaScript · 154 lines · 145 code · 3 blank · 6 comment · 45 complexity · dce21f9fc7c660b708d017207e604ec9 MD5 · raw file
- // Constructor
- function Path(segments, options) {
- if (!(this instanceof Path)) return new Path(segments, options);
- this.segments = segments || [];
- this.options = {};
- if (options) this.setOptions(options);
- }
- // Prototype
- Path.prototype = {
- constructor: Path,
- x_fill: false,
- x_stroke: true,
- x_strokeType: 'solid',
- x_dashLength: 6,
- x_dotSpacing: 4,
- setOptions: function (options) {
- var keys = objectKeys(options);
- var keysLength = keys.length;
- for (var i = 0; i < keysLength; ++i) {
- var key = keys[i];
- if ('x_' == key.substr(0, 2)) {
- this[key] = options[key];
- } else {
- this.options[key] = options[key];
- }
- }
- },
- setupSegments: function () {},
- // Based on Oliver Steele's bezier.js library.
- addBezier: function (pointsOrBezier) {
- this.segments.push(pointsOrBezier instanceof Array ? Bezier(pointsOrBezier) : pointsOrBezier);
- },
- offset: function (dx, dy) {
- if (0 == this.segments.length) this.setupSegments();
- var segmentsLength = this.segments.length;
- for (var i = 0; i < segmentsLength; ++i) {
- this.segments[i].offset(dx, dy);
- }
- },
- getBB: function () {
- if (0 == this.segments.length) this.setupSegments();
- var l, t, r, b, p = this.segments[0].points[0];
- l = r = p.x;
- t = b = p.y;
- var segmentsLength = this.segments.length;
- for (var i = 0; i < segmentsLength; ++i) {
- var points = this.segments[i].points;
- var pointsLength = points.length;
- for (var j = 0; j < pointsLength; ++j) {
- var point = this.segments[i].points[j];
- l = Math.min(l, point.x);
- t = Math.min(t, point.y);
- r = Math.max(r, point.x);
- b = Math.max(b, point.y);
- }
- }
- var rect = Rect(l, t, r, b);
- return (this.getBB = function () {return rect;})();
- },
- isPointInBB: function (x, y, tolerance) {
- if (typeof tolerance == 'undefined') tolerance = 0;
- var bb = this.getBB();
- if (0 < tolerance) {
- bb = Object.clone(bb);
- bb.inset(-tolerance, -tolerance);
- }
- return !(x < bb.l || x > bb.r || y < bb.t || y > bb.b);
- },
- isPointOnPath: function (x, y, tolerance) {
- if (typeof tolerance == 'undefined') tolerance = 0;
- if (!this.isPointInBB(x, y, tolerance)) return false;
- var segmentsLength = this.segments.length;
- for (var i = 0; i < segmentsLength; ++i) {
- if (this.segments[i].isPointOnBezier(x, y, tolerance)) {
- return true;
- }
- }
- return false;
- },
- isPointInPath: function (x, y) {
- return false;
- },
- // Based on Oliver Steele's bezier.js library.
- makePath: function (ctx) {
- if (0 == this.segments.length) this.setupSegments();
- var segmentsLength = this.segments.length;
- for (var i = 0; i < segmentsLength; ++i) {
- this.segments[i].makePath(ctx, 0 == i);
- }
- },
- makeDashedPath: function (ctx, dashLength, firstDistance, drawFirst) {
- if (0 == this.segments.length) this.setupSegments();
- var info = {
- drawFirst: (typeof drawFirst == 'undefined') || drawFirst,
- firstDistance: firstDistance || dashLength
- };
- var segmentsLength = this.segments.length;
- for (var i = 0; i < segmentsLength; ++i) {
- info = this.segments[i].makeDashedPath(ctx, dashLength, info.firstDistance, info.drawFirst);
- }
- },
- makeDottedPath: function (ctx, dotSpacing, firstDistance) {
- if (0 == this.segments.length) this.setupSegments();
- if (!firstDistance) firstDistance = dotSpacing;
- var segmentsLength = this.segments.length;
- for (var i = 0; i < segmentsLength; ++i) {
- firstDistance = this.segments[i].makeDottedPath(ctx, dotSpacing, firstDistance);
- }
- },
- draw: function (ctx) {
- ctx.save();
- var keys = objectKeys(this.options);
- var keysLength = keys.length;
- for (var i = 0; i < keysLength; ++i) {
- var key = keys[i];
- ctx[key] = this.options[key];
- }
- if (this.x_fill) {
- ctx.beginPath();
- this.makePath(ctx);
- ctx.fill();
- }
- if (this.x_stroke) {
- switch (this.x_strokeType) {
- case 'dashed':
- ctx.beginPath();
- this.makeDashedPath(ctx, this.x_dashLength);
- break;
- case 'dotted':
- if (ctx.lineWidth < 2) ctx.lineWidth = 2;
- ctx.beginPath();
- this.makeDottedPath(ctx, this.x_dotSpacing);
- break;
- case 'solid':
- default:
- if (!this.x_fill) {
- ctx.beginPath();
- this.makePath(ctx);
- }
- }
- ctx.stroke();
- }
- ctx.restore();
- }
- };
- // Exports
- module.exports = Path;
- // Dependencies
- var Bezier = require('./Bezier.js');
- var objectKeys = require('./objectKeys.js');
- var Rect = require('./Rect.js');