paper.js/src/path/CompoundPath.js

238 lines
6.2 KiB
JavaScript
Raw Normal View History

2011-03-06 19:50:44 -05:00
/*
* Paper.js
*
* This file is part of Paper.js, a JavaScript Vector Graphics Library,
* based on Scriptographer.org and designed to be largely API compatible.
2011-03-07 20:41:50 -05:00
* http://paperjs.org/
2011-03-06 19:50:44 -05:00
* http://scriptographer.org/
*
2011-03-07 20:41:50 -05:00
* Distributed under the MIT license. See LICENSE file for details.
*
2011-03-06 19:50:44 -05:00
* Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
* http://lehni.org/ & http://jonathanpuckey.com/
*
2011-03-07 20:41:50 -05:00
* All rights reserved.
2011-03-06 19:50:44 -05:00
*/
var CompoundPath = this.CompoundPath = PathItem.extend({
2011-05-22 19:49:01 -04:00
/** @lends CompoundPath# */
/**
* Creates a new compound path item and places it in the active layer.
*
* @constructs CompoundPath
* @param {Array} [paths] the paths to place within the compound path.
*
* @example
* // Create a donut shaped compound path:
* var circle = new Path.Circle(new Point(50, 50), 30);
* var innerCircle = new Path.Circle(new Point(50, 50), 10);
* var compoundPath = new CompoundPath([circle, innerCircle]);
* compoundPath.fillColor = 'red';
*
* // Move the inner circle 5pt to the right:
* compoundPath.children[1].position.x += 5;
2011-05-22 19:49:01 -04:00
*
* @class A compound path contains two or more paths, holes are drawn
* where the paths overlap. All the paths in a compound path take on the
2011-05-27 07:54:34 -04:00
* style of the backmost path and can be accessed through its
* {@link Item#children} list.
2011-05-22 19:49:01 -04:00
*
* @extends PathItem
* @extends Item
*/
2011-05-15 13:05:47 -04:00
initialize: function(paths) {
this.base();
this._children = [];
// Do not reassign to paths, since arguments would get modified, which
// we potentially use as array, depending on what is passed.
var items = !paths || !Array.isArray(paths)
|| typeof paths[0] !== 'object' ? arguments : paths;
for (var i = 0, l = items.length; i < l; i++) {
var path = items[i];
// All paths except for the top one (last one in list) are set to
// clockwise orientation when creating a compound path, so that they
// appear as holes, but only if their orientation was not already
// specified before (= _clockwise is defined).
// TODO: This should really be handled in appendTop / Bottom, right?
if (path._clockwise === undefined)
path.setClockwise(i < l - 1);
this.appendTop(path);
}
},
/**
* If this is a compound path with only one path inside,
* the path is moved outside and the compound path is erased.
* Otherwise, the compound path is returned unmodified.
*
2011-05-22 19:49:01 -04:00
* @return {CompoundPath|Path} the simplified compound path
*/
simplify: function() {
if (this._children.length == 1) {
var child = this._children[0];
child.moveAbove(this);
this.remove();
return child;
}
return this;
},
2011-05-22 19:49:01 -04:00
/**
* Smooth bezier curves without changing the amount of segments or their
* points, by only smoothing and adjusting their handle points, for both
* open ended and closed paths.
*
* @author Oleg V. Polikarpotchkin
*/
smooth: function() {
for (var i = 0, l = this._children.length; i < l; i++)
this._children[i].smooth();
},
draw: function(ctx, param) {
var firstChild = this._children[0];
ctx.beginPath();
param.compound = true;
for (var i = 0, l = this._children.length; i < l; i++)
Item.draw(this._children[i], ctx, param);
firstChild._setStyles(ctx);
var fillColor = firstChild.getFillColor(),
strokeColor = firstChild.getStrokeColor();
if (fillColor) {
ctx.fillStyle = fillColor.getCanvasStyle(ctx);
ctx.fill();
}
if (strokeColor) {
ctx.strokeStyle = strokeColor.getCanvasStyle(ctx);
ctx.stroke();
}
param.compound = false;
}
}, new function() { // Injection scope for PostScript-like drawing functions
function getCurrentPath(that) {
2011-05-15 14:31:25 -04:00
if (!that._children.length)
2011-03-03 12:29:40 -05:00
throw new Error('Use a moveTo() command first');
2011-05-15 14:31:25 -04:00
return that._children[that._children.length - 1];
}
var fields = {
2011-05-22 19:49:01 -04:00
/** @lends CompoundPath# */
/**
2011-05-27 07:54:34 -04:00
* {@grouptitle Postscript Style Drawing Commands}
*
* Creates a new path in the compound-path and adds the point
* as its first segment.
*
2011-05-22 19:49:01 -04:00
* @param {Point} point
*/
moveTo: function(point) {
var path = new Path();
this.appendTop(path);
path.moveTo.apply(path, arguments);
},
2011-05-22 19:49:01 -04:00
/**
* Creates a new path in the compound-path and adds the point as its
* first segment relative to the position of the last segment of the
* current path.
*
2011-05-22 19:49:01 -04:00
* @param {Point} point
*/
2011-05-15 14:58:09 -04:00
moveBy: function(point) {
this.moveTo(getCurrentPath(this).getLastSegment()._point.add(
Point.read(arguments)));
},
2011-05-22 19:49:01 -04:00
/**
* Closes the path. If it is closed, Paper.js connects the first and
* last segments.
*/
closePath: function() {
2011-04-30 18:22:29 -04:00
getCurrentPath(this).setClosed(true);
}
};
// DOCS: document CompoundPath#lineTo
/**
* @name CompoundPath#lineTo
* @function
* @param {Point} point
*/
/**
* Adds a cubic bezier curve to the current path, defined by two handles and
* a to point.
*
* @name CompoundPath#cubicCurveTo
* @function
* @param {Point} handle1
* @param {Point} handle2
* @param {Point} to
*/
/**
* Adds a quadratic bezier curve to the current path, defined by a handle
* and a to point.
*
* @name CompoundPath#quadraticCurveTo
* @function
* @param {Point} handle
* @param {Point} to
*/
// DOCS: document CompoundPath#curveTo
/**
* @name CompoundPath#curveTo
* @function
* @param {Point} through
* @param {Point} to
* @param {Number} [parameter=0.5]
*/
// DOCS: document CompoundPath#arcTo
/**
* @name CompoundPath#arcTo
* @function
* @param {Point} to
* @param {Boolean} [clockwise=true]
*/
// DOCS: document CompoundPath#lineBy
/**
* @name CompoundPath#lineBy
* @function
* @param {Point} vector
*/
// DOCS: document CompoundPath#curveBy
/**
* @name CompoundPath#curveBy
* @function
* @param {Point} throughVector
* @param {Point} toVector
* @param {Number} [parameter=0.5]
*/
// DOCS: document CompoundPath#arcBy
/**
* @name CompoundPath#arcBy
* @function
* @param {Point} throughVector
* @param {Point} toVector
*/
2011-05-22 19:49:01 -04:00
// DOCS: document CompoundPath#lineTo, CompoundPath#cubicCurveTo etc
// Redirect all other drawing commands to the current path
Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo',
'arcTo', 'lineBy', 'curveBy', 'arcBy'], function(key) {
fields[key] = function() {
var path = getCurrentPath(this);
path[key].apply(path, arguments);
};
});
return fields;
});