mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2024-12-29 09:22:22 -05:00
Merge GradientColor into Color.
Work in progress.
This commit is contained in:
parent
380fce3946
commit
5209e97c8d
15 changed files with 154 additions and 51 deletions
|
@ -10,7 +10,7 @@
|
|||
var gradient = new Gradient(['yellow', 'red', 'black'], true);
|
||||
var from = path.position;
|
||||
var to = path.bounds.rightCenter;
|
||||
var gradientColor = new GradientColor(gradient, from, to);
|
||||
var gradientColor = new Color(gradient, from, to);
|
||||
path.fillColor = gradientColor;
|
||||
path.strokeColor = 'black';
|
||||
window._json = project.exportJson();
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
radius: radius / 3
|
||||
})
|
||||
],
|
||||
fillColor: new GradientColor(gradient, 0, radius, radius / 8),
|
||||
fillColor: new Color(gradient, 0, radius, radius / 8),
|
||||
position: this.point
|
||||
});
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
var path = new Path.Rectangle(view.bounds);
|
||||
var gradient = new Gradient(colors, true);
|
||||
var radius = Math.max(view.size.width, view.size.height) * 0.75;
|
||||
path.fillColor = new GradientColor(gradient, point, point + [radius, 0]);
|
||||
path.fillColor = new Color(gradient, point, point + [radius, 0]);
|
||||
var gradientColor = path.fillColor;
|
||||
|
||||
var mouseDown = false,
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
var circle = new Path.Circle({
|
||||
center: from,
|
||||
radius: radius,
|
||||
fillColor: new GradientColor(radial, from, to),
|
||||
fillColor: new Color(radial, from, to),
|
||||
strokeColor: 'black'
|
||||
});
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
|||
var rect = new Path.Rectangle({
|
||||
from: from,
|
||||
to: to,
|
||||
fillColor: new GradientColor(linear, from, to),
|
||||
fillColor: new Color(linear, from, to),
|
||||
strokeColor: 'black'
|
||||
});
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
var gradient = new Gradient(colors, true);
|
||||
var from = center;
|
||||
var to = center + vector;
|
||||
var gradientColor = new GradientColor(gradient, from, to);
|
||||
var gradientColor = new Color(gradient, from, to);
|
||||
path.fillColor = path.strokeColor = gradientColor;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,8 @@ var Color = this.Color = Base.extend(new function() {
|
|||
gray: ['gray'],
|
||||
rgb: ['red', 'green', 'blue'],
|
||||
hsb: ['hue', 'saturation', 'brightness'],
|
||||
hsl: ['hue', 'saturation', 'lightness']
|
||||
hsl: ['hue', 'saturation', 'lightness'],
|
||||
gradient: ['gradient', 'origin', 'destination', 'hilite']
|
||||
};
|
||||
|
||||
var colorCache = {},
|
||||
|
@ -192,7 +193,18 @@ var Color = this.Color = Base.extend(new function() {
|
|||
'gray-hsl': function(g) {
|
||||
// TODO: Is lightness really the same as brightness for gray?
|
||||
return [0, 0, g];
|
||||
},
|
||||
|
||||
'gradient-rgb': function(gradient) {
|
||||
// TODO: Implement
|
||||
return [];
|
||||
},
|
||||
|
||||
'rgb-gradient': function(r, g, b) {
|
||||
// TODO: Implement
|
||||
return [];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Produce getters and setter methods for the various color components known
|
||||
|
@ -201,12 +213,15 @@ var Color = this.Color = Base.extend(new function() {
|
|||
// its component.
|
||||
return Base.each(types, function(properties, type) {
|
||||
Base.each(properties, function(name, index) {
|
||||
var isHue = name === 'hue',
|
||||
var part = Base.capitalize(name),
|
||||
isHue = name === 'hue',
|
||||
isGradient = name === 'gradient',
|
||||
isPoint = type === 'gradient' && !isGradient,
|
||||
isHilite = name === 'hilite',
|
||||
// Both hue and saturation have overlapping properties between
|
||||
// hsb and hsl. Handle this here separately, by testing for
|
||||
// overlaps and skipping conversion if the type is /hs[bl]/
|
||||
hasOverlap = /^(hue|saturation)$/.test(name),
|
||||
part = Base.capitalize(name);
|
||||
hasOverlap = /^(hue|saturation)$/.test(name);
|
||||
|
||||
this['get' + part] = function() {
|
||||
return this._type === type
|
||||
|
@ -222,11 +237,20 @@ var Color = this.Color = Base.extend(new function() {
|
|||
this._components = this._convert(type);
|
||||
this._type = type;
|
||||
}
|
||||
this._components[index] = isHue
|
||||
if (!isGradient)
|
||||
value = isHue
|
||||
// Keep negative values within modulo 360 too:
|
||||
? ((value % 360) + 360) % 360
|
||||
// All other values are 0..1
|
||||
: Math.min(Math.max(value, 0), 1);
|
||||
: isPoint
|
||||
? Point.read(arguments, 0, 0, true, isHilite) // clone, readNull
|
||||
// All other values are 0..1
|
||||
: Math.min(Math.max(value, 0), 1);
|
||||
if (value != null) {
|
||||
this._components[index] = value;
|
||||
if (isGradient)
|
||||
value._addOwner(this);
|
||||
this._changed();
|
||||
}
|
||||
};
|
||||
}, this);
|
||||
}, /** @lends Color# */{
|
||||
|
@ -242,6 +266,10 @@ var Color = this.Color = Base.extend(new function() {
|
|||
args = arguments,
|
||||
read = 0,
|
||||
type;
|
||||
if (Array.isArray(arg)) {
|
||||
args = arg;
|
||||
arg = args[0];
|
||||
}
|
||||
// Try type arg first
|
||||
if (typeof arg === 'string' && arg in types) {
|
||||
type = arg;
|
||||
|
@ -286,17 +314,19 @@ var Color = this.Color = Base.extend(new function() {
|
|||
components = arg._components.slice();
|
||||
alpha = arg._alpha;
|
||||
} else if (arg._class === 'Gradient') {
|
||||
// TODO: Construct gradient
|
||||
type = 'gradient';
|
||||
components = slice.call(args);
|
||||
} else {
|
||||
// Determine type by presence of object property names
|
||||
type = 'hue' in arg
|
||||
? 'lightness' in arg
|
||||
? 'hsl'
|
||||
: 'hsb'
|
||||
: 'gray' in arg
|
||||
? 'gray'
|
||||
: 'rgb';
|
||||
: 'gradient' in arg
|
||||
? 'gradient'
|
||||
: 'gray' in arg
|
||||
? 'gray'
|
||||
: 'rgb';
|
||||
var properties = types[type];
|
||||
components = [];
|
||||
for (var i = 0, l = properties.length; i < l; i++)
|
||||
|
@ -307,19 +337,31 @@ var Color = this.Color = Base.extend(new function() {
|
|||
if (this._read && type)
|
||||
read = 1;
|
||||
}
|
||||
// Define this GradientColor's unique id.
|
||||
if (type === 'gradient')
|
||||
this._id = ++Base._uid;
|
||||
// Default fallbacks: rgb, black
|
||||
this._type = type || 'rgb';
|
||||
this._components = components || (type === 'gray' ? [0] : [0, 0, 0]);
|
||||
this._alpha = alpha;
|
||||
// Trigger setters for each component by looping through properties
|
||||
// and resseting component value.
|
||||
// TODO: This is a hack and should implemented better, e.g. with
|
||||
// value handlers.
|
||||
var properties = types[this._type];
|
||||
for (var i = 0, l = properties.length; i < l; i++)
|
||||
this[properties[i]] = this._components[i];
|
||||
if (this._read)
|
||||
this._read = read;
|
||||
},
|
||||
|
||||
_serialize: function(options) {
|
||||
// We can ommit the type for gray and rgb:
|
||||
return /^(gray|rgb)$/.test(this._type)
|
||||
? this._components
|
||||
: [this._type].concat(this._components);
|
||||
_serialize: function(options, dictionary) {
|
||||
return Base.serialize(
|
||||
// We can ommit the type for gray and rgb:
|
||||
/^(gray|rgb)$/.test(this._type)
|
||||
? this._components
|
||||
: [this._type].concat(this._components),
|
||||
options, true, dictionary);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -477,8 +519,53 @@ var Color = this.Color = Base.extend(new function() {
|
|||
return css;
|
||||
},
|
||||
|
||||
toCanvasStyle: function() {
|
||||
return this.toCss();
|
||||
toCanvasStyle: function(ctx) {
|
||||
if (this._type !== 'gradient')
|
||||
return this.toCss();
|
||||
// Gradient code form here onwards, incudling caching
|
||||
if (this._canvasGradient)
|
||||
return this._canvasGradient;
|
||||
var components = this._components,
|
||||
gradient = components[0],
|
||||
stops = gradient._stops,
|
||||
origin = components[1],
|
||||
destination = components[2],
|
||||
canvasGradient;
|
||||
if (gradient._radial) {
|
||||
var radius = destination.getDistance(origin),
|
||||
hilite = components[3];
|
||||
if (hilite) {
|
||||
var vector = hilite.subtract(origin);
|
||||
if (vector.getLength() > radius)
|
||||
hilite = origin.add(vector.normalize(radius - 0.1));
|
||||
}
|
||||
var start = hilite || origin;
|
||||
canvasGradient = ctx.createRadialGradient(start.x, start.y,
|
||||
0, origin.x, origin.y, radius);
|
||||
} else {
|
||||
canvasGradient = ctx.createLinearGradient(origin.x, origin.y,
|
||||
destination.x, destination.y);
|
||||
}
|
||||
for (var i = 0, l = stops.length; i < l; i++) {
|
||||
var stop = stops[i];
|
||||
canvasGradient.addColorStop(stop._rampPoint, stop._color.toCss());
|
||||
}
|
||||
return this._canvasGradient = canvasGradient;
|
||||
},
|
||||
|
||||
/**
|
||||
* Transform the gradient color by the specified matrix.
|
||||
*
|
||||
* @param {Matrix} matrix the matrix to transform the gradient color by
|
||||
*/
|
||||
transform: function(matrix) {
|
||||
if (this._type === 'gradient') {
|
||||
var components = this._components;
|
||||
for (var i = 1, l = components.length; i < l; i++) {
|
||||
var point = components[i];
|
||||
matrix._transformPoint(point, point, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -613,6 +700,16 @@ var Color = this.Color = Base.extend(new function() {
|
|||
color._type = type;
|
||||
color._components = components;
|
||||
color._alpha = alpha;
|
||||
if (type === 'gradient') {
|
||||
// Make sure gradients always have an id
|
||||
color._id = ++Base._uid;
|
||||
// Clone all points:
|
||||
for (var i = 1, l = components.length; i < l; i++) {
|
||||
var point = components[i];
|
||||
if (point)
|
||||
components[i] = point.clone();
|
||||
}
|
||||
}
|
||||
return color;
|
||||
},
|
||||
|
||||
|
@ -626,16 +723,18 @@ var Color = this.Color = Base.extend(new function() {
|
|||
|
||||
// Expose RgbColor, RGBColor, etc. constructors for backward compatibility.
|
||||
Base.each(Color._types, function(properties, type) {
|
||||
this[Base.capitalize(type) + 'Color'] = this[type.toUpperCase() + 'Color'] =
|
||||
var ctor = this[Base.capitalize(type) + 'Color'] =
|
||||
function(arg) {
|
||||
var argType = arg != null && typeof arg,
|
||||
components = argType === 'number'
|
||||
? arguments
|
||||
: argType === 'object' && arg.length != null
|
||||
? arg
|
||||
: null;
|
||||
components = argType === 'object' && arg.length != null
|
||||
? arg
|
||||
: argType === 'string'
|
||||
? null
|
||||
: arguments;
|
||||
return components
|
||||
? new Color(type, components)
|
||||
: new Color(arg);
|
||||
};
|
||||
if (!/^(gray|gradient)$/.test(type))
|
||||
this[type.toUpperCase() + 'Color'] = ctor;
|
||||
}, this);
|
||||
|
|
|
@ -29,7 +29,7 @@ var Gradient = this.Gradient = Base.extend(/** @lends Gradient# */{
|
|||
|
||||
_serialize: function(options, dictionary) {
|
||||
return dictionary.add(this, function() {
|
||||
return Base.serialize([this._type, this._stops],
|
||||
return Base.serialize([this._stops, this._radial],
|
||||
options, true, dictionary);
|
||||
});
|
||||
},
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
* @class The GradientColor object.
|
||||
*/
|
||||
var GradientColor = this.GradientColor = Color.extend(/** @lends GradientColor# */{
|
||||
_type: 'gradient',
|
||||
|
||||
/**
|
||||
* Creates a gradient color object.
|
||||
|
@ -45,7 +44,7 @@ var GradientColor = this.GradientColor = Color.extend(/** @lends GradientColor#
|
|||
*
|
||||
* // Have the gradient color run between the topLeft and
|
||||
* // bottomRight points we defined earlier:
|
||||
* var gradientColor = new GradientColor(gradient, topLeft, bottomRight);
|
||||
* var gradientColor = new Color(gradient, topLeft, bottomRight);
|
||||
*
|
||||
* // Set the fill color of the path to the gradient color:
|
||||
* path.fillColor = gradientColor;
|
||||
|
@ -77,7 +76,7 @@ var GradientColor = this.GradientColor = Color.extend(/** @lends GradientColor#
|
|||
* var to = path.position + [80, 0];
|
||||
*
|
||||
* // Create the gradient color:
|
||||
* var gradientColor = new GradientColor(gradient, from, to);
|
||||
* var gradientColor = new Color(gradient, from, to);
|
||||
*
|
||||
* // Set the fill color of the path to the gradient color:
|
||||
* path.fillColor = gradientColor;
|
||||
|
@ -145,7 +144,7 @@ var GradientColor = this.GradientColor = Color.extend(/** @lends GradientColor#
|
|||
* // to the bottom right point of the view:
|
||||
* var from = view.bounds.topLeft;
|
||||
* var to = view.bounds.bottomRight;
|
||||
* var gradientColor = new GradientColor(gradient, from, to);
|
||||
* var gradientColor = new Color(gradient, from, to);
|
||||
* path.fillColor = gradientColor;
|
||||
*
|
||||
* function onMouseMove(event) {
|
||||
|
@ -185,7 +184,7 @@ var GradientColor = this.GradientColor = Color.extend(/** @lends GradientColor#
|
|||
* var gradient = new Gradient(['yellow', 'red', 'black'], true);
|
||||
* var from = view.center;
|
||||
* var to = view.bounds.bottomRight;
|
||||
* var gradientColor = new GradientColor(gradient, from, to);
|
||||
* var gradientColor = new Color(gradient, from, to);
|
||||
* path.fillColor = gradientColor;
|
||||
*
|
||||
* function onMouseMove(event) {
|
||||
|
@ -221,7 +220,7 @@ var GradientColor = this.GradientColor = Color.extend(/** @lends GradientColor#
|
|||
* var gradient = new Gradient(['yellow', 'red', 'black'], true);
|
||||
* var from = path.position;
|
||||
* var to = path.bounds.rightCenter;
|
||||
* var gradientColor = new GradientColor(gradient, from, to);
|
||||
* var gradientColor = new Color(gradient, from, to);
|
||||
*
|
||||
* path.fillColor = gradientColor;
|
||||
*
|
||||
|
|
|
@ -54,7 +54,7 @@ var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{
|
|||
},
|
||||
|
||||
_serialize: function(options, dictionary) {
|
||||
return Base.serialize([this._color, this._rampPoint], options, false,
|
||||
return Base.serialize([this._color, this._rampPoint], options, true,
|
||||
dictionary);
|
||||
},
|
||||
|
||||
|
@ -92,7 +92,7 @@ var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{
|
|||
* var gradient = new Gradient(colors, true);
|
||||
* var from = path.position;
|
||||
* var to = path.bounds.rightCenter;
|
||||
* var gradientColor = new GradientColor(gradient, from, to);
|
||||
* var gradientColor = new Color(gradient, from, to);
|
||||
*
|
||||
* path.fillColor = gradientColor;
|
||||
*
|
||||
|
@ -141,7 +141,7 @@ var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{
|
|||
* // to the right center of its bounding rectangle:
|
||||
* var from = path.position;
|
||||
* var to = path.bounds.rightCenter;
|
||||
* var gradientColor = new GradientColor(gradient, from, to);
|
||||
* var gradientColor = new Color(gradient, from, to);
|
||||
* path.fillColor = gradientColor;
|
||||
*
|
||||
* // This function is called each frame of the animation:
|
||||
|
|
|
@ -290,7 +290,12 @@ this.Base = Base.inject(/** @lends Base# */{
|
|||
ref = this.references[id];
|
||||
if (!ref) {
|
||||
this.length++;
|
||||
this.definitions[id] = create.call(item);
|
||||
var res = create.call(item);
|
||||
// Also automatically insert class for dictionary
|
||||
// entries.
|
||||
if (item._class && res[0] !== item._class)
|
||||
res.unshift(item._class);
|
||||
this.definitions[id] = res;
|
||||
ref = this.references[id] = [id];
|
||||
}
|
||||
return ref;
|
||||
|
@ -300,8 +305,8 @@ this.Base = Base.inject(/** @lends Base# */{
|
|||
if (obj && obj._serialize) {
|
||||
res = obj._serialize(options, dictionary);
|
||||
// If we don't serialize to compact form (meaning no type
|
||||
// identifier), see if _serialize didn't already add the type,
|
||||
// e.g. for types that do not support compact form.
|
||||
// identifier), see if _serialize didn't already add the class,
|
||||
// e.g. for classes that do not support compact form.
|
||||
if (obj._class && !compact && res[0] !== obj._class)
|
||||
res.unshift(obj._class);
|
||||
} else if (Array.isArray(obj)) {
|
||||
|
|
|
@ -87,7 +87,6 @@ var paper = new function() {
|
|||
/*#*/ include('style/CharacterStyle.js');
|
||||
|
||||
/*#*/ include('color/Color.js');
|
||||
/*#*/ include('color/GradientColor.js');
|
||||
/*#*/ include('color/Gradient.js');
|
||||
/*#*/ include('color/GradientStop.js');
|
||||
|
||||
|
|
|
@ -341,12 +341,11 @@ new function() {
|
|||
// TODO: Implement gradient merging in SvgImport
|
||||
var gradientNode = getDefinition(color);
|
||||
if (!gradientNode) {
|
||||
var gradient = color.gradient,
|
||||
var gradient = color.getGradient(),
|
||||
radial = gradient._radial,
|
||||
matrix = item._gradientMatrix,
|
||||
origin = color._origin.transform(matrix),
|
||||
destination = color._destination.transform(matrix),
|
||||
highlight = color._hilite && color._hilite.transform(matrix),
|
||||
origin = color.getOrigin().transform(matrix),
|
||||
destination = color.getDestination().transform(matrix),
|
||||
attrs;
|
||||
if (radial) {
|
||||
attrs = {
|
||||
|
@ -354,7 +353,9 @@ new function() {
|
|||
cy: origin.y,
|
||||
r: origin.getDistance(destination)
|
||||
};
|
||||
var highlight = color.getHilite();
|
||||
if (highlight) {
|
||||
highlight = highlight.transform(matrix);
|
||||
attrs.fx = highlight.x;
|
||||
attrs.fy = highlight.y;
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ new function() {
|
|||
// We don't return the GradientColor, since we only need a reference to
|
||||
// it in definitions, which is created in applyAttributes()
|
||||
applyAttributes(
|
||||
new GradientColor(gradient, origin, destination, highlight), node);
|
||||
new Color(gradient, origin, destination, highlight), node);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ test('Path#clone()', function() {
|
|||
test('Path#clone() with GradientColor', function() {
|
||||
var colors = ['red', 'green', 'black'];
|
||||
var gradient = new Gradient(colors, true);
|
||||
var color = new GradientColor(gradient, [0, 0], [20, 20], [10, 10]);
|
||||
var color = new Color(gradient, [0, 0], [20, 20], [10, 10]);
|
||||
|
||||
var path = new Path([10, 20], [30, 40]);
|
||||
path.fillColor = color;
|
||||
|
|
|
@ -61,7 +61,7 @@ test('Gradients', function() {
|
|||
var gradient = new Gradient(['yellow', 'red', 'black'], true);
|
||||
var from = path.position;
|
||||
var to = path.bounds.rightCenter;
|
||||
var gradientColor = new GradientColor(gradient, from, to);
|
||||
var gradientColor = new Color(gradient, from, to);
|
||||
path.fillColor = gradientColor;
|
||||
path.strokeColor = 'black';
|
||||
testExportImportJson(paper.project);
|
||||
|
|
Loading…
Reference in a new issue