2011-03-06 19:50:44 -05:00
|
|
|
/*
|
2013-01-28 21:03:27 -05:00
|
|
|
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
|
2011-03-07 20:41:50 -05:00
|
|
|
* http://paperjs.org/
|
2011-06-30 06:01:51 -04:00
|
|
|
*
|
2013-01-28 21:03:27 -05:00
|
|
|
* Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
|
2011-03-06 19:50:44 -05:00
|
|
|
* http://lehni.org/ & http://jonathanpuckey.com/
|
2011-06-30 06:01:51 -04:00
|
|
|
*
|
2011-07-01 06:17:45 -04:00
|
|
|
* Distributed under the MIT license. See LICENSE file for details.
|
|
|
|
*
|
2011-03-07 20:41:50 -05:00
|
|
|
* All rights reserved.
|
2011-03-06 19:50:44 -05:00
|
|
|
*/
|
|
|
|
|
2011-06-22 18:56:05 -04:00
|
|
|
/**
|
|
|
|
* @name Gradient
|
2011-06-30 06:01:51 -04:00
|
|
|
*
|
2011-06-22 18:56:05 -04:00
|
|
|
* @class The Gradient object.
|
2013-04-21 09:35:31 -04:00
|
|
|
*
|
|
|
|
* @classexample {@paperscript height=300}
|
|
|
|
* // Applying a linear gradient color containing evenly distributed
|
|
|
|
* // color stops:
|
|
|
|
*
|
|
|
|
* // Define two points which we will be using to construct
|
|
|
|
* // the path and to position the gradient color:
|
|
|
|
* var topLeft = view.center - [80, 80];
|
|
|
|
* var bottomRight = view.center + [80, 80];
|
|
|
|
*
|
|
|
|
* // Create a rectangle shaped path between
|
|
|
|
* // the topLeft and bottomRight points:
|
|
|
|
* var path = new Path.Rectangle(topLeft, bottomRight);
|
|
|
|
*
|
|
|
|
* // Fill the path with a gradient of three evenly divided color stops
|
|
|
|
* // that runs between the two points we defined earlier:
|
|
|
|
* path.fillColor = {
|
|
|
|
* gradient: {
|
|
|
|
* stops: ['yellow', 'red', 'blue']
|
|
|
|
* },
|
|
|
|
* origin: topLeft,
|
|
|
|
* destination: bottomRight
|
|
|
|
* };
|
|
|
|
*
|
|
|
|
* @classexample {@paperscript height=300}
|
|
|
|
* // Create a circle shaped path at the center of the view,
|
|
|
|
* // using 40% of the height of the view as its radius
|
|
|
|
* // and fill it with a radial gradient color:
|
|
|
|
* var path = new Path.Circle({
|
|
|
|
* center: view.center,
|
|
|
|
* radius: view.bounds.height * 0.4
|
|
|
|
* });
|
|
|
|
*
|
|
|
|
* // Fill the path with a radial gradient color with three stops:
|
|
|
|
* // yellow from 0% to 5%, mix between red from 5% to 20%,
|
|
|
|
* // mix between red and black from 20% to 100%:
|
|
|
|
* path.fillColor = {
|
|
|
|
* gradient: {
|
|
|
|
* stops: [['yellow', 0.05], ['red', 0.2], ['black', 1]],
|
|
|
|
* radial: true
|
|
|
|
* },
|
|
|
|
* origin: path.position,
|
|
|
|
* destination: path.bounds.rightCenter
|
|
|
|
* };
|
2011-06-22 18:56:05 -04:00
|
|
|
*/
|
2013-05-27 15:48:58 -04:00
|
|
|
var Gradient = Base.extend(/** @lends Gradient# */{
|
2013-04-09 20:08:09 -04:00
|
|
|
// DOCS: Document #initialize()
|
2013-05-27 15:48:58 -04:00
|
|
|
initialize: function Gradient(stops, radial) {
|
2013-02-10 22:38:35 -05:00
|
|
|
// Define this Gradient's unique id.
|
2013-04-22 22:09:59 -04:00
|
|
|
this._id = Gradient._id = (Gradient._id || 0) + 1;
|
2013-04-09 12:23:08 -04:00
|
|
|
if (stops && this._set(stops))
|
|
|
|
stops = radial = null;
|
|
|
|
if (!this._stops)
|
2013-04-09 12:20:32 -04:00
|
|
|
this.setStops(stops || ['white', 'black']);
|
2013-04-09 12:23:08 -04:00
|
|
|
if (this._radial == null)
|
2013-04-09 12:20:32 -04:00
|
|
|
// Support old string type argument and new radial boolean.
|
|
|
|
this.setRadial(typeof radial === 'string' && radial === 'radial'
|
|
|
|
|| radial || false);
|
2011-02-19 16:50:37 -05:00
|
|
|
},
|
2011-03-03 17:45:17 -05:00
|
|
|
|
2013-02-12 17:57:54 -05:00
|
|
|
_serialize: function(options, dictionary) {
|
2013-02-11 22:31:58 -05:00
|
|
|
return dictionary.add(this, function() {
|
2013-04-09 04:21:36 -04:00
|
|
|
return Base.serialize([this._stops, this._radial],
|
2013-02-12 17:57:54 -05:00
|
|
|
options, true, dictionary);
|
2013-02-11 22:31:58 -05:00
|
|
|
});
|
2013-02-11 22:22:18 -05:00
|
|
|
},
|
|
|
|
|
2012-03-04 13:14:13 -05:00
|
|
|
/**
|
|
|
|
* Called by various setters whenever a gradient value changes
|
|
|
|
*/
|
|
|
|
_changed: function() {
|
|
|
|
// Loop through the gradient-colors that use this gradient and notify
|
|
|
|
// them, so they can notify the items they belong to.
|
|
|
|
for (var i = 0, l = this._owners && this._owners.length; i < l; i++)
|
|
|
|
this._owners[i]._changed();
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-04-09 11:36:02 -04:00
|
|
|
* Called by Color#setGradient()
|
2012-03-04 13:14:13 -05:00
|
|
|
* This is required to pass on _changed() notifications to the _owners.
|
|
|
|
*/
|
|
|
|
_addOwner: function(color) {
|
|
|
|
if (!this._owners)
|
|
|
|
this._owners = [];
|
|
|
|
this._owners.push(color);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-04-09 11:36:02 -04:00
|
|
|
* Called by Color whenever this gradient stops being used.
|
2012-03-04 13:14:13 -05:00
|
|
|
*/
|
|
|
|
_removeOwner: function(color) {
|
|
|
|
var index = this._owners ? this._owners.indexOf(color) : -1;
|
|
|
|
if (index != -1) {
|
|
|
|
this._owners.splice(index, 1);
|
2013-04-08 23:52:21 -04:00
|
|
|
if (this._owners.length === 0)
|
2012-03-04 13:14:13 -05:00
|
|
|
delete this._owners;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2011-05-25 18:55:44 -04:00
|
|
|
/**
|
|
|
|
* @return {Gradient} a copy of the gradient
|
|
|
|
*/
|
2011-05-19 17:02:26 -04:00
|
|
|
clone: function() {
|
|
|
|
var stops = [];
|
|
|
|
for (var i = 0, l = this._stops.length; i < l; i++)
|
|
|
|
stops[i] = this._stops[i].clone();
|
2013-03-01 20:39:36 -05:00
|
|
|
return new this.constructor(stops);
|
2011-05-19 17:02:26 -04:00
|
|
|
},
|
|
|
|
|
2011-05-25 18:55:44 -04:00
|
|
|
/**
|
|
|
|
* The gradient stops on the gradient ramp.
|
2011-06-30 06:01:51 -04:00
|
|
|
*
|
2011-05-26 14:09:25 -04:00
|
|
|
* @type GradientStop[]
|
2011-05-25 18:55:44 -04:00
|
|
|
* @bean
|
|
|
|
*/
|
2011-02-19 16:50:37 -05:00
|
|
|
getStops: function() {
|
|
|
|
return this._stops;
|
|
|
|
},
|
2011-03-03 17:45:17 -05:00
|
|
|
|
2011-02-19 16:50:37 -05:00
|
|
|
setStops: function(stops) {
|
2012-03-04 13:14:13 -05:00
|
|
|
// If this gradient already contains stops, first remove
|
|
|
|
// this gradient as their owner.
|
|
|
|
if (this.stops) {
|
2012-10-10 22:27:14 -04:00
|
|
|
for (var i = 0, l = this._stops.length; i < l; i++)
|
|
|
|
delete this._stops[i]._owner;
|
2012-03-04 13:14:13 -05:00
|
|
|
}
|
2011-02-20 21:32:39 -05:00
|
|
|
if (stops.length < 2)
|
2011-03-03 17:45:17 -05:00
|
|
|
throw new Error(
|
|
|
|
'Gradient stop list needs to contain at least two stops.');
|
2013-06-11 22:49:35 -04:00
|
|
|
this._stops = GradientStop.readAll(stops, 0, false, true); // clone
|
2011-05-19 15:51:09 -04:00
|
|
|
// Now reassign ramp points if they were not specified.
|
|
|
|
for (var i = 0, l = this._stops.length; i < l; i++) {
|
|
|
|
var stop = this._stops[i];
|
2012-10-10 22:27:14 -04:00
|
|
|
stop._owner = this;
|
2011-05-19 15:51:09 -04:00
|
|
|
if (stop._defaultRamp)
|
|
|
|
stop.setRampPoint(i / (l - 1));
|
2011-04-07 11:01:49 -04:00
|
|
|
}
|
2012-03-04 13:14:13 -05:00
|
|
|
this._changed();
|
2011-05-05 15:28:28 -04:00
|
|
|
},
|
2011-05-19 15:51:09 -04:00
|
|
|
|
2013-04-09 20:08:09 -04:00
|
|
|
/**
|
|
|
|
* Specifies whether the gradient is radial or linear.
|
|
|
|
*
|
|
|
|
* @type Boolean
|
|
|
|
* @bean
|
|
|
|
*/
|
2013-04-08 23:52:21 -04:00
|
|
|
getRadial: function() {
|
|
|
|
return this._radial;
|
|
|
|
},
|
|
|
|
|
|
|
|
setRadial: function(radial) {
|
|
|
|
this._radial = radial;
|
|
|
|
this._changed();
|
|
|
|
},
|
|
|
|
|
2011-05-25 18:55:44 -04:00
|
|
|
/**
|
|
|
|
* Checks whether the gradient is equal to the supplied gradient.
|
2011-06-30 06:01:51 -04:00
|
|
|
*
|
2011-05-25 18:55:44 -04:00
|
|
|
* @param {Gradient} gradient
|
2011-05-30 13:42:17 -04:00
|
|
|
* @return {Boolean} {@true they are equal}
|
2011-05-25 18:55:44 -04:00
|
|
|
*/
|
2011-05-05 15:28:28 -04:00
|
|
|
equals: function(gradient) {
|
2013-03-01 20:39:36 -05:00
|
|
|
if (gradient && gradient.constructor == this.constructor
|
|
|
|
&& this._stops.length == gradient._stops.length) {
|
2011-05-19 17:00:03 -04:00
|
|
|
for (var i = 0, l = this._stops.length; i < l; i++) {
|
|
|
|
if (!this._stops[i].equals(gradient._stops[i]))
|
2011-05-05 15:28:28 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2011-02-19 16:50:37 -05:00
|
|
|
}
|
2011-03-03 11:32:55 -05:00
|
|
|
});
|