mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-01 02:38:43 -05:00
Remove Item#applyMatrix boolean, go back to previous way of directly applying transformations to children in Group and Layer, and introduce new Clip class for non-transformed nested matrices.
This commit is contained in:
parent
c70b985911
commit
7c2e57e105
17 changed files with 83 additions and 64 deletions
|
@ -125,7 +125,6 @@
|
||||||
path.closed = true;
|
path.closed = true;
|
||||||
var thrust = new Path([-8, -4], [-14, 0], [-8, 4]);
|
var thrust = new Path([-8, -4], [-14, 0], [-8, 4]);
|
||||||
var group = new Group(path, thrust);
|
var group = new Group(path, thrust);
|
||||||
group.applyMatrix = true;
|
|
||||||
group.position = view.bounds.center;
|
group.position = view.bounds.center;
|
||||||
return {
|
return {
|
||||||
item: group,
|
item: group,
|
||||||
|
|
|
@ -27,21 +27,21 @@
|
||||||
var radius = this.radius = 50 * Math.random() + 30;
|
var radius = this.radius = 50 * Math.random() + 30;
|
||||||
// Wrap CompoundPath in a Group, since CompoundPaths directly
|
// Wrap CompoundPath in a Group, since CompoundPaths directly
|
||||||
// applies the transformations to the content, just like Path.
|
// applies the transformations to the content, just like Path.
|
||||||
this.item = new Group({
|
var ball = new CompoundPath({
|
||||||
children: [
|
children: [
|
||||||
new CompoundPath({
|
new Path.Circle({
|
||||||
children: [
|
radius: radius
|
||||||
new Path.Circle({
|
}),
|
||||||
radius: radius
|
new Path.Circle({
|
||||||
}),
|
center: radius / 8,
|
||||||
new Path.Circle({
|
radius: radius / 3
|
||||||
center: radius / 8,
|
|
||||||
radius: radius / 3
|
|
||||||
})
|
|
||||||
],
|
|
||||||
fillColor: new Color(gradient, 0, radius, radius / 8),
|
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
|
fillColor: new Color(gradient, 0, radius, radius / 8),
|
||||||
|
});
|
||||||
|
|
||||||
|
this.item = new Clip({
|
||||||
|
children: [ball],
|
||||||
position: this.point
|
position: this.point
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
project.importSVG(document.getElementById('svg'));
|
project.importSVG(document.getElementById('svg'));
|
||||||
|
|
||||||
// Resize the tiger to fit within the window:
|
// Resize the tiger to fit within the window:
|
||||||
project.activeLayer.applyMatrix = true;
|
|
||||||
project.activeLayer.fitBounds(view.bounds);
|
project.activeLayer.fitBounds(view.bounds);
|
||||||
|
|
||||||
var items = project.activeLayer.firstChild.children;
|
var items = project.activeLayer.firstChild.children;
|
||||||
|
|
|
@ -123,7 +123,6 @@
|
||||||
|
|
||||||
var count = 30;
|
var count = 30;
|
||||||
var group = new Group(paths);
|
var group = new Group(paths);
|
||||||
group.applyMatrix = true;
|
|
||||||
var headGroup;
|
var headGroup;
|
||||||
var eyePosition = new Point();
|
var eyePosition = new Point();
|
||||||
var eyeFollow = (Point.random() - 0.5);
|
var eyeFollow = (Point.random() - 0.5);
|
||||||
|
|
|
@ -12,10 +12,6 @@
|
||||||
var yesGroup = words.children.yes;
|
var yesGroup = words.children.yes;
|
||||||
var noGroup = words.children.no;
|
var noGroup = words.children.no;
|
||||||
|
|
||||||
project.activeLayer.applyMatrix = true;
|
|
||||||
noGroup.applyMatrix = true;
|
|
||||||
yesGroup.applyMatrix = true;
|
|
||||||
|
|
||||||
// Resize the words to fit snugly inside the view:
|
// Resize the words to fit snugly inside the view:
|
||||||
project.activeLayer.fitBounds(view.bounds);
|
project.activeLayer.fitBounds(view.bounds);
|
||||||
project.activeLayer.scale(0.8);
|
project.activeLayer.scale(0.8);
|
||||||
|
|
|
@ -69,7 +69,6 @@
|
||||||
// Transform the raster, so it fills the view:
|
// Transform the raster, so it fills the view:
|
||||||
raster.fitBounds(view.bounds, true);
|
raster.fitBounds(view.bounds, true);
|
||||||
group = new Group();
|
group = new Group();
|
||||||
group.applyMatrix = true;
|
|
||||||
for (var y = 0; y < values.amount; y++) {
|
for (var y = 0; y < values.amount; y++) {
|
||||||
for (var x = 0; x < values.amount; x++) {
|
for (var x = 0; x < values.amount; x++) {
|
||||||
var copy = piece.clone();
|
var copy = piece.clone();
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
|
|
||||||
// Create the group of circle shaped paths and scale it up a bit:
|
// Create the group of circle shaped paths and scale it up a bit:
|
||||||
var group = createPhyllotaxis(values.amount);
|
var group = createPhyllotaxis(values.amount);
|
||||||
group.applyMatrix = true;
|
|
||||||
group.scale(3);
|
group.scale(3);
|
||||||
|
|
||||||
function createPhyllotaxis(amount) {
|
function createPhyllotaxis(amount) {
|
||||||
|
|
26
src/item/Clip.js
Normal file
26
src/item/Clip.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
|
||||||
|
* http://paperjs.org/
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
|
||||||
|
* http://lehni.org/ & http://jonathanpuckey.com/
|
||||||
|
*
|
||||||
|
* Distributed under the MIT license. See LICENSE file for details.
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Clip
|
||||||
|
*
|
||||||
|
* @class A Clip is a collection of items, similar to a Group. But instead of
|
||||||
|
* automatically passing on transformations to its children by calling
|
||||||
|
* {@link Item#applyMatrix()}, the transformations are stored in the internal
|
||||||
|
* matrix.
|
||||||
|
*
|
||||||
|
* @extends Group
|
||||||
|
*/
|
||||||
|
var Clip = this.Clip = Group.extend(/** @lends Clip# */{
|
||||||
|
_class: 'Clip',
|
||||||
|
_applyMatrix: false
|
||||||
|
});
|
|
@ -37,6 +37,9 @@ var Item = this.Item = Base.extend(Callback, {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, /** @lends Item# */{
|
}, /** @lends Item# */{
|
||||||
|
// All items apply their matrix by default.
|
||||||
|
// Exceptions are Raster, PlacedSymbol, Clip and Shape.
|
||||||
|
_applyMatrix: true,
|
||||||
_boundsSelected: false,
|
_boundsSelected: false,
|
||||||
// Provide information about fields to be serialized, with their defaults
|
// Provide information about fields to be serialized, with their defaults
|
||||||
// that can be ommited.
|
// that can be ommited.
|
||||||
|
@ -508,16 +511,6 @@ var Item = this.Item = Base.extend(Callback, {
|
||||||
*/
|
*/
|
||||||
_guide: false,
|
_guide: false,
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies whether the item directly transforms its contents when
|
|
||||||
* transformations are applied to it, or wether it simply stores them in
|
|
||||||
* {@link Item#matrix}.
|
|
||||||
*
|
|
||||||
* @type Boolean
|
|
||||||
* @default false
|
|
||||||
*/
|
|
||||||
applyMatrix: false,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether an item is selected and will also return {@code true}
|
* Specifies whether an item is selected and will also return {@code true}
|
||||||
* if the item is partially selected (groups with some selected or partially
|
* if the item is partially selected (groups with some selected or partially
|
||||||
|
@ -1203,7 +1196,7 @@ var Item = this.Item = Base.extend(Callback, {
|
||||||
// TODO: Consider moving this to Base once it's useful in more than one
|
// TODO: Consider moving this to Base once it's useful in more than one
|
||||||
// place
|
// place
|
||||||
var keys = ['_locked', '_visible', '_blendMode', '_opacity',
|
var keys = ['_locked', '_visible', '_blendMode', '_opacity',
|
||||||
'_clipMask', '_guide', 'applyMatrix'];
|
'_clipMask', '_guide'];
|
||||||
for (var i = 0, l = keys.length; i < l; i++) {
|
for (var i = 0, l = keys.length; i < l; i++) {
|
||||||
var key = keys[i];
|
var key = keys[i];
|
||||||
if (this.hasOwnProperty(key))
|
if (this.hasOwnProperty(key))
|
||||||
|
@ -2193,26 +2186,10 @@ var Item = this.Item = Base.extend(Callback, {
|
||||||
position = this._position;
|
position = this._position;
|
||||||
// Simply preconcatenate the internal matrix with the passed one:
|
// Simply preconcatenate the internal matrix with the passed one:
|
||||||
this._matrix.preConcatenate(matrix);
|
this._matrix.preConcatenate(matrix);
|
||||||
if (this._transform)
|
// Call applyMatrix if we need to directly apply the accumulated
|
||||||
this._transform(matrix);
|
// transformations to the item's content.
|
||||||
// If we need to directly apply the accumulated transformations, call
|
if (this._applyMatrix || arguments[1])
|
||||||
// #_applyMatrix() with the internal _matrix, and set it to the identity
|
this.applyMatrix(false);
|
||||||
// transformation if it was possible to apply it. Application is not
|
|
||||||
// possible on Raster, PointText, PlacedSymbol, since the matrix is
|
|
||||||
// storing the actual location / transformation state.
|
|
||||||
if ((this.applyMatrix || arguments[1])
|
|
||||||
&& this._applyMatrix(this._matrix)) {
|
|
||||||
// When the matrix could be applied, we also need to transform
|
|
||||||
// color styles with matrices (only gradients so far):
|
|
||||||
var style = this._style,
|
|
||||||
fillColor = style.getFillColor(),
|
|
||||||
strokeColor = style.getStrokeColor();
|
|
||||||
if (fillColor)
|
|
||||||
fillColor.transform(this._matrix);
|
|
||||||
if (strokeColor)
|
|
||||||
strokeColor.transform(this._matrix);
|
|
||||||
this._matrix.reset();
|
|
||||||
}
|
|
||||||
// We always need to call _changed since we're caching bounds on all
|
// We always need to call _changed since we're caching bounds on all
|
||||||
// items, including Group.
|
// items, including Group.
|
||||||
this._changed(/*#=*/ Change.GEOMETRY);
|
this._changed(/*#=*/ Change.GEOMETRY);
|
||||||
|
@ -2242,16 +2219,39 @@ var Item = this.Item = Base.extend(Callback, {
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
_applyMatrix: function(matrix) {
|
_transformContent: function(matrix, applyMatrix) {
|
||||||
// Pass on the transformation to the children, and apply it there too,
|
|
||||||
// by passing true for the 2nd hidden parameter.
|
|
||||||
if (this._children) {
|
if (this._children) {
|
||||||
for (var i = 0, l = this._children.length; i < l; i++)
|
for (var i = 0, l = this._children.length; i < l; i++)
|
||||||
this._children[i].transform(matrix, true);
|
this._children[i].transform(matrix, applyMatrix);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
applyMatrix: function(_dontNotify) {
|
||||||
|
// Call #_transformContent() with the internal _matrix and pass true for
|
||||||
|
// applyMatrix. Application is not possible on Raster, PointText,
|
||||||
|
// PlacedSymbol, since the matrix is where the actual location /
|
||||||
|
// transformation state is stored.
|
||||||
|
// Pass on the transformation to the content, and apply it there too,
|
||||||
|
// by passing true for the 2nd hidden parameter.
|
||||||
|
if (this._transformContent(this._matrix, true)) {
|
||||||
|
// When the matrix could be applied, we also need to transform
|
||||||
|
// color styles with matrices (only gradients so far):
|
||||||
|
var style = this._style,
|
||||||
|
fillColor = style.getFillColor(true),
|
||||||
|
strokeColor = style.getStrokeColor(true);
|
||||||
|
if (fillColor)
|
||||||
|
fillColor.transform(this._matrix);
|
||||||
|
if (strokeColor)
|
||||||
|
strokeColor.transform(this._matrix);
|
||||||
|
// Reset the internal matrix to the identity transformation if it
|
||||||
|
// was possible to apply it.
|
||||||
|
this._matrix.reset();
|
||||||
|
}
|
||||||
|
if (!_dontNotify)
|
||||||
|
this._changed(/*#=*/ Change.GEOMETRY);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform the item so that its {@link #bounds} fit within the specified
|
* Transform the item so that its {@link #bounds} fit within the specified
|
||||||
* rectangle, without changing its aspect ratio.
|
* rectangle, without changing its aspect ratio.
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
*/
|
*/
|
||||||
var PlacedSymbol = this.PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
|
var PlacedSymbol = this.PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
|
||||||
_class: 'PlacedSymbol',
|
_class: 'PlacedSymbol',
|
||||||
|
_applyMatrix: false,
|
||||||
// PlacedSymbol uses strokeBounds for bounds
|
// PlacedSymbol uses strokeBounds for bounds
|
||||||
_boundsGetter: { getBounds: 'getStrokeBounds' },
|
_boundsGetter: { getBounds: 'getStrokeBounds' },
|
||||||
_boundsSelected: true,
|
_boundsSelected: true,
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
var Raster = this.Raster = Item.extend(/** @lends Raster# */{
|
var Raster = this.Raster = Item.extend(/** @lends Raster# */{
|
||||||
_class: 'Raster',
|
_class: 'Raster',
|
||||||
|
_applyMatrix: false,
|
||||||
// Raster doesn't make the distinction between the different bounds,
|
// Raster doesn't make the distinction between the different bounds,
|
||||||
// so use the same name for all of them
|
// so use the same name for all of them
|
||||||
_boundsGetter: 'getBounds',
|
_boundsGetter: 'getBounds',
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
var Shape = this.Shape = Item.extend(/** @lends Shape# */{
|
var Shape = this.Shape = Item.extend(/** @lends Shape# */{
|
||||||
_class: 'Shape',
|
_class: 'Shape',
|
||||||
|
_applyMatrix: false,
|
||||||
|
|
||||||
initialize: function(type, point, size) {
|
initialize: function(type, point, size) {
|
||||||
this.base(point);
|
this.base(point);
|
||||||
|
|
|
@ -67,6 +67,7 @@ var paper = new function() {
|
||||||
/*#*/ include('item/Item.js');
|
/*#*/ include('item/Item.js');
|
||||||
/*#*/ include('item/Group.js');
|
/*#*/ include('item/Group.js');
|
||||||
/*#*/ include('item/Layer.js');
|
/*#*/ include('item/Layer.js');
|
||||||
|
/*#*/ include('item/Clip.js');
|
||||||
/*#*/ include('item/Shape.js');
|
/*#*/ include('item/Shape.js');
|
||||||
/*#*/ include('item/Raster.js');
|
/*#*/ include('item/Raster.js');
|
||||||
/*#*/ include('item/PlacedSymbol.js');
|
/*#*/ include('item/PlacedSymbol.js');
|
||||||
|
|
|
@ -300,7 +300,7 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
_applyMatrix: function(matrix) {
|
_transformContent: function(matrix) {
|
||||||
var coords = new Array(6);
|
var coords = new Array(6);
|
||||||
for (var i = 0, l = this._segments.length; i < l; i++)
|
for (var i = 0, l = this._segments.length; i < l; i++)
|
||||||
this._segments[i]._transformCoordinates(matrix, coords, true);
|
this._segments[i]._transformCoordinates(matrix, coords, true);
|
||||||
|
@ -1539,7 +1539,7 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
||||||
* the specified point
|
* the specified point
|
||||||
*/
|
*/
|
||||||
getNearestLocation: function(point) {
|
getNearestLocation: function(point) {
|
||||||
point = this._matrix.inverseTransform(Point.read(arguments));
|
point = Point.read(arguments);
|
||||||
var curves = this.getCurves(),
|
var curves = this.getCurves(),
|
||||||
minDist = Infinity,
|
minDist = Infinity,
|
||||||
minLoc = null;
|
minLoc = null;
|
||||||
|
|
|
@ -20,9 +20,6 @@
|
||||||
* @extends Item
|
* @extends Item
|
||||||
*/
|
*/
|
||||||
var PathItem = this.PathItem = Item.extend(/** @lends PathItem# */{
|
var PathItem = this.PathItem = Item.extend(/** @lends PathItem# */{
|
||||||
// All PathItems directly apply transformations by default.
|
|
||||||
applyMatrix: true,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all intersections between two {@link PathItem} items as an array
|
* Returns all intersections between two {@link PathItem} items as an array
|
||||||
* of {@link CurveLocation} objects. {@link CompoundPath} items are also
|
* of {@link CurveLocation} objects. {@link CompoundPath} items are also
|
||||||
|
|
|
@ -151,12 +151,13 @@ var Style = this.Style = Base.extend(new function() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fields[get] = function() {
|
fields[get] = function(/* dontMerge */) {
|
||||||
var value,
|
var value,
|
||||||
children = this._item && this._item._children;
|
children = this._item && this._item._children;
|
||||||
// If this item has children, walk through all of them and see if
|
// If this item has children, walk through all of them and see if
|
||||||
// they all have the same style.
|
// they all have the same style.
|
||||||
if (!children || children.length === 0
|
// If true is passed for dontMerge, don't merge children styles
|
||||||
|
if (!children || children.length === 0 || arguments[0]
|
||||||
|| this._item._type === 'compound-path') {
|
|| this._item._type === 'compound-path') {
|
||||||
var value = this._values[key];
|
var value = this._values[key];
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
|
|
|
@ -53,7 +53,7 @@ test('path.bounds when contained in a transformed group', function() {
|
||||||
var group = new Group([path]);
|
var group = new Group([path]);
|
||||||
compareRectangles(path.bounds, { x: 10, y: 10, width: 50, height: 50 }, 'path.bounds before group translation');
|
compareRectangles(path.bounds, { x: 10, y: 10, width: 50, height: 50 }, 'path.bounds before group translation');
|
||||||
group.translate(100, 100);
|
group.translate(100, 100);
|
||||||
compareRectangles(path.bounds, { x: 10, y: 10, width: 50, height: 50 }, 'path.bounds after group translation');
|
compareRectangles(path.bounds, { x: 110, y: 110, width: 50, height: 50 }, 'path.bounds after group translation');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('text.bounds', function() {
|
test('text.bounds', function() {
|
||||||
|
|
Loading…
Reference in a new issue