forked from paperjs/paper.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGroup.js
More file actions
199 lines (190 loc) · 5.29 KB
/
Copy pathGroup.js
File metadata and controls
199 lines (190 loc) · 5.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
* 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 Group
*
* @class A Group is a collection of items. When you transform a Group, its
* children are treated as a single unit without changing their relative
* positions.
*
* @extends Item
*/
var Group = Item.extend(/** @lends Group# */{
_class: 'Group',
_serializeFields: {
children: []
},
// DOCS: document new Group(item, item...);
/**
* Creates a new Group item and places it at the top of the active layer.
*
* @name Group#initialize
* @param {Item[]} [children] An array of children that will be added to the
* newly created group.
*
* @example {@paperscript}
* // Create a group containing two paths:
* var path = new Path([100, 100], [100, 200]);
* var path2 = new Path([50, 150], [150, 150]);
*
* // Create a group from the two paths:
* var group = new Group([path, path2]);
*
* // Set the stroke color of all items in the group:
* group.strokeColor = 'black';
*
* // Move the group to the center of the view:
* group.position = view.center;
*
* @example {@paperscript height=320}
* // Click in the view to add a path to the group, which in turn is rotated
* // every frame:
* var group = new Group();
*
* function onMouseDown(event) {
* // Create a new circle shaped path at the position
* // of the mouse:
* var path = new Path.Circle(event.point, 5);
* path.fillColor = 'black';
*
* // Add the path to the group's children list:
* group.addChild(path);
* }
*
* function onFrame(event) {
* // Rotate the group by 1 degree from
* // the centerpoint of the view:
* group.rotate(1, view.center);
* }
*/
/**
* Creates a new Group item and places it at the top of the active layer.
*
* @name Group#initialize
* @param {Object} object an object literal containing the properties to be
* set on the group.
*
* @example {@paperscript}
* var path = new Path([100, 100], [100, 200]);
* var path2 = new Path([50, 150], [150, 150]);
*
* // Create a group from the two paths:
* var group = new Group({
* children: [path, path2],
* // Set the stroke color of all items in the group:
* strokeColor: 'black',
* // Move the group to the center of the view:
* position: view.center
* });
*/
initialize: function Group(arg) {
// Allow Group to have children and named children
this._children = [];
this._namedChildren = {};
if (!this._initialize(arg))
this.addChildren(Array.isArray(arg) ? arg : arguments);
},
_changed: function _changed(flags) {
_changed.base.call(this, flags);
if (flags & /*#=*/ ChangeFlag.HIERARCHY && this._transformContent
&& !this._matrix.isIdentity()) {
// Apply matrix now that we have content.
this.applyMatrix();
}
if (flags & (/*#=*/ ChangeFlag.HIERARCHY | /*#=*/ ChangeFlag.CLIPPING)) {
// Clear cached clip item whenever hierarchy changes
delete this._clipItem;
}
},
_getClipItem: function() {
// Allow us to set _clipItem to null when none is found and still return
// it as a defined value without searching again
if (this._clipItem !== undefined)
return this._clipItem;
for (var i = 0, l = this._children.length; i < l; i++) {
var child = this._children[i];
if (child._clipMask)
return this._clipItem = child;
}
// Make sure we're setting _clipItem to null so it won't be searched for
// nex time.
return this._clipItem = null;
},
/**
* Specifies whether the group applies transformations directly to its
* children, or whether they are to be stored in its {@link Item#matrix}
*
* @type Boolean
* @default true
* @bean
*/
getTransformContent: function() {
return this._transformContent;
},
setTransformContent: function(transform) {
this._transformContent = transform;
if (transform)
this.applyMatrix();
},
/**
* Specifies whether the group item is to be clipped.
* When setting to {@code true}, the first child in the group is
* automatically defined as the clipping mask.
*
* @type Boolean
* @bean
*
* @example {@paperscript}
* var star = new Path.Star({
* center: view.center,
* points: 6,
* radius1: 20,
* radius2: 40,
* fillColor: 'red'
* });
*
* var circle = new Path.Circle({
* center: view.center,
* radius: 25,
* strokeColor: 'black'
* });
*
* // Create a group of the two items and clip it:
* var group = new Group(circle, star);
* group.clipped = true;
*
* // Lets animate the circle:
* function onFrame(event) {
* var offset = Math.sin(event.count / 30) * 30;
* circle.position.x = view.center.x + offset;
* }
*/
isClipped: function() {
return !!this._getClipItem();
},
setClipped: function(clipped) {
var child = this.getFirstChild();
if (child)
child.setClipMask(clipped);
},
_draw: function(ctx, param) {
var clipItem = param.clipItem = this._getClipItem();
if (clipItem)
clipItem.draw(ctx, param.extend({ clip: true }));
for (var i = 0, l = this._children.length; i < l; i++) {
var item = this._children[i];
if (item !== clipItem)
item.draw(ctx, param);
}
param.clipItem = null;
}
});