manga-renderer 1.0.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/LICENSE +17 -0
- package/README.md +118 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +184 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/book/book.d.ts +133 -0
- package/dist/lib/book/book.js +329 -0
- package/dist/lib/book/book.js.map +1 -0
- package/dist/lib/book/envelope.d.ts +26 -0
- package/dist/lib/book/envelope.js +158 -0
- package/dist/lib/book/envelope.js.map +1 -0
- package/dist/lib/book/imagePacking.d.ts +10 -0
- package/dist/lib/book/imagePacking.js +213 -0
- package/dist/lib/book/imagePacking.js.map +1 -0
- package/dist/lib/book/layout.d.ts +41 -0
- package/dist/lib/book/layout.js +14 -0
- package/dist/lib/book/layout.js.map +1 -0
- package/dist/lib/book/notebook.d.ts +72 -0
- package/dist/lib/book/notebook.js +30 -0
- package/dist/lib/book/notebook.js.map +1 -0
- package/dist/lib/book/richChat.d.ts +36 -0
- package/dist/lib/book/richChat.js +87 -0
- package/dist/lib/book/richChat.js.map +1 -0
- package/dist/lib/book/storyboard.d.ts +125 -0
- package/dist/lib/book/storyboard.js +44 -0
- package/dist/lib/book/storyboard.js.map +1 -0
- package/dist/lib/layeredCanvas/dataModels/bubble.d.ts +96 -0
- package/dist/lib/layeredCanvas/dataModels/bubble.js +630 -0
- package/dist/lib/layeredCanvas/dataModels/bubble.js.map +1 -0
- package/dist/lib/layeredCanvas/dataModels/effect.d.ts +25 -0
- package/dist/lib/layeredCanvas/dataModels/effect.js +104 -0
- package/dist/lib/layeredCanvas/dataModels/effect.js.map +1 -0
- package/dist/lib/layeredCanvas/dataModels/film.d.ts +44 -0
- package/dist/lib/layeredCanvas/dataModels/film.js +172 -0
- package/dist/lib/layeredCanvas/dataModels/film.js.map +1 -0
- package/dist/lib/layeredCanvas/dataModels/frameTree.d.ts +99 -0
- package/dist/lib/layeredCanvas/dataModels/frameTree.js +861 -0
- package/dist/lib/layeredCanvas/dataModels/frameTree.js.map +1 -0
- package/dist/lib/layeredCanvas/dataModels/media.d.ts +39 -0
- package/dist/lib/layeredCanvas/dataModels/media.js +69 -0
- package/dist/lib/layeredCanvas/dataModels/media.js.map +1 -0
- package/dist/lib/layeredCanvas/layers/SampleLayer.d.ts +6 -0
- package/dist/lib/layeredCanvas/layers/SampleLayer.js +22 -0
- package/dist/lib/layeredCanvas/layers/SampleLayer.js.map +1 -0
- package/dist/lib/layeredCanvas/layers/arrayLayer.d.ts +49 -0
- package/dist/lib/layeredCanvas/layers/arrayLayer.js +364 -0
- package/dist/lib/layeredCanvas/layers/arrayLayer.js.map +1 -0
- package/dist/lib/layeredCanvas/layers/bubbleLayer.d.ts +97 -0
- package/dist/lib/layeredCanvas/layers/bubbleLayer.js +1418 -0
- package/dist/lib/layeredCanvas/layers/bubbleLayer.js.map +1 -0
- package/dist/lib/layeredCanvas/layers/floorLayer.d.ts +13 -0
- package/dist/lib/layeredCanvas/layers/floorLayer.js +64 -0
- package/dist/lib/layeredCanvas/layers/floorLayer.js.map +1 -0
- package/dist/lib/layeredCanvas/layers/frameLayer.d.ts +106 -0
- package/dist/lib/layeredCanvas/layers/frameLayer.js +1283 -0
- package/dist/lib/layeredCanvas/layers/frameLayer.js.map +1 -0
- package/dist/lib/layeredCanvas/layers/inlinePainterLayer.d.ts +33 -0
- package/dist/lib/layeredCanvas/layers/inlinePainterLayer.js +222 -0
- package/dist/lib/layeredCanvas/layers/inlinePainterLayer.js.map +1 -0
- package/dist/lib/layeredCanvas/layers/paperRendererLayer.d.ts +64 -0
- package/dist/lib/layeredCanvas/layers/paperRendererLayer.js +443 -0
- package/dist/lib/layeredCanvas/layers/paperRendererLayer.js.map +1 -0
- package/dist/lib/layeredCanvas/layers/undoLayer.d.ts +8 -0
- package/dist/lib/layeredCanvas/layers/undoLayer.js +24 -0
- package/dist/lib/layeredCanvas/layers/undoLayer.js.map +1 -0
- package/dist/lib/layeredCanvas/system/keyCache.d.ts +4 -0
- package/dist/lib/layeredCanvas/system/keyCache.js +61 -0
- package/dist/lib/layeredCanvas/system/keyCache.js.map +1 -0
- package/dist/lib/layeredCanvas/system/layeredCanvas.d.ts +172 -0
- package/dist/lib/layeredCanvas/system/layeredCanvas.js +597 -0
- package/dist/lib/layeredCanvas/system/layeredCanvas.js.map +1 -0
- package/dist/lib/layeredCanvas/system/paperArray.d.ts +29 -0
- package/dist/lib/layeredCanvas/system/paperArray.js +108 -0
- package/dist/lib/layeredCanvas/system/paperArray.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/draw/bubbleGraphic.d.ts +7 -0
- package/dist/lib/layeredCanvas/tools/draw/bubbleGraphic.js +728 -0
- package/dist/lib/layeredCanvas/tools/draw/bubbleGraphic.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/draw/clickableIcon.d.ts +42 -0
- package/dist/lib/layeredCanvas/tools/draw/clickableIcon.js +129 -0
- package/dist/lib/layeredCanvas/tools/draw/clickableIcon.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/draw/drawFilmStack.d.ts +4 -0
- package/dist/lib/layeredCanvas/tools/draw/drawFilmStack.js +53 -0
- package/dist/lib/layeredCanvas/tools/draw/drawFilmStack.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/draw/drawText.d.ts +8 -0
- package/dist/lib/layeredCanvas/tools/draw/drawText.js +45 -0
- package/dist/lib/layeredCanvas/tools/draw/drawText.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/draw/richText.d.ts +15 -0
- package/dist/lib/layeredCanvas/tools/draw/richText.js +172 -0
- package/dist/lib/layeredCanvas/tools/draw/richText.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/draw/selectionFrame.d.ts +5 -0
- package/dist/lib/layeredCanvas/tools/draw/selectionFrame.js +63 -0
- package/dist/lib/layeredCanvas/tools/draw/selectionFrame.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/draw/typeSetting.d.ts +16 -0
- package/dist/lib/layeredCanvas/tools/draw/typeSetting.js +2 -0
- package/dist/lib/layeredCanvas/tools/draw/typeSetting.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/draw/verticalText.d.ts +3 -0
- package/dist/lib/layeredCanvas/tools/draw/verticalText.js +230 -0
- package/dist/lib/layeredCanvas/tools/draw/verticalText.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/focusKeeper.d.ts +8 -0
- package/dist/lib/layeredCanvas/tools/focusKeeper.js +15 -0
- package/dist/lib/layeredCanvas/tools/focusKeeper.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/frameExamples.d.ts +382 -0
- package/dist/lib/layeredCanvas/tools/frameExamples.js +758 -0
- package/dist/lib/layeredCanvas/tools/frameExamples.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/geometry/bubbleGeometry.d.ts +12 -0
- package/dist/lib/layeredCanvas/tools/geometry/bubbleGeometry.js +117 -0
- package/dist/lib/layeredCanvas/tools/geometry/bubbleGeometry.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/geometry/convertPoint.d.ts +2 -0
- package/dist/lib/layeredCanvas/tools/geometry/convertPoint.js +25 -0
- package/dist/lib/layeredCanvas/tools/geometry/convertPoint.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/geometry/geometry.d.ts +69 -0
- package/dist/lib/layeredCanvas/tools/geometry/geometry.js +408 -0
- package/dist/lib/layeredCanvas/tools/geometry/geometry.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/geometry/geometry.vitest.d.ts +1 -0
- package/dist/lib/layeredCanvas/tools/geometry/geometry.vitest.js +58 -0
- package/dist/lib/layeredCanvas/tools/geometry/geometry.vitest.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/geometry/quickHull.d.ts +10 -0
- package/dist/lib/layeredCanvas/tools/geometry/quickHull.js +91 -0
- package/dist/lib/layeredCanvas/tools/geometry/quickHull.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/geometry/trapezoid.d.ts +18 -0
- package/dist/lib/layeredCanvas/tools/geometry/trapezoid.js +105 -0
- package/dist/lib/layeredCanvas/tools/geometry/trapezoid.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/grid.d.ts +7 -0
- package/dist/lib/layeredCanvas/tools/grid.js +16 -0
- package/dist/lib/layeredCanvas/tools/grid.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/haiku.d.ts +1 -0
- package/dist/lib/layeredCanvas/tools/haiku.js +17 -0
- package/dist/lib/layeredCanvas/tools/haiku.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/imageUtil.d.ts +8 -0
- package/dist/lib/layeredCanvas/tools/imageUtil.js +58 -0
- package/dist/lib/layeredCanvas/tools/imageUtil.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/kinsoku.d.ts +26 -0
- package/dist/lib/layeredCanvas/tools/kinsoku.js +124 -0
- package/dist/lib/layeredCanvas/tools/kinsoku.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/misc.d.ts +25 -0
- package/dist/lib/layeredCanvas/tools/misc.js +46 -0
- package/dist/lib/layeredCanvas/tools/misc.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/perfectFreehandUtil.d.ts +2 -0
- package/dist/lib/layeredCanvas/tools/perfectFreehandUtil.js +21 -0
- package/dist/lib/layeredCanvas/tools/perfectFreehandUtil.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/pictureControl.d.ts +4 -0
- package/dist/lib/layeredCanvas/tools/pictureControl.js +24 -0
- package/dist/lib/layeredCanvas/tools/pictureControl.js.map +1 -0
- package/dist/lib/layeredCanvas/tools/rectHandle.d.ts +6 -0
- package/dist/lib/layeredCanvas/tools/rectHandle.js +17 -0
- package/dist/lib/layeredCanvas/tools/rectHandle.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,728 @@
|
|
|
1
|
+
import seedrandom from "seedrandom";
|
|
2
|
+
import { QuickHull } from "../geometry/quickHull";
|
|
3
|
+
import paper from 'paper';
|
|
4
|
+
import { tailCoordToWorldCoord, jitterDistances } from "../geometry/bubbleGeometry";
|
|
5
|
+
import { color2string, generateRandomAngles, generateSuperEllipsePoints, subdividePointsWithBump } from "../geometry/bubbleGeometry";
|
|
6
|
+
import { clamp, magnitude2D, perpendicular2D, normalize2D, rotate2D, projectionScalingFactor2D } from "../geometry/geometry";
|
|
7
|
+
import { PaperOffset } from 'paperjs-offset';
|
|
8
|
+
import rough from 'roughjs';
|
|
9
|
+
import rgba from 'color-rgba';
|
|
10
|
+
export function initPaperJs() {
|
|
11
|
+
// https://github.com/paperjs/paper.js/issues/1889
|
|
12
|
+
paper.setup([1, 1]); // creates a virtual canvas
|
|
13
|
+
paper.view.autoUpdate = false; // disables drawing any shape automatically
|
|
14
|
+
}
|
|
15
|
+
export function getBubbleName(shape) {
|
|
16
|
+
switch (shape) {
|
|
17
|
+
case "rounded": return "角丸";
|
|
18
|
+
case "square": return "四角形";
|
|
19
|
+
case "ellipse": return "楕円";
|
|
20
|
+
case "concentration": return "意識";
|
|
21
|
+
case "polygon": return "多角形";
|
|
22
|
+
case "strokes": return "線";
|
|
23
|
+
case "double-strokes": return "二重線";
|
|
24
|
+
case "harsh": return "トゲトゲ";
|
|
25
|
+
case "shout": return "シャウト";
|
|
26
|
+
case "soft": return "やわらか";
|
|
27
|
+
case "heart": return "ハート";
|
|
28
|
+
case "diamond": return "ダイヤ";
|
|
29
|
+
case "arrow": return "矢印";
|
|
30
|
+
case "motion-lines": return "集中線";
|
|
31
|
+
case "speed-lines": return "流線";
|
|
32
|
+
case "ellipse-mind": return "楕円?";
|
|
33
|
+
case "soft-mind": return "やわらか?";
|
|
34
|
+
case "rounded-mind": return "角丸?";
|
|
35
|
+
case "none": return "なし";
|
|
36
|
+
default:
|
|
37
|
+
throw new Error(`Unknown bubble : ${shape}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function drawBubble(context, method, seed, size, shape, opts) {
|
|
41
|
+
seed = opts.randomSeed ?? 0;
|
|
42
|
+
switch (shape) {
|
|
43
|
+
case "rounded":
|
|
44
|
+
drawRoundedBubble(context, method, seed, size, opts);
|
|
45
|
+
break;
|
|
46
|
+
case "square":
|
|
47
|
+
drawSquareBubble(context, method, seed, size, opts);
|
|
48
|
+
break;
|
|
49
|
+
case "ellipse":
|
|
50
|
+
drawEllipseBubble(context, method, seed, size, opts);
|
|
51
|
+
break;
|
|
52
|
+
case "concentration":
|
|
53
|
+
drawConcentrationBubble(context, method, seed, size, opts);
|
|
54
|
+
break;
|
|
55
|
+
case "polygon":
|
|
56
|
+
drawPolygonBubble(context, method, seed, size, opts);
|
|
57
|
+
break;
|
|
58
|
+
case "strokes":
|
|
59
|
+
drawStrokesBubble(context, method, seed, size, opts);
|
|
60
|
+
break;
|
|
61
|
+
case "double-strokes":
|
|
62
|
+
drawDoubleStrokesBubble(context, method, seed, size, opts);
|
|
63
|
+
break;
|
|
64
|
+
case "harsh":
|
|
65
|
+
drawHarshBubble(context, method, seed, size, opts);
|
|
66
|
+
break;
|
|
67
|
+
case "shout":
|
|
68
|
+
drawShoutBubble(context, method, seed, size, opts);
|
|
69
|
+
break;
|
|
70
|
+
case "soft":
|
|
71
|
+
drawSoftBubble(context, method, seed, size, opts);
|
|
72
|
+
break;
|
|
73
|
+
case "heart":
|
|
74
|
+
drawHeartBubble(context, method, seed, size, opts);
|
|
75
|
+
break;
|
|
76
|
+
case "diamond":
|
|
77
|
+
drawDiamondBubble(context, method, seed, size, opts);
|
|
78
|
+
break;
|
|
79
|
+
case "arrow":
|
|
80
|
+
drawArrowBubble(context, method, seed, size, opts);
|
|
81
|
+
break;
|
|
82
|
+
case "motion-lines":
|
|
83
|
+
drawMotionLinesBubble(context, method, seed, size, opts);
|
|
84
|
+
break;
|
|
85
|
+
case "speed-lines":
|
|
86
|
+
drawSpeedLinesBubble(context, method, seed, size, opts);
|
|
87
|
+
break;
|
|
88
|
+
case "ellipse-mind":
|
|
89
|
+
drawEllipseMindBubble(context, method, seed, size, opts);
|
|
90
|
+
break;
|
|
91
|
+
case "soft-mind":
|
|
92
|
+
drawSoftMindBubble(context, method, seed, size, opts);
|
|
93
|
+
break;
|
|
94
|
+
case "rounded-mind":
|
|
95
|
+
drawRoundedMindBubble(context, method, seed, size, opts);
|
|
96
|
+
break;
|
|
97
|
+
case "none":
|
|
98
|
+
break;
|
|
99
|
+
default:
|
|
100
|
+
throw new Error(`Unknown bubble : ${shape}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function drawConcentrationBubble(context, method, seed, size, opts) {
|
|
104
|
+
const [w, h] = size;
|
|
105
|
+
if (method === "fill") {
|
|
106
|
+
context.save();
|
|
107
|
+
context.translate(0, 0);
|
|
108
|
+
context.scale(w / 2, h / 2);
|
|
109
|
+
context.lineWidth = 1 / Math.min(w, h);
|
|
110
|
+
// draw n radial line
|
|
111
|
+
const n = opts.lineCount;
|
|
112
|
+
context.save();
|
|
113
|
+
const gradient = context.createRadialGradient(0, 0, 1, 0, 0, opts.lineLength);
|
|
114
|
+
const color = context.strokeStyle;
|
|
115
|
+
const color0 = rgba(color); // わざとstrokeStyleを使う
|
|
116
|
+
const color1 = rgba(color);
|
|
117
|
+
color0[3] = 0;
|
|
118
|
+
gradient.addColorStop(0.0, color2string(color1));
|
|
119
|
+
gradient.addColorStop(1.0, color2string(color0));
|
|
120
|
+
context.strokeStyle = gradient;
|
|
121
|
+
context.beginPath();
|
|
122
|
+
for (let i = 0; i < n; i++) {
|
|
123
|
+
const angle = (i * 2 * Math.PI) / n;
|
|
124
|
+
const [dx, dy] = [Math.cos(angle), Math.sin(angle)];
|
|
125
|
+
const [lx, ly] = [dx * opts.lineLength, dy * opts.lineLength];
|
|
126
|
+
context.moveTo(dx, dy);
|
|
127
|
+
context.lineTo(lx, ly);
|
|
128
|
+
}
|
|
129
|
+
context.closePath();
|
|
130
|
+
context.stroke();
|
|
131
|
+
context.restore();
|
|
132
|
+
context.beginPath();
|
|
133
|
+
context.ellipse(0, 0, 1, 1, 0, 0, 2 * Math.PI);
|
|
134
|
+
context.fill();
|
|
135
|
+
context.restore();
|
|
136
|
+
}
|
|
137
|
+
else if (method === "clip") {
|
|
138
|
+
context.beginPath();
|
|
139
|
+
context.ellipse(0, 0, w * 0.5, h * 0.5, 0, 0, 2 * Math.PI);
|
|
140
|
+
context.clip();
|
|
141
|
+
}
|
|
142
|
+
else { // stroke
|
|
143
|
+
// do nothing;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function drawStrokesBubble(context, method, seed, size, opts) {
|
|
147
|
+
drawStrokesBubbleAux(context, method, seed, size, opts, false);
|
|
148
|
+
}
|
|
149
|
+
function drawDoubleStrokesBubble(context, method, seed, size, opts) {
|
|
150
|
+
drawStrokesBubbleAux(context, method, seed, size, opts, true);
|
|
151
|
+
}
|
|
152
|
+
function drawStrokesBubbleAux(context, method, seed, size, opts, double) {
|
|
153
|
+
const rng = seedrandom(seed);
|
|
154
|
+
const rawPoints = generateSuperEllipsePoints(size, generateRandomAngles(rng, opts.vertexCount, opts.angleJitter), opts.superEllipse);
|
|
155
|
+
const points = QuickHull(rawPoints);
|
|
156
|
+
if (method == "fill" || method == "clip") {
|
|
157
|
+
const path = new paper.Path();
|
|
158
|
+
for (let i = 0; i < points.length; i++) {
|
|
159
|
+
const p = points[i];
|
|
160
|
+
if (i === 0) {
|
|
161
|
+
path.moveTo(p);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
path.lineTo(p);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
path.closed = true;
|
|
168
|
+
drawPath(context, method, path, opts);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
const color = context.strokeStyle;
|
|
172
|
+
for (let i = 0; i < points.length; i++) {
|
|
173
|
+
context.beginPath();
|
|
174
|
+
const p0 = points[i];
|
|
175
|
+
const p1 = points[(i + 1) % points.length];
|
|
176
|
+
const [q0, q1] = extendLineSegment(p0, p1, opts.overRun);
|
|
177
|
+
const gradient = context.createLinearGradient(...q0, ...q1);
|
|
178
|
+
const color0 = rgba(color); // わざとstrokeStyleを使う
|
|
179
|
+
const color1 = rgba(color);
|
|
180
|
+
color0[3] = 0;
|
|
181
|
+
gradient.addColorStop(0, color2string(color0));
|
|
182
|
+
gradient.addColorStop(0.15, color2string(color1));
|
|
183
|
+
gradient.addColorStop(0.85, color2string(color1));
|
|
184
|
+
gradient.addColorStop(1, color2string(color0));
|
|
185
|
+
context.strokeStyle = gradient;
|
|
186
|
+
context.moveTo(q0[0], q0[1]);
|
|
187
|
+
context.lineTo(q1[0], q1[1]);
|
|
188
|
+
if (double) {
|
|
189
|
+
const dist = Math.min(size[0], size[1]) * opts.interval;
|
|
190
|
+
const [dx, dy] = [p1[0] - p0[0], p1[1] - p0[1]];
|
|
191
|
+
const [nx, ny] = [-dy, dx];
|
|
192
|
+
const [mx, my] = [
|
|
193
|
+
nx / Math.sqrt(nx * nx + ny * ny),
|
|
194
|
+
ny / Math.sqrt(nx * nx + ny * ny),
|
|
195
|
+
];
|
|
196
|
+
const [qx, qy] = [q0[0] + mx * dist, q0[1] + my * dist];
|
|
197
|
+
const [rx, ry] = [q1[0] + mx * dist, q1[1] + my * dist];
|
|
198
|
+
context.moveTo(qx, qy);
|
|
199
|
+
context.lineTo(rx, ry);
|
|
200
|
+
}
|
|
201
|
+
context.stroke();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function drawMotionLinesBubble(context, method, seed, size, opts) {
|
|
206
|
+
const [x, y, w, h] = sizeToRect(size);
|
|
207
|
+
if (method === "fill") {
|
|
208
|
+
const rng = seedrandom(seed);
|
|
209
|
+
context.save();
|
|
210
|
+
context.beginPath();
|
|
211
|
+
context.rect(x, y, w, h);
|
|
212
|
+
context.clip();
|
|
213
|
+
context.lineWidth = 1;
|
|
214
|
+
// draw n parallel line
|
|
215
|
+
const n = opts.lineCount;
|
|
216
|
+
const icd = opts?.focalPoint ?? [0, 0];
|
|
217
|
+
const rangeVector = opts?.focalRange ?? [0, Math.hypot(w / 2, h / 2) * 0.25];
|
|
218
|
+
const range = Math.hypot(rangeVector[0], rangeVector[1]);
|
|
219
|
+
const [ox, oy, od] = [0, 0, Math.hypot(w / 2, h / 2)]; // 外円
|
|
220
|
+
const [ix, iy, id] = [icd[0], icd[1], range]; // 内円
|
|
221
|
+
// グラデーション
|
|
222
|
+
const gradient = context.createRadialGradient(ix, iy, id, ox, oy, od);
|
|
223
|
+
const color0 = rgba(context.strokeStyle); // わざとstrokeStyleを使う
|
|
224
|
+
const color1 = rgba(context.strokeStyle);
|
|
225
|
+
color0[3] = 0;
|
|
226
|
+
gradient.addColorStop(0.0, color2string(color0));
|
|
227
|
+
gradient.addColorStop(0.2, color2string(color1));
|
|
228
|
+
gradient.addColorStop(1.0, color2string(color1));
|
|
229
|
+
context.fillStyle = gradient;
|
|
230
|
+
// 線を描く
|
|
231
|
+
for (let i = 0; i < n; i++) {
|
|
232
|
+
const angle = (i * 2 * Math.PI) / n + (rng() - 0.5) * opts.angleJitter;
|
|
233
|
+
const [dx, dy] = [Math.cos(angle), Math.sin(angle)];
|
|
234
|
+
const sdr = id * (1 + rng() * opts.startJitter);
|
|
235
|
+
//const sdr = id + rng() * 40;
|
|
236
|
+
const p0 = [ix, iy];
|
|
237
|
+
const p1 = [ox + dx * od, oy + dy * od];
|
|
238
|
+
const v = [p1[0] - p0[0], p1[1] - p0[1]];
|
|
239
|
+
const length = Math.hypot(...v);
|
|
240
|
+
const p2 = [p0[0] + v[0] * sdr / length, p0[1] + v[1] * sdr / length];
|
|
241
|
+
const lw = opts.lineWidth * 0.1;
|
|
242
|
+
const [q0, q1] = [perpendicular2D(v, lw), perpendicular2D(v, -lw)];
|
|
243
|
+
context.beginPath();
|
|
244
|
+
context.moveTo(p2[0], p2[1]);
|
|
245
|
+
context.lineTo(p1[0] + q0[0], p1[1] + q0[1]);
|
|
246
|
+
context.lineTo(p1[0] + q1[0], p1[1] + q1[1]);
|
|
247
|
+
context.closePath();
|
|
248
|
+
context.fill();
|
|
249
|
+
}
|
|
250
|
+
context.restore();
|
|
251
|
+
}
|
|
252
|
+
else { // stroke, clip
|
|
253
|
+
// do nothing;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function drawSpeedLinesBubble(context, method, seed, size, opts) {
|
|
257
|
+
const [x, y, w, h] = sizeToRect(size);
|
|
258
|
+
if (method === "fill") {
|
|
259
|
+
const rng = seedrandom(seed);
|
|
260
|
+
context.save();
|
|
261
|
+
context.beginPath();
|
|
262
|
+
context.rect(x, y, w, h);
|
|
263
|
+
context.clip();
|
|
264
|
+
const tailTip = opts?.tailTip ?? [0, 0];
|
|
265
|
+
const tailMid = tailCoordToWorldCoord([0, 0], tailTip, opts?.tailMid ?? [0, 0]);
|
|
266
|
+
const length = Math.hypot(w, h);
|
|
267
|
+
const angle = Math.atan2(tailTip[1], tailTip[0]);
|
|
268
|
+
context.rotate(angle);
|
|
269
|
+
function calculateNormalizedPosition([fx, fy]) {
|
|
270
|
+
const v0 = [length * 0.5, 0];
|
|
271
|
+
const [nx, ny] = rotate2D(v0, angle);
|
|
272
|
+
const psf = 0.5 - projectionScalingFactor2D([fx, fy], [nx, ny]) * 0.5;
|
|
273
|
+
return clamp(psf);
|
|
274
|
+
}
|
|
275
|
+
context.lineWidth = 1;
|
|
276
|
+
const n = opts.lineCount;
|
|
277
|
+
const psf0 = clamp(0.5 - magnitude2D(tailTip) / length);
|
|
278
|
+
const psf1 = calculateNormalizedPosition(tailMid);
|
|
279
|
+
// 線を描く
|
|
280
|
+
for (let i = 0; i < n; i++) {
|
|
281
|
+
const y = (i + 0.5) / n * length - length / 2 + rng() * length * opts.laneJitter;
|
|
282
|
+
const lx = -length * 0.5 + (rng() - 0.5) * w * opts.startJitter;
|
|
283
|
+
const lw = h * opts.lineWidth * 0.01 * (rng() + 0.5);
|
|
284
|
+
// グラデーション
|
|
285
|
+
const gradient = context.createLinearGradient(lx + length, y, lx, y);
|
|
286
|
+
const color0 = rgba(context.strokeStyle); // わざとstrokeStyleを使う
|
|
287
|
+
const color1 = rgba(context.strokeStyle);
|
|
288
|
+
color0[3] = 0;
|
|
289
|
+
gradient.addColorStop(psf0, color2string(color0));
|
|
290
|
+
gradient.addColorStop(psf1, color2string(color1));
|
|
291
|
+
gradient.addColorStop(1.0, color2string(color1));
|
|
292
|
+
context.fillStyle = gradient;
|
|
293
|
+
context.beginPath();
|
|
294
|
+
context.moveTo(lx, y - lw);
|
|
295
|
+
context.lineTo(lx + length, y);
|
|
296
|
+
context.lineTo(lx, y + lw);
|
|
297
|
+
context.closePath();
|
|
298
|
+
context.fill();
|
|
299
|
+
}
|
|
300
|
+
context.restore();
|
|
301
|
+
}
|
|
302
|
+
else { // stroke, clip
|
|
303
|
+
// do nothing;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function extendLineSegment(p0, p1, extensionFactor) {
|
|
307
|
+
const [dx, dy] = [p1[0] - p0[0], p1[1] - p0[1]];
|
|
308
|
+
const q0 = [p1[0] - dx * extensionFactor, p1[1] - dy * extensionFactor];
|
|
309
|
+
const q1 = [p0[0] + dx * extensionFactor, p0[1] + dy * extensionFactor];
|
|
310
|
+
return [q0, q1];
|
|
311
|
+
}
|
|
312
|
+
function finishTrivialPath(context, method) {
|
|
313
|
+
switch (method) {
|
|
314
|
+
case 'fill':
|
|
315
|
+
context.fill();
|
|
316
|
+
break;
|
|
317
|
+
case 'stroke':
|
|
318
|
+
context.stroke();
|
|
319
|
+
break;
|
|
320
|
+
case 'clip':
|
|
321
|
+
context.clip();
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
export function getPath(shape, size, opts, seed) {
|
|
326
|
+
seed = opts.randomSeed ?? 0;
|
|
327
|
+
const startTime = performance.now();
|
|
328
|
+
try {
|
|
329
|
+
switch (shape) {
|
|
330
|
+
case 'square':
|
|
331
|
+
return getSquarePath(size, opts, seed);
|
|
332
|
+
case 'ellipse':
|
|
333
|
+
return getEllipsePath(size, opts, seed);
|
|
334
|
+
case 'polygon':
|
|
335
|
+
return getPolygonPath(size, opts, seed);
|
|
336
|
+
case 'rounded':
|
|
337
|
+
return getRoundedPath(size, opts, seed);
|
|
338
|
+
case 'harsh':
|
|
339
|
+
return getHarshPath(size, opts, seed);
|
|
340
|
+
case 'shout':
|
|
341
|
+
return getShoutPath(size, opts, seed);
|
|
342
|
+
case 'soft':
|
|
343
|
+
return getSoftPath(size, opts, seed);
|
|
344
|
+
case 'heart':
|
|
345
|
+
return getHeartPath(size, opts, seed);
|
|
346
|
+
case 'diamond':
|
|
347
|
+
return getDiamondPath(size, opts, seed);
|
|
348
|
+
case 'arrow':
|
|
349
|
+
return getArrowPath(size, opts, seed);
|
|
350
|
+
case 'ellipse-mind':
|
|
351
|
+
return getEllipseMindPath(size, opts, seed);
|
|
352
|
+
case 'soft-mind':
|
|
353
|
+
return getSoftMindPath(size, opts, seed);
|
|
354
|
+
case 'rounded-mind':
|
|
355
|
+
return getRoundedMindPath(size, opts, seed);
|
|
356
|
+
}
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
finally {
|
|
360
|
+
// console.log(`getPath(${shape}, ${r}, ${opts}) took ${performance.now() - startTime} ms`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
function sizeToRect(size) {
|
|
364
|
+
return [-size[0] * 0.5, -size[1] * 0.5, size[0], size[1]];
|
|
365
|
+
}
|
|
366
|
+
function halfSize(size) {
|
|
367
|
+
return [size[0] * 0.5, size[1] * 0.5];
|
|
368
|
+
}
|
|
369
|
+
function getSquarePath(size, opts, seed) {
|
|
370
|
+
const path = new paper.Path.Rectangle(sizeToRect(size));
|
|
371
|
+
return addTrivialTail(path, size, opts);
|
|
372
|
+
}
|
|
373
|
+
function getEllipsePath(size, opts, seed) {
|
|
374
|
+
const path = new paper.Path.Ellipse({ center: [0, 0], radius: halfSize(size) });
|
|
375
|
+
return addTrivialTail(path, size, opts);
|
|
376
|
+
}
|
|
377
|
+
function getRoundedPath(size, opts, seed) {
|
|
378
|
+
const [x0, y0, w, h] = sizeToRect(size);
|
|
379
|
+
const [x1, y1] = [0, 0];
|
|
380
|
+
const [x2, y2] = [x0 + w, y0 + h];
|
|
381
|
+
const [sx, sy] = [opts.xStraight * w * 0.5, opts.yStraight * h * 0.5];
|
|
382
|
+
const path = new paper.Path();
|
|
383
|
+
path.moveTo([x1 + sx, y0]);
|
|
384
|
+
path.lineTo([x1 - sx, y0]);
|
|
385
|
+
path.quadraticCurveTo([x0, y0], [x0, y1 - sy]);
|
|
386
|
+
path.lineTo([x0, y1 + sy]);
|
|
387
|
+
path.quadraticCurveTo([x0, y2], [x1 - sx, y2]);
|
|
388
|
+
path.lineTo([x1 + sx, y2]);
|
|
389
|
+
path.quadraticCurveTo([x2, y2], [x2, y1 + sy]);
|
|
390
|
+
path.lineTo([x2, y1 - sy]);
|
|
391
|
+
path.quadraticCurveTo([x2, y0], [x1 + sx, y0]);
|
|
392
|
+
path.closed = true;
|
|
393
|
+
return addTrivialTail(path, size, opts);
|
|
394
|
+
}
|
|
395
|
+
function getHarshPath(size, opts, seed) {
|
|
396
|
+
const rng = seedrandom(seed);
|
|
397
|
+
let angles = generateRandomAngles(rng, opts.bumpCount, opts.angleJitter);
|
|
398
|
+
const rawPoints = generateSuperEllipsePoints(size, angles, opts.superEllipse);
|
|
399
|
+
let points = subdividePointsWithBump(size, rawPoints, opts.bumpDepth);
|
|
400
|
+
const path = new paper.Path();
|
|
401
|
+
path.addSegments(points);
|
|
402
|
+
path.closed = true;
|
|
403
|
+
return addTrivialTail(path, size, opts);
|
|
404
|
+
}
|
|
405
|
+
function getShoutPath(size, opts, seed) {
|
|
406
|
+
const bump = opts.bumpSharp;
|
|
407
|
+
const rng = seedrandom(seed);
|
|
408
|
+
let points;
|
|
409
|
+
const angles = generateRandomAngles(rng, opts.bumpCount, opts.angleJitter);
|
|
410
|
+
points = generateSuperEllipsePoints(size, angles, opts.superEllipse);
|
|
411
|
+
points = subdividePointsWithBump(size, points, bump);
|
|
412
|
+
points = jitterDistances(rng, points, bump, opts.depthJitter);
|
|
413
|
+
const path = new paper.Path();
|
|
414
|
+
path.moveTo(points[0]);
|
|
415
|
+
for (let i = 0; i < points.length; i += 2) {
|
|
416
|
+
const p0 = points[i];
|
|
417
|
+
const p1 = points[i + 1];
|
|
418
|
+
const p2 = points[(i + 2) % points.length];
|
|
419
|
+
path.quadraticCurveTo(p1, p2);
|
|
420
|
+
}
|
|
421
|
+
path.closed = true;
|
|
422
|
+
return addTrivialTail(path, size, opts);
|
|
423
|
+
}
|
|
424
|
+
function getSoftPath(size, opts, seed) {
|
|
425
|
+
const rng = seedrandom(seed);
|
|
426
|
+
const rawPoints = generateSuperEllipsePoints(size, generateRandomAngles(rng, opts.bumpCount, opts.angleJitter), opts.superEllipse);
|
|
427
|
+
const points = subdividePointsWithBump(size, rawPoints, -opts.bumpDepth);
|
|
428
|
+
const path = new paper.Path();
|
|
429
|
+
if (opts.smoothing) {
|
|
430
|
+
for (let i = 0; i < points.length + 1; i++) {
|
|
431
|
+
const p0 = points[i % points.length];
|
|
432
|
+
const p1 = points[(i + 1) % points.length];
|
|
433
|
+
let cp = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
|
|
434
|
+
if (i == 0) {
|
|
435
|
+
path.moveTo(cp);
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
path.quadraticCurveTo(p0, cp);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
path.moveTo(points[0]);
|
|
444
|
+
for (let i = 0; i < points.length; i += 2) {
|
|
445
|
+
const p1 = points[i + 1];
|
|
446
|
+
const p2 = points[(i + 2) % points.length];
|
|
447
|
+
path.quadraticCurveTo(p1, p2);
|
|
448
|
+
}
|
|
449
|
+
path.closed = true;
|
|
450
|
+
}
|
|
451
|
+
return addTrivialTail(path, size, opts);
|
|
452
|
+
}
|
|
453
|
+
function getHeartPath(size, opts, seed) {
|
|
454
|
+
const [w, h] = size;
|
|
455
|
+
const [x, y] = [0, 0];
|
|
456
|
+
const h1 = h * -0.58;
|
|
457
|
+
const h2 = h * -0.35;
|
|
458
|
+
const h3 = h * -0.1;
|
|
459
|
+
const h4 = h * 0.1;
|
|
460
|
+
const h5 = h * 0.35;
|
|
461
|
+
const h6 = h * 0.5;
|
|
462
|
+
const path = new paper.Path();
|
|
463
|
+
path.moveTo([x, y + h2]);
|
|
464
|
+
path.cubicCurveTo([-0.1 * w, h1], [-0.5 * w, h1], [-0.5 * w, h3]);
|
|
465
|
+
path.cubicCurveTo([-0.5 * w, h4], [-0.3 * w, h5], [0, h6]);
|
|
466
|
+
path.cubicCurveTo([0.3 * w, h5], [0.5 * w, h4], [0.5 * w, h3]);
|
|
467
|
+
path.cubicCurveTo([0.5 * w, h1], [0.1 * w, h1], [0, h2]);
|
|
468
|
+
path.closed = true;
|
|
469
|
+
return path;
|
|
470
|
+
}
|
|
471
|
+
function getDiamondPath(size, opts, seed) {
|
|
472
|
+
const [x0, y0, w, h] = sizeToRect(size);
|
|
473
|
+
const path = new paper.Path();
|
|
474
|
+
path.moveTo([0, y0]);
|
|
475
|
+
path.lineTo([x0, 0]);
|
|
476
|
+
path.lineTo([0, y0 + h]);
|
|
477
|
+
path.lineTo([x0 + w, 0]);
|
|
478
|
+
path.closed = true;
|
|
479
|
+
return path;
|
|
480
|
+
}
|
|
481
|
+
function getArrowPath(size, opts, seed) {
|
|
482
|
+
const [x0, y0, w, h] = sizeToRect(size);
|
|
483
|
+
const { shaftWidth, headLength } = opts;
|
|
484
|
+
const actualHalfShaftWidth = shaftWidth * w * 0.5;
|
|
485
|
+
const path = new paper.Path();
|
|
486
|
+
const y1 = y0 + h * headLength;
|
|
487
|
+
const x1 = x0 + w * 0.5 - actualHalfShaftWidth;
|
|
488
|
+
const x2 = x0 + w * 0.5 + actualHalfShaftWidth;
|
|
489
|
+
path.moveTo([0, y0]);
|
|
490
|
+
path.lineTo([x0, y1]);
|
|
491
|
+
path.lineTo([x1, y1]);
|
|
492
|
+
path.lineTo([x1, y0 + h]);
|
|
493
|
+
path.lineTo([x2, y0 + h]);
|
|
494
|
+
path.lineTo([x2, y1]);
|
|
495
|
+
path.lineTo([x0 + w, y1]);
|
|
496
|
+
path.lineTo([0, y0]);
|
|
497
|
+
path.closed = true;
|
|
498
|
+
return path;
|
|
499
|
+
}
|
|
500
|
+
function getEllipseMindPath(size, opts, seed) {
|
|
501
|
+
const newOpts = { ...opts };
|
|
502
|
+
newOpts.tailTip = [0, 0];
|
|
503
|
+
newOpts.tailMid = [0.5, 0];
|
|
504
|
+
const path = getEllipsePath(size, newOpts, seed);
|
|
505
|
+
const path2 = addMind(path, seed, size, opts, newOpts);
|
|
506
|
+
return path2;
|
|
507
|
+
}
|
|
508
|
+
function getSoftMindPath(size, opts, seed) {
|
|
509
|
+
const newOpts = { ...opts };
|
|
510
|
+
newOpts.tailTip = [0, 0];
|
|
511
|
+
newOpts.tailMid = [0.5, 0];
|
|
512
|
+
const path = getSoftPath(size, newOpts, seed);
|
|
513
|
+
const path2 = addMind(path, seed, size, opts, newOpts);
|
|
514
|
+
return path2;
|
|
515
|
+
}
|
|
516
|
+
function getRoundedMindPath(size, opts, seed) {
|
|
517
|
+
const newOpts = { ...opts };
|
|
518
|
+
newOpts.tailTip = [0, 0];
|
|
519
|
+
newOpts.tailMid = [0.5, 0];
|
|
520
|
+
const path = getRoundedPath(size, newOpts, seed);
|
|
521
|
+
const path2 = addMind(path, seed, size, opts, newOpts);
|
|
522
|
+
return path2;
|
|
523
|
+
}
|
|
524
|
+
function getCloudPath(size, opts, seed, vertexCount, superEllipseN, bumpFactor) {
|
|
525
|
+
const rng = seedrandom(seed);
|
|
526
|
+
const rawPoints = generateSuperEllipsePoints(size, generateRandomAngles(rng, vertexCount), superEllipseN);
|
|
527
|
+
const points = subdividePointsWithBump(size, rawPoints, -bumpFactor);
|
|
528
|
+
const path = new paper.Path();
|
|
529
|
+
path.moveTo(points[0]);
|
|
530
|
+
for (let i = 0; i < points.length; i += 2) {
|
|
531
|
+
const p0 = points[i];
|
|
532
|
+
const p1 = points[i + 1];
|
|
533
|
+
const p2 = points[(i + 2) % points.length];
|
|
534
|
+
path.quadraticCurveTo(p1, p2);
|
|
535
|
+
}
|
|
536
|
+
path.closed = true;
|
|
537
|
+
//return path;
|
|
538
|
+
return addTrivialTail(path, size, opts);
|
|
539
|
+
}
|
|
540
|
+
function addTrivialTail(path, size, opts) {
|
|
541
|
+
if (opts?.tailTip) {
|
|
542
|
+
const v = opts.tailTip;
|
|
543
|
+
const m = opts.tailMid;
|
|
544
|
+
if (v[0] === 0 && v[1] === 0) {
|
|
545
|
+
// do nothing
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
if (!opts?.extract) {
|
|
549
|
+
return path.unite(makeTrivialTailPath(size, m, v, opts.tailWidth));
|
|
550
|
+
}
|
|
551
|
+
else {
|
|
552
|
+
return path.subtract(makeExtractTailPath(size, m, v, opts.extractWidth));
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
return path;
|
|
557
|
+
}
|
|
558
|
+
function makeTrivialTailPath(size, m, v, tailWidth) {
|
|
559
|
+
if (m == null || (m[0] == 0 && m[1] == 0)) {
|
|
560
|
+
m = [0.5, 0];
|
|
561
|
+
}
|
|
562
|
+
const a = size[0] * size[1] * tailWidth;
|
|
563
|
+
const l = Math.max(50000, Math.hypot(v[0], v[1]) ** 2);
|
|
564
|
+
const vd1 = normalize2D(perpendicular2D(v), a * 35 / l);
|
|
565
|
+
const vd2 = normalize2D(perpendicular2D(v, -1), a * 35 / l);
|
|
566
|
+
const vt1 = [v[0] - vd1[0], v[1] - vd1[1]];
|
|
567
|
+
const vt2 = [v[0] - vd2[0], v[1] - vd2[1]];
|
|
568
|
+
const v0 = v;
|
|
569
|
+
const v1 = vd1;
|
|
570
|
+
const v2 = vd2;
|
|
571
|
+
const m1 = tailCoordToWorldCoord(v1, vt1, m);
|
|
572
|
+
const m2 = tailCoordToWorldCoord(v2, vt2, m);
|
|
573
|
+
const tail = new paper.Path();
|
|
574
|
+
tail.moveTo(v1);
|
|
575
|
+
tail.curveTo(m1, v0);
|
|
576
|
+
tail.curveTo(m2, v2);
|
|
577
|
+
tail.closed = true;
|
|
578
|
+
return tail;
|
|
579
|
+
}
|
|
580
|
+
function makeExtractTailPath(size, m, p, w) {
|
|
581
|
+
if (m == null || (m[0] == 0 && m[1] == 0)) {
|
|
582
|
+
m = [0.5, 0];
|
|
583
|
+
}
|
|
584
|
+
const q = tailCoordToWorldCoord([0, 0], p, m);
|
|
585
|
+
const v = [p[0] - q[0], p[1] - q[1]];
|
|
586
|
+
const l = Math.hypot(p[0], p[1]);
|
|
587
|
+
const vd = normalize2D(perpendicular2D(v), l * w);
|
|
588
|
+
const vt1 = [p[0] + vd[0], p[1] + vd[1]];
|
|
589
|
+
const vt2 = [p[0] - vd[0], p[1] - vd[1]];
|
|
590
|
+
const tail = new paper.Path();
|
|
591
|
+
tail.moveTo(q);
|
|
592
|
+
tail.lineTo(vt1);
|
|
593
|
+
tail.lineTo(vt2);
|
|
594
|
+
tail.closed = true;
|
|
595
|
+
return tail;
|
|
596
|
+
}
|
|
597
|
+
function getPolygonPath(size, opts, seed) {
|
|
598
|
+
const rng = seedrandom(seed);
|
|
599
|
+
const angles = generateRandomAngles(rng, opts.vertexCount, opts.angleJitter);
|
|
600
|
+
const rawPoints = generateSuperEllipsePoints(size, angles, opts.superEllipse);
|
|
601
|
+
const points = QuickHull(rawPoints); // 型定義不足でコンパイルエラーが出るのでworkaround
|
|
602
|
+
const path = new paper.Path();
|
|
603
|
+
path.addSegments(points);
|
|
604
|
+
path.closed = true;
|
|
605
|
+
return addTrivialTail(path, size, opts);
|
|
606
|
+
}
|
|
607
|
+
function drawEllipseBubble(context, method, seed, size, opts) {
|
|
608
|
+
const path = getEllipsePath(size, opts, seed);
|
|
609
|
+
drawPath(context, method, path, opts);
|
|
610
|
+
}
|
|
611
|
+
function drawSquareBubble(context, method, seed, size, opts) {
|
|
612
|
+
const path = getSquarePath(size, opts, seed);
|
|
613
|
+
drawPath(context, method, path, opts);
|
|
614
|
+
}
|
|
615
|
+
function drawPolygonBubble(context, method, seed, size, opts) {
|
|
616
|
+
const path = getPolygonPath(size, opts, seed);
|
|
617
|
+
drawPath(context, method, path, opts);
|
|
618
|
+
}
|
|
619
|
+
function drawRoundedBubble(context, method, seed, size, opts) {
|
|
620
|
+
const path = getRoundedPath(size, opts, seed);
|
|
621
|
+
drawPath(context, method, path, opts);
|
|
622
|
+
}
|
|
623
|
+
function drawHarshBubble(context, method, seed, size, opts) {
|
|
624
|
+
const path = getHarshPath(size, opts, seed);
|
|
625
|
+
drawPath(context, method, path, opts);
|
|
626
|
+
}
|
|
627
|
+
function drawShoutBubble(context, method, seed, size, opts) {
|
|
628
|
+
const path = getShoutPath(size, opts, seed);
|
|
629
|
+
drawPath(context, method, path, opts);
|
|
630
|
+
}
|
|
631
|
+
function drawSoftBubble(context, method, seed, size, opts) {
|
|
632
|
+
const path = getSoftPath(size, opts, seed);
|
|
633
|
+
drawPath(context, method, path, opts);
|
|
634
|
+
}
|
|
635
|
+
function drawHeartBubble(context, method, seed, size, opts) {
|
|
636
|
+
const path = getHeartPath(size, opts, seed);
|
|
637
|
+
drawPath(context, method, path, opts);
|
|
638
|
+
}
|
|
639
|
+
function drawDiamondBubble(context, method, seed, size, opts) {
|
|
640
|
+
const path = getDiamondPath(size, opts, seed);
|
|
641
|
+
drawPath(context, method, path, opts);
|
|
642
|
+
}
|
|
643
|
+
function drawArrowBubble(context, method, seed, size, opts) {
|
|
644
|
+
const path = getArrowPath(size, opts, seed);
|
|
645
|
+
drawPath(context, method, path, opts);
|
|
646
|
+
}
|
|
647
|
+
function drawEllipseMindBubble(context, method, seed, size, opts) {
|
|
648
|
+
const path = getEllipseMindPath(size, opts, seed);
|
|
649
|
+
drawPath(context, method, path, opts);
|
|
650
|
+
}
|
|
651
|
+
function drawSoftMindBubble(context, method, seed, size, opts) {
|
|
652
|
+
const path = getSoftMindPath(size, opts, seed);
|
|
653
|
+
drawPath(context, method, path, opts);
|
|
654
|
+
}
|
|
655
|
+
function drawRoundedMindBubble(context, method, seed, size, opts) {
|
|
656
|
+
const path = getRoundedMindPath(size, opts, seed);
|
|
657
|
+
drawPath(context, method, path, opts);
|
|
658
|
+
}
|
|
659
|
+
export function drawPath(context, method, unified, opts) {
|
|
660
|
+
context.beginPath();
|
|
661
|
+
switch (method) {
|
|
662
|
+
case 'fill':
|
|
663
|
+
if (opts?.shapeExpand && 0 < opts?.shapeExpand) {
|
|
664
|
+
let expansion = Math.min(unified.bounds.width, unified.bounds.height) * opts.shapeExpand;
|
|
665
|
+
let path = PaperOffset.offset(unified, expansion);
|
|
666
|
+
context.fill(new Path2D(path.pathData));
|
|
667
|
+
}
|
|
668
|
+
else {
|
|
669
|
+
context.fill(new Path2D(unified.pathData));
|
|
670
|
+
}
|
|
671
|
+
break;
|
|
672
|
+
case 'stroke':
|
|
673
|
+
const roughness = opts.roughness ?? 0;
|
|
674
|
+
if (0 < roughness) {
|
|
675
|
+
const seed = (opts.randomSeed ?? 0) + 1;
|
|
676
|
+
const rc = rough.canvas(context.canvas, { options: { seed, roughness, strokeWidth: context.lineWidth, stroke: context.strokeStyle } });
|
|
677
|
+
rc.path(unified.pathData);
|
|
678
|
+
}
|
|
679
|
+
else {
|
|
680
|
+
context.stroke(new Path2D(unified.pathData));
|
|
681
|
+
}
|
|
682
|
+
break;
|
|
683
|
+
case 'clip':
|
|
684
|
+
context.clip(new Path2D(unified.pathData));
|
|
685
|
+
break;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
/*
|
|
689
|
+
function pathToPoints(path, segments = 200) {
|
|
690
|
+
let points = [];
|
|
691
|
+
const length = path.length;
|
|
692
|
+
for (let i = 0; i <= segments; i++) {
|
|
693
|
+
let point = path.getPointAt(i / segments * length);
|
|
694
|
+
points.push(point);
|
|
695
|
+
}
|
|
696
|
+
return points;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
function drawPoints(context, points, color) {
|
|
700
|
+
context.save();
|
|
701
|
+
context.strokeStyle = color;
|
|
702
|
+
context.beginPath();
|
|
703
|
+
for (let i = 0; i < points.length; i++) {
|
|
704
|
+
const p = points[i];
|
|
705
|
+
// draw circle
|
|
706
|
+
context.moveTo(p[0], p[1]);
|
|
707
|
+
context.arc(p[0], p[1], 2, 0, 2 * Math.PI);
|
|
708
|
+
}
|
|
709
|
+
context.stroke();
|
|
710
|
+
context.restore();
|
|
711
|
+
}
|
|
712
|
+
*/
|
|
713
|
+
function addMind(path, seed, size, opts, newOpts) {
|
|
714
|
+
const trail = [[0.97, 0.04], [0.8, 0.05], [0.6, 0.08], [0.3, 0.12]];
|
|
715
|
+
const m = tailCoordToWorldCoord([0, 0], opts.tailTip, opts.tailMid);
|
|
716
|
+
const s = opts.tailTip;
|
|
717
|
+
const v = [s[0] - m[0], s[1] - m[1]];
|
|
718
|
+
const r = Math.min(size[0], size[1]) * 0.5 * opts.tailWidth;
|
|
719
|
+
for (let t of trail) {
|
|
720
|
+
const p = [m[0] + t[0] * v[0], m[1] + t[0] * v[1]];
|
|
721
|
+
const rt = r * t[1] * 2;
|
|
722
|
+
const path2 = getCloudPath([rt, rt], newOpts, seed, 6, 2, 0.15);
|
|
723
|
+
path2.translate(p);
|
|
724
|
+
path = path.unite(path2);
|
|
725
|
+
}
|
|
726
|
+
return path;
|
|
727
|
+
}
|
|
728
|
+
//# sourceMappingURL=bubbleGraphic.js.map
|