paper 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +95 -0
- package/dist/docs/assets/js/paper.js +4565 -733
- package/dist/docs/classes/AreaText.html +720 -242
- package/dist/docs/classes/ChangeFlag.html +1 -1
- package/dist/docs/classes/Color.html +218 -21
- package/dist/docs/classes/CompoundPath.html +1146 -296
- package/dist/docs/classes/Curve.html +1 -1
- package/dist/docs/classes/CurveLocation.html +1 -1
- package/dist/docs/classes/DrawEvent.html +69 -0
- package/dist/docs/classes/Effect.html +434 -0
- package/dist/docs/classes/EffectInstance.html +304 -0
- package/dist/docs/classes/Event.html +1 -1
- package/dist/docs/classes/Gradient.html +1 -1
- package/dist/docs/classes/GradientStop.html +1 -1
- package/dist/docs/classes/Group.html +792 -243
- package/dist/docs/classes/HitResult.html +1 -1
- package/dist/docs/classes/HostItem.html +720 -242
- package/dist/docs/classes/Item.html +777 -242
- package/dist/docs/classes/Key.html +1 -1
- package/dist/docs/classes/KeyEvent.html +1 -1
- package/dist/docs/classes/Layer.html +734 -185
- package/dist/docs/classes/Matrix.html +1 -1
- package/dist/docs/classes/MouseEvent.html +1 -1
- package/dist/docs/classes/PaperScope.html +1 -1
- package/dist/docs/classes/PaperScript.html +4 -2
- package/dist/docs/classes/Path.html +1195 -252
- package/dist/docs/classes/PathItem.html +1148 -298
- package/dist/docs/classes/PathText.html +720 -242
- package/dist/docs/classes/PatternDefinition.html +367 -0
- package/dist/docs/classes/Point.html +1 -1
- package/dist/docs/classes/PointText.html +720 -242
- package/dist/docs/classes/Project.html +177 -7
- package/dist/docs/classes/Raster.html +720 -242
- package/dist/docs/classes/Rectangle.html +1 -1
- package/dist/docs/classes/Segment.html +3 -3
- package/dist/docs/classes/Shape.html +720 -242
- package/dist/docs/classes/Size.html +1 -1
- package/dist/docs/classes/StrokeProfileStop.html +346 -0
- package/dist/docs/classes/Style.html +1 -1
- package/dist/docs/classes/SymbolDefinition.html +28 -2
- package/dist/docs/classes/SymbolItem.html +720 -242
- package/dist/docs/classes/TextItem.html +720 -242
- package/dist/docs/classes/TextRange.html +1 -1
- package/dist/docs/classes/TextStory.html +1 -1
- package/dist/docs/classes/Tool.html +2 -2
- package/dist/docs/classes/ToolEvent.html +1 -1
- package/dist/docs/classes/Tween.html +1 -1
- package/dist/docs/classes/View.html +2 -2
- package/dist/docs/classes/global.html +1 -1
- package/dist/docs/classes/index.html +2 -2
- package/dist/docs/index.html +1 -1
- package/dist/node/browser.js +15 -0
- package/dist/paper-core.js +4476 -674
- package/dist/paper-core.min.js +3 -3
- package/dist/paper-full.js +4565 -733
- package/dist/paper-full.min.js +3 -3
- package/dist/paper-hosted.js +5111 -823
- package/dist/paper.d.ts +898 -47
- package/examples/Paperjs.org/LiveEffects.html +366 -0
- package/examples/Paperjs.org/Offsetting.html +379 -0
- package/examples/Paperjs.org/StrokeProfiles.html +706 -0
- package/examples/Scripts/Patterns.html +57 -0
- package/package.json +5 -3
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Live Effects</title>
|
|
6
|
+
<link rel="stylesheet" href="../css/style.css">
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
background: #f6f4f0;
|
|
10
|
+
font: 13px/1.4 -apple-system, 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
|
11
|
+
color: #333;
|
|
12
|
+
}
|
|
13
|
+
.panel {
|
|
14
|
+
position: absolute;
|
|
15
|
+
top: 12px;
|
|
16
|
+
right: 12px;
|
|
17
|
+
width: 260px;
|
|
18
|
+
max-height: calc(100% - 52px);
|
|
19
|
+
overflow-y: auto;
|
|
20
|
+
padding: 14px 16px;
|
|
21
|
+
background: rgba(255, 255, 255, 0.92);
|
|
22
|
+
border-radius: 12px;
|
|
23
|
+
box-shadow: 0 2px 16px rgba(0, 0, 0, 0.12);
|
|
24
|
+
}
|
|
25
|
+
.panel h1 {
|
|
26
|
+
margin: 0 0 10px;
|
|
27
|
+
font-size: 16px;
|
|
28
|
+
}
|
|
29
|
+
.panel label {
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: space-between;
|
|
33
|
+
gap: 8px;
|
|
34
|
+
margin: 6px 0;
|
|
35
|
+
}
|
|
36
|
+
.panel input[type=range] {
|
|
37
|
+
width: 120px;
|
|
38
|
+
}
|
|
39
|
+
.panel select {
|
|
40
|
+
width: 128px;
|
|
41
|
+
}
|
|
42
|
+
.effect {
|
|
43
|
+
margin: 8px 0;
|
|
44
|
+
padding: 6px 10px;
|
|
45
|
+
border: 1px solid #ddd;
|
|
46
|
+
border-radius: 8px;
|
|
47
|
+
background: white;
|
|
48
|
+
}
|
|
49
|
+
.effect.hidden {
|
|
50
|
+
opacity: 0.5;
|
|
51
|
+
}
|
|
52
|
+
.effect header {
|
|
53
|
+
display: flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
gap: 6px;
|
|
56
|
+
font-weight: 600;
|
|
57
|
+
}
|
|
58
|
+
.effect header span {
|
|
59
|
+
flex: 1;
|
|
60
|
+
}
|
|
61
|
+
.effect button {
|
|
62
|
+
padding: 0 6px;
|
|
63
|
+
}
|
|
64
|
+
.panel .info {
|
|
65
|
+
margin-top: 10px;
|
|
66
|
+
color: #888;
|
|
67
|
+
font-size: 11px;
|
|
68
|
+
}
|
|
69
|
+
</style>
|
|
70
|
+
<script type="text/javascript" src="../../dist/paper-full.js"></script>
|
|
71
|
+
<script type="text/paperscript" canvas="canvas">
|
|
72
|
+
var presets = {
|
|
73
|
+
'Star': function() {
|
|
74
|
+
return new Path.Star({
|
|
75
|
+
center: view.center,
|
|
76
|
+
points: 6,
|
|
77
|
+
radius1: 70,
|
|
78
|
+
radius2: 150,
|
|
79
|
+
fillColor: '#ffcf5c',
|
|
80
|
+
strokeColor: '#e0306a',
|
|
81
|
+
strokeWidth: 16,
|
|
82
|
+
strokeJoin: 'round'
|
|
83
|
+
});
|
|
84
|
+
},
|
|
85
|
+
'Wave': function() {
|
|
86
|
+
var path = new Path({
|
|
87
|
+
segments: [[-240, 60], [-120, -80], [0, 60], [120, -80],
|
|
88
|
+
[240, 60]],
|
|
89
|
+
strokeColor: '#e0306a',
|
|
90
|
+
strokeWidth: 24,
|
|
91
|
+
strokeCap: 'round'
|
|
92
|
+
});
|
|
93
|
+
path.smooth({ type: 'catmull-rom' });
|
|
94
|
+
path.position = view.center;
|
|
95
|
+
return path;
|
|
96
|
+
},
|
|
97
|
+
'Pressure': function() {
|
|
98
|
+
var path = presets['Wave']();
|
|
99
|
+
path.strokeProfile = [
|
|
100
|
+
{ offset: 0, width: 0.2 },
|
|
101
|
+
{ offset: path.length / 2, width: 1.6 },
|
|
102
|
+
{ offset: path.length, width: 0.2 }
|
|
103
|
+
];
|
|
104
|
+
return path;
|
|
105
|
+
},
|
|
106
|
+
'Blob': function() {
|
|
107
|
+
var path = new Path.Circle({
|
|
108
|
+
center: view.center,
|
|
109
|
+
radius: 120,
|
|
110
|
+
fillColor: '#5ca8ff'
|
|
111
|
+
});
|
|
112
|
+
path.segments[1].point += [60, 30];
|
|
113
|
+
path.segments[3].point -= [40, 50];
|
|
114
|
+
return path;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// The ranges of the number parameters, which the effects leave open:
|
|
119
|
+
var ranges = {
|
|
120
|
+
distance: [-60, 60],
|
|
121
|
+
miterLimit: [1, 20]
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
var settings = {
|
|
125
|
+
preset: 'Star',
|
|
126
|
+
showBounds: true
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
var path;
|
|
130
|
+
var drag = null;
|
|
131
|
+
var info = document.getElementById('info');
|
|
132
|
+
var list = document.getElementById('effects');
|
|
133
|
+
|
|
134
|
+
function createPreset(name) {
|
|
135
|
+
var effects = path ? path.effects : [];
|
|
136
|
+
if (path)
|
|
137
|
+
path.remove();
|
|
138
|
+
path = presets[name]();
|
|
139
|
+
path.set({
|
|
140
|
+
fullySelected: true,
|
|
141
|
+
selectedColor: '#222',
|
|
142
|
+
onDrawSelection: drawPreviewBounds
|
|
143
|
+
});
|
|
144
|
+
// Keep the effects when switching paths, as copies:
|
|
145
|
+
path.effects = effects.map(describe);
|
|
146
|
+
update();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Draws the preview bounds over the selection of the path, see
|
|
150
|
+
// Item#onDrawSelection:
|
|
151
|
+
function drawPreviewBounds(event) {
|
|
152
|
+
if (settings.showBounds) {
|
|
153
|
+
var ctx = event.context,
|
|
154
|
+
bounds = path.previewBounds,
|
|
155
|
+
topLeft = event.matrix.transform(bounds.topLeft),
|
|
156
|
+
bottomRight = event.matrix.transform(bounds.bottomRight);
|
|
157
|
+
ctx.setLineDash([4, 3]);
|
|
158
|
+
ctx.strokeStyle = '#1060ff';
|
|
159
|
+
ctx.strokeRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x,
|
|
160
|
+
bottomRight.y - topLeft.y);
|
|
161
|
+
ctx.setLineDash([]);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Returns the plain object that describes the effect instance, which
|
|
166
|
+
// items take to add it:
|
|
167
|
+
function describe(instance) {
|
|
168
|
+
return {
|
|
169
|
+
type: instance.type,
|
|
170
|
+
parameters: instance.parameters,
|
|
171
|
+
visible: instance.visible
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Builds the panel of each effect instance: its visibility, its order
|
|
176
|
+
// and its parameters, with the controls that its effect declares:
|
|
177
|
+
function updatePanel() {
|
|
178
|
+
list.innerHTML = '';
|
|
179
|
+
path.effects.forEach(function(instance) {
|
|
180
|
+
var effect = instance.effect,
|
|
181
|
+
element = document.createElement('div');
|
|
182
|
+
element.className = 'effect'
|
|
183
|
+
+ (instance.visible ? '' : ' hidden');
|
|
184
|
+
var header = document.createElement('header');
|
|
185
|
+
var visible = document.createElement('input');
|
|
186
|
+
visible.type = 'checkbox';
|
|
187
|
+
visible.checked = instance.visible;
|
|
188
|
+
visible.title = 'Visible';
|
|
189
|
+
visible.addEventListener('input', function() {
|
|
190
|
+
instance.visible = visible.checked;
|
|
191
|
+
element.classList.toggle('hidden', !instance.visible);
|
|
192
|
+
update(false);
|
|
193
|
+
});
|
|
194
|
+
var title = document.createElement('span');
|
|
195
|
+
title.textContent = effect.label;
|
|
196
|
+
header.appendChild(visible);
|
|
197
|
+
header.appendChild(title);
|
|
198
|
+
// Moves the instance by the amount in the order:
|
|
199
|
+
function move(amount) {
|
|
200
|
+
var index = instance.index + amount;
|
|
201
|
+
if (index >= 0 && index < path.effects.length) {
|
|
202
|
+
instance.remove();
|
|
203
|
+
path.insertEffect(index, describe(instance));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
[
|
|
208
|
+
['↑', function() { move(-1); }],
|
|
209
|
+
['↓', function() { move(1); }],
|
|
210
|
+
['✕', function() { instance.remove(); }]
|
|
211
|
+
].forEach(function(entry) {
|
|
212
|
+
var button = document.createElement('button');
|
|
213
|
+
button.textContent = entry[0];
|
|
214
|
+
button.addEventListener('click', function() {
|
|
215
|
+
entry[1]();
|
|
216
|
+
update();
|
|
217
|
+
});
|
|
218
|
+
header.appendChild(button);
|
|
219
|
+
});
|
|
220
|
+
element.appendChild(header);
|
|
221
|
+
Object.keys(effect.parameters).forEach(function(key) {
|
|
222
|
+
var parameter = effect.parameters[key],
|
|
223
|
+
isList = parameter.type === 'list',
|
|
224
|
+
range = ranges[key],
|
|
225
|
+
label = document.createElement('label'),
|
|
226
|
+
input = document.createElement(isList
|
|
227
|
+
? 'select' : 'input');
|
|
228
|
+
label.textContent = parameter.label;
|
|
229
|
+
if (isList) {
|
|
230
|
+
parameter.options.forEach(function(option) {
|
|
231
|
+
var node = document.createElement('option');
|
|
232
|
+
node.textContent = option;
|
|
233
|
+
input.appendChild(node);
|
|
234
|
+
});
|
|
235
|
+
} else {
|
|
236
|
+
input.type = 'range';
|
|
237
|
+
input.min = range[0];
|
|
238
|
+
input.max = range[1];
|
|
239
|
+
input.step = 0.5;
|
|
240
|
+
}
|
|
241
|
+
input.value = instance[key];
|
|
242
|
+
input.addEventListener('input', function() {
|
|
243
|
+
// Setting a parameter through its property redraws:
|
|
244
|
+
instance[key] = isList ? input.value : +input.value;
|
|
245
|
+
update(false);
|
|
246
|
+
});
|
|
247
|
+
label.appendChild(input);
|
|
248
|
+
element.appendChild(label);
|
|
249
|
+
});
|
|
250
|
+
list.appendChild(element);
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function update(rebuild) {
|
|
255
|
+
var time = Date.now();
|
|
256
|
+
path.getEffectOutput();
|
|
257
|
+
info.textContent = path.effects.length + ' effects, applied in '
|
|
258
|
+
+ (Date.now() - time) + ' ms.';
|
|
259
|
+
if (rebuild !== false)
|
|
260
|
+
updatePanel();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
document.getElementById('add').addEventListener('input', function() {
|
|
264
|
+
if (this.value) {
|
|
265
|
+
path.addEffect({
|
|
266
|
+
type: this.value,
|
|
267
|
+
parameters: this.value === 'offset'
|
|
268
|
+
? { distance: 20, join: 'round' } : {}
|
|
269
|
+
});
|
|
270
|
+
this.value = '';
|
|
271
|
+
update();
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
function onMouseDown(event) {
|
|
276
|
+
var hit = path.hitTest(event.point, {
|
|
277
|
+
segments: true,
|
|
278
|
+
handles: true,
|
|
279
|
+
fill: true,
|
|
280
|
+
stroke: true,
|
|
281
|
+
tolerance: 6
|
|
282
|
+
});
|
|
283
|
+
drag = hit && {
|
|
284
|
+
type: hit.type,
|
|
285
|
+
segment: hit.segment
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function onMouseDrag(event) {
|
|
290
|
+
if (drag) {
|
|
291
|
+
var name = {
|
|
292
|
+
'segment': 'point',
|
|
293
|
+
'handle-in': 'handleIn',
|
|
294
|
+
'handle-out': 'handleOut'
|
|
295
|
+
}[drag.type];
|
|
296
|
+
if (name) {
|
|
297
|
+
drag.segment[name] += event.delta;
|
|
298
|
+
} else {
|
|
299
|
+
path.position += event.delta;
|
|
300
|
+
}
|
|
301
|
+
update(false);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function onMouseUp() {
|
|
306
|
+
drag = null;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function bind(id, key, convert) {
|
|
310
|
+
var input = document.getElementById(id);
|
|
311
|
+
input.addEventListener('input', function() {
|
|
312
|
+
settings[key] = convert ? convert(input) : input.value;
|
|
313
|
+
if (key === 'preset') {
|
|
314
|
+
createPreset(settings.preset);
|
|
315
|
+
} else {
|
|
316
|
+
view.update(true);
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
bind('preset', 'preset');
|
|
322
|
+
bind('show-bounds', 'showBounds', function(input) {
|
|
323
|
+
return input.checked;
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
createPreset(settings.preset);
|
|
327
|
+
path.addEffect({
|
|
328
|
+
type: 'offset',
|
|
329
|
+
parameters: { distance: 20, join: 'round' }
|
|
330
|
+
});
|
|
331
|
+
update();
|
|
332
|
+
</script>
|
|
333
|
+
</head>
|
|
334
|
+
<body>
|
|
335
|
+
<canvas id="canvas" resize></canvas>
|
|
336
|
+
<div class="panel">
|
|
337
|
+
<h1>Live Effects</h1>
|
|
338
|
+
<label>Path
|
|
339
|
+
<select id="preset">
|
|
340
|
+
<option>Star</option>
|
|
341
|
+
<option>Wave</option>
|
|
342
|
+
<option>Pressure</option>
|
|
343
|
+
<option>Blob</option>
|
|
344
|
+
</select>
|
|
345
|
+
</label>
|
|
346
|
+
<label>Preview bounds <input id="show-bounds" type="checkbox" checked></label>
|
|
347
|
+
<label>Add effect
|
|
348
|
+
<select id="add">
|
|
349
|
+
<option value="">…</option>
|
|
350
|
+
<option value="offset">Offset</option>
|
|
351
|
+
<option value="outline">Outline stroke</option>
|
|
352
|
+
</select>
|
|
353
|
+
</label>
|
|
354
|
+
<div id="effects"></div>
|
|
355
|
+
<div class="info">
|
|
356
|
+
<p id="info"></p>
|
|
357
|
+
<p>The path keeps its own geometry and style, and its effects
|
|
358
|
+
derive what is drawn from it, in order, each from the one before.
|
|
359
|
+
Drag its points and handles, or the path itself, to edit it: the
|
|
360
|
+
effects follow. The dashed rectangle is its
|
|
361
|
+
<code>previewBounds</code>, while hit testing, <code>bounds</code>
|
|
362
|
+
and <code>strokeBounds</code> stay with the path.</p>
|
|
363
|
+
</div>
|
|
364
|
+
</div>
|
|
365
|
+
</body>
|
|
366
|
+
</html>
|