mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2024-12-29 09:22:22 -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;
|
||||
var thrust = new Path([-8, -4], [-14, 0], [-8, 4]);
|
||||
var group = new Group(path, thrust);
|
||||
group.applyMatrix = true;
|
||||
group.position = view.bounds.center;
|
||||
return {
|
||||
item: group,
|
||||
|
|
|
@ -27,21 +27,21 @@
|
|||
var radius = this.radius = 50 * Math.random() + 30;
|
||||
// Wrap CompoundPath in a Group, since CompoundPaths directly
|
||||
// applies the transformations to the content, just like Path.
|
||||
this.item = new Group({
|
||||
var ball = new CompoundPath({
|
||||
children: [
|
||||
new CompoundPath({
|
||||
children: [
|
||||
new Path.Circle({
|
||||
radius: radius
|
||||
}),
|
||||
new Path.Circle({
|
||||
center: radius / 8,
|
||||
radius: radius / 3
|
||||
})
|
||||
],
|
||||
fillColor: new Color(gradient, 0, radius, radius / 8),
|
||||
new Path.Circle({
|
||||
radius: radius
|
||||
}),
|
||||
new Path.Circle({
|
||||
center: radius / 8,
|
||||
radius: radius / 3
|
||||
})
|
||||
],
|
||||
fillColor: new Color(gradient, 0, radius, radius / 8),
|
||||
});
|
||||
|
||||
this.item = new Clip({
|
||||
children: [ball],
|
||||
position: this.point
|
||||
});
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
project.importSVG(document.getElementById('svg'));
|
||||
|
||||
// Resize the tiger to fit within the window:
|
||||
project.activeLayer.applyMatrix = true;
|
||||
project.activeLayer.fitBounds(view.bounds);
|
||||
|
||||
var items = project.activeLayer.firstChild.children;
|
||||
|
|
|
@ -123,7 +123,6 @@
|
|||
|
||||
var count = 30;
|
||||
var group = new Group(paths);
|
||||
group.applyMatrix = true;
|
||||
var headGroup;
|
||||
var eyePosition = new Point();
|
||||
var eyeFollow = (Point.random() - 0.5);
|
||||
|
|
|
@ -12,10 +12,6 @@
|
|||
var yesGroup = words.children.yes;
|
||||
var noGroup = words.children.no;
|
||||
|
||||
project.activeLayer.applyMatrix = true;
|
||||
noGroup.applyMatrix = true;
|
||||
yesGroup.applyMatrix = true;
|
||||
|
||||
// Resize the words to fit snugly inside the view:
|
||||
project.activeLayer.fitBounds(view.bounds);
|
||||
project.activeLayer.scale(0.8);
|
||||
|
|
|
@ -69,7 +69,6 @@
|
|||
// Transform the raster, so it fills the view:
|
||||
raster.fitBounds(view.bounds, true);
|
||||
group = new Group();
|
||||
group.applyMatrix = true;
|
||||
for (var y = 0; y < values.amount; y++) {
|
||||
for (var x = 0; x < values.amount; x++) {
|
||||
var copy = piece.clone();
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
// Create the group of circle shaped paths and scale it up a bit:
|
||||
var group = createPhyllotaxis(values.amount);
|
||||
group.applyMatrix = true;
|
||||
group.scale(3);
|
||||
|
||||
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# */{
|
||||
// All items apply their matrix by default.
|
||||
// Exceptions are Raster, PlacedSymbol, Clip and Shape.
|
||||
_applyMatrix: true,
|
||||
_boundsSelected: false,
|
||||
// Provide information about fields to be serialized, with their defaults
|
||||
// that can be ommited.
|
||||
|
@ -508,16 +511,6 @@ var Item = this.Item = Base.extend(Callback, {
|
|||
*/
|
||||
_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}
|
||||
* 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
|
||||
// place
|
||||
var keys = ['_locked', '_visible', '_blendMode', '_opacity',
|
||||
'_clipMask', '_guide', 'applyMatrix'];
|
||||
'_clipMask', '_guide'];
|
||||
for (var i = 0, l = keys.length; i < l; i++) {
|
||||
var key = keys[i];
|
||||
if (this.hasOwnProperty(key))
|
||||
|
@ -2193,26 +2186,10 @@ var Item = this.Item = Base.extend(Callback, {
|
|||
position = this._position;
|
||||
// Simply preconcatenate the internal matrix with the passed one:
|
||||
this._matrix.preConcatenate(matrix);
|
||||
if (this._transform)
|
||||
this._transform(matrix);
|
||||
// If we need to directly apply the accumulated transformations, call
|
||||
// #_applyMatrix() with the internal _matrix, and set it to the identity
|
||||
// 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();
|
||||
}
|
||||
// Call applyMatrix if we need to directly apply the accumulated
|
||||
// transformations to the item's content.
|
||||
if (this._applyMatrix || arguments[1])
|
||||
this.applyMatrix(false);
|
||||
// We always need to call _changed since we're caching bounds on all
|
||||
// items, including Group.
|
||||
this._changed(/*#=*/ Change.GEOMETRY);
|
||||
|
@ -2242,16 +2219,39 @@ var Item = this.Item = Base.extend(Callback, {
|
|||
return this;
|
||||
},
|
||||
|
||||
_applyMatrix: function(matrix) {
|
||||
// Pass on the transformation to the children, and apply it there too,
|
||||
// by passing true for the 2nd hidden parameter.
|
||||
_transformContent: function(matrix, applyMatrix) {
|
||||
if (this._children) {
|
||||
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;
|
||||
}
|
||||
},
|
||||
|
||||
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
|
||||
* rectangle, without changing its aspect ratio.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*/
|
||||
var PlacedSymbol = this.PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
|
||||
_class: 'PlacedSymbol',
|
||||
_applyMatrix: false,
|
||||
// PlacedSymbol uses strokeBounds for bounds
|
||||
_boundsGetter: { getBounds: 'getStrokeBounds' },
|
||||
_boundsSelected: true,
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
var Raster = this.Raster = Item.extend(/** @lends Raster# */{
|
||||
_class: 'Raster',
|
||||
_applyMatrix: false,
|
||||
// Raster doesn't make the distinction between the different bounds,
|
||||
// so use the same name for all of them
|
||||
_boundsGetter: 'getBounds',
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
var Shape = this.Shape = Item.extend(/** @lends Shape# */{
|
||||
_class: 'Shape',
|
||||
_applyMatrix: false,
|
||||
|
||||
initialize: function(type, point, size) {
|
||||
this.base(point);
|
||||
|
|
|
@ -67,6 +67,7 @@ var paper = new function() {
|
|||
/*#*/ include('item/Item.js');
|
||||
/*#*/ include('item/Group.js');
|
||||
/*#*/ include('item/Layer.js');
|
||||
/*#*/ include('item/Clip.js');
|
||||
/*#*/ include('item/Shape.js');
|
||||
/*#*/ include('item/Raster.js');
|
||||
/*#*/ include('item/PlacedSymbol.js');
|
||||
|
|
|
@ -300,7 +300,7 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
|||
return true;
|
||||
},
|
||||
|
||||
_applyMatrix: function(matrix) {
|
||||
_transformContent: function(matrix) {
|
||||
var coords = new Array(6);
|
||||
for (var i = 0, l = this._segments.length; i < l; i++)
|
||||
this._segments[i]._transformCoordinates(matrix, coords, true);
|
||||
|
@ -1539,7 +1539,7 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
|||
* the specified point
|
||||
*/
|
||||
getNearestLocation: function(point) {
|
||||
point = this._matrix.inverseTransform(Point.read(arguments));
|
||||
point = Point.read(arguments);
|
||||
var curves = this.getCurves(),
|
||||
minDist = Infinity,
|
||||
minLoc = null;
|
||||
|
|
|
@ -20,9 +20,6 @@
|
|||
* @extends Item
|
||||
*/
|
||||
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
|
||||
* 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,
|
||||
children = this._item && this._item._children;
|
||||
// If this item has children, walk through all of them and see if
|
||||
// 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') {
|
||||
var value = this._values[key];
|
||||
if (value === undefined) {
|
||||
|
|
|
@ -53,7 +53,7 @@ test('path.bounds when contained in a transformed group', function() {
|
|||
var group = new Group([path]);
|
||||
compareRectangles(path.bounds, { x: 10, y: 10, width: 50, height: 50 }, 'path.bounds before group translation');
|
||||
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() {
|
||||
|
|
Loading…
Reference in a new issue