@elixpo/lixsketch 4.5.8
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 +21 -0
- package/README.md +169 -0
- package/fonts/fonts.css +29 -0
- package/fonts/lixCode.ttf +0 -0
- package/fonts/lixDefault.ttf +0 -0
- package/fonts/lixDocs.ttf +0 -0
- package/fonts/lixFancy.ttf +0 -0
- package/fonts/lixFont.woff2 +0 -0
- package/package.json +49 -0
- package/src/SketchEngine.js +473 -0
- package/src/core/AIRenderer.js +1390 -0
- package/src/core/CopyPaste.js +655 -0
- package/src/core/EraserTrail.js +234 -0
- package/src/core/EventDispatcher.js +371 -0
- package/src/core/GraphEngine.js +150 -0
- package/src/core/GraphMathParser.js +231 -0
- package/src/core/GraphRenderer.js +255 -0
- package/src/core/LayerOrder.js +91 -0
- package/src/core/LixScriptParser.js +1299 -0
- package/src/core/MermaidFlowchartRenderer.js +475 -0
- package/src/core/MermaidSequenceParser.js +197 -0
- package/src/core/MermaidSequenceRenderer.js +479 -0
- package/src/core/ResizeCode.js +175 -0
- package/src/core/ResizeShapes.js +318 -0
- package/src/core/SceneSerializer.js +778 -0
- package/src/core/Selection.js +1861 -0
- package/src/core/SnapGuides.js +273 -0
- package/src/core/UndoRedo.js +1358 -0
- package/src/core/ZoomPan.js +258 -0
- package/src/core/ai-system-prompt.js +663 -0
- package/src/index.js +69 -0
- package/src/shapes/Arrow.js +1979 -0
- package/src/shapes/Circle.js +751 -0
- package/src/shapes/CodeShape.js +244 -0
- package/src/shapes/Frame.js +1460 -0
- package/src/shapes/FreehandStroke.js +724 -0
- package/src/shapes/IconShape.js +265 -0
- package/src/shapes/ImageShape.js +270 -0
- package/src/shapes/Line.js +738 -0
- package/src/shapes/Rectangle.js +794 -0
- package/src/shapes/TextShape.js +225 -0
- package/src/tools/arrowTool.js +581 -0
- package/src/tools/circleTool.js +619 -0
- package/src/tools/codeTool.js +2103 -0
- package/src/tools/eraserTool.js +131 -0
- package/src/tools/frameTool.js +241 -0
- package/src/tools/freehandTool.js +620 -0
- package/src/tools/iconTool.js +1344 -0
- package/src/tools/imageTool.js +1323 -0
- package/src/tools/laserTool.js +317 -0
- package/src/tools/lineTool.js +502 -0
- package/src/tools/rectangleTool.js +544 -0
- package/src/tools/textTool.js +1823 -0
- package/src/utils/imageCompressor.js +107 -0
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// Line tool event handlers - extracted from lineTool.js
|
|
3
|
+
import { pushCreateAction, pushDeleteAction, pushOptionsChangeAction, pushTransformAction, pushFrameAttachmentAction } from '../core/UndoRedo.js';
|
|
4
|
+
import { updateAttachedArrows as updateArrowsForShape, cleanupAttachments } from './arrowTool.js';
|
|
5
|
+
import { calculateSnap, clearSnapGuides } from '../core/SnapGuides.js';
|
|
6
|
+
|
|
7
|
+
let isDrawingLine = false;
|
|
8
|
+
let currentLine = null;
|
|
9
|
+
let lineStartX = 0;
|
|
10
|
+
let lineStartY = 0;
|
|
11
|
+
let currentLineGroup = null;
|
|
12
|
+
let lineColor = "#fff";
|
|
13
|
+
let lineStrokeWidth = 3;
|
|
14
|
+
let lineStrokeStyle = "solid";
|
|
15
|
+
let lineEdgeType = 1;
|
|
16
|
+
let lineSktetchRate = 3;
|
|
17
|
+
|
|
18
|
+
let isDraggingLine = false;
|
|
19
|
+
let dragOldPosLine = null;
|
|
20
|
+
let copiedShapeData = null;
|
|
21
|
+
let draggedShapeInitialFrameLine = null;
|
|
22
|
+
let hoveredFrameLine = null;
|
|
23
|
+
|
|
24
|
+
let startX, startY;
|
|
25
|
+
|
|
26
|
+
let lineColorOptions = document.querySelectorAll(".lineColor > span");
|
|
27
|
+
let lineThicknessOptions = document.querySelectorAll(".lineThicknessSpan");
|
|
28
|
+
let lineOutlineOptions = document.querySelectorAll(".lineStyleSpan");
|
|
29
|
+
let lineSlopeOptions = document.querySelectorAll(".lineSlopeSpan");
|
|
30
|
+
let lineEdgeOptions = document.querySelectorAll(".lineEdgeSpan");
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
function getSVGCoordsFromMouse(e) {
|
|
34
|
+
const viewBox = svg.viewBox.baseVal;
|
|
35
|
+
const rect = svg.getBoundingClientRect();
|
|
36
|
+
const mouseX = e.clientX - rect.left;
|
|
37
|
+
const mouseY = e.clientY - rect.top;
|
|
38
|
+
const svgX = viewBox.x + (mouseX / rect.width) * viewBox.width;
|
|
39
|
+
const svgY = viewBox.y + (mouseY / rect.height) * viewBox.height;
|
|
40
|
+
return { x: svgX, y: svgY };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Add delete functionality
|
|
44
|
+
function deleteCurrentShape() {
|
|
45
|
+
if (currentShape && currentShape.shapeName === 'line') {
|
|
46
|
+
const idx = shapes.indexOf(currentShape);
|
|
47
|
+
if (idx !== -1) shapes.splice(idx, 1);
|
|
48
|
+
if (currentShape.group.parentNode) {
|
|
49
|
+
currentShape.group.parentNode.removeChild(currentShape.group);
|
|
50
|
+
}
|
|
51
|
+
pushDeleteAction(currentShape);
|
|
52
|
+
currentShape = null;
|
|
53
|
+
disableAllSideBars();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
document.addEventListener('keydown', (e) => {
|
|
58
|
+
if (e.key === 'Delete' && currentShape && currentShape.shapeName === 'line') {
|
|
59
|
+
deleteCurrentShape();
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const handleMouseDown = (e) => {
|
|
64
|
+
if (!isLineToolActive && !isSelectionToolActive) return;
|
|
65
|
+
|
|
66
|
+
const { x, y } = getSVGCoordsFromMouse(e);
|
|
67
|
+
|
|
68
|
+
if (isLineToolActive) {
|
|
69
|
+
isDrawingLine = true;
|
|
70
|
+
currentLine = new Line(
|
|
71
|
+
{ x, y },
|
|
72
|
+
{ x, y },
|
|
73
|
+
{
|
|
74
|
+
stroke: lineColor,
|
|
75
|
+
strokeWidth: lineStrokeWidth,
|
|
76
|
+
roughness: lineSktetchRate,
|
|
77
|
+
bowing: lineEdgeType,
|
|
78
|
+
strokeDasharray: lineStrokeStyle === "dashed" ? "5,5" : (lineStrokeStyle === "dotted" ? "2,12" : "")
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
currentLine.isBeingDrawn = true;
|
|
82
|
+
shapes.push(currentLine);
|
|
83
|
+
currentShape = currentLine;
|
|
84
|
+
} else if (isSelectionToolActive) {
|
|
85
|
+
let clickedOnShape = false;
|
|
86
|
+
|
|
87
|
+
// Check if clicking on current selected line
|
|
88
|
+
if (currentShape && currentShape.shapeName === 'line' && currentShape.isSelected) {
|
|
89
|
+
const anchorInfo = currentShape.isNearAnchor(x, y);
|
|
90
|
+
|
|
91
|
+
if (anchorInfo && anchorInfo.type === 'anchor') {
|
|
92
|
+
clickedOnShape = true;
|
|
93
|
+
// Start anchor drag
|
|
94
|
+
dragOldPosLine = {
|
|
95
|
+
startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },
|
|
96
|
+
endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },
|
|
97
|
+
controlPoint: currentShape.controlPoint ? { x: currentShape.controlPoint.x, y: currentShape.controlPoint.y } : null,
|
|
98
|
+
isCurved: currentShape.isCurved,
|
|
99
|
+
parentFrame: currentShape.parentFrame
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const anchorIndex = anchorInfo.index;
|
|
103
|
+
|
|
104
|
+
const onPointerMove = (event) => {
|
|
105
|
+
const { x: newX, y: newY } = getSVGCoordsFromMouse(event);
|
|
106
|
+
currentShape.updatePosition(anchorIndex, newX, newY);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const onPointerUp = () => {
|
|
110
|
+
if (dragOldPosLine) {
|
|
111
|
+
const newPos = {
|
|
112
|
+
startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },
|
|
113
|
+
endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },
|
|
114
|
+
controlPoint: currentShape.controlPoint ? { x: currentShape.controlPoint.x, y: currentShape.controlPoint.y } : null,
|
|
115
|
+
isCurved: currentShape.isCurved,
|
|
116
|
+
parentFrame: currentShape.parentFrame
|
|
117
|
+
};
|
|
118
|
+
pushTransformAction(currentShape, dragOldPosLine, newPos);
|
|
119
|
+
dragOldPosLine = null;
|
|
120
|
+
}
|
|
121
|
+
svg.removeEventListener('pointermove', onPointerMove);
|
|
122
|
+
svg.removeEventListener('pointerup', onPointerUp);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
svg.addEventListener('pointermove', onPointerMove);
|
|
126
|
+
svg.addEventListener('pointerup', onPointerUp);
|
|
127
|
+
|
|
128
|
+
// Prevent default to stop any other drag behavior
|
|
129
|
+
e.preventDefault();
|
|
130
|
+
e.stopPropagation();
|
|
131
|
+
|
|
132
|
+
} else if (currentShape.contains(x, y)) {
|
|
133
|
+
// Dragging the line itself (not anchors)
|
|
134
|
+
isDraggingLine = true;
|
|
135
|
+
dragOldPosLine = {
|
|
136
|
+
startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },
|
|
137
|
+
endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },
|
|
138
|
+
controlPoint: currentShape.controlPoint ? { x: currentShape.controlPoint.x, y: currentShape.controlPoint.y } : null,
|
|
139
|
+
isCurved: currentShape.isCurved,
|
|
140
|
+
parentFrame: currentShape.parentFrame
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// Store initial frame state
|
|
144
|
+
draggedShapeInitialFrameLine = currentShape.parentFrame || null;
|
|
145
|
+
|
|
146
|
+
// Temporarily remove from frame clipping if dragging
|
|
147
|
+
if (currentShape.parentFrame) {
|
|
148
|
+
currentShape.parentFrame.temporarilyRemoveFromFrame(currentShape);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
startX = x;
|
|
152
|
+
startY = y;
|
|
153
|
+
clickedOnShape = true;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// If not clicking on selected shape, check for other shapes
|
|
158
|
+
if (!clickedOnShape) {
|
|
159
|
+
let shapeToSelect = null;
|
|
160
|
+
for (let i = shapes.length - 1; i >= 0; i--) {
|
|
161
|
+
const shape = shapes[i];
|
|
162
|
+
if (shape instanceof Line && shape.contains(x, y)) {
|
|
163
|
+
shapeToSelect = shape;
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (currentShape && currentShape !== shapeToSelect) {
|
|
169
|
+
currentShape.removeSelection();
|
|
170
|
+
currentShape = null;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (shapeToSelect) {
|
|
174
|
+
currentShape = shapeToSelect;
|
|
175
|
+
currentShape.selectLine();
|
|
176
|
+
clickedOnShape = true;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (!clickedOnShape && currentShape) {
|
|
181
|
+
currentShape.removeSelection();
|
|
182
|
+
currentShape = null;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
// Update clone function to remove rotation property
|
|
187
|
+
function cloneLineData(line) {
|
|
188
|
+
return {
|
|
189
|
+
startPoint: { x: line.startPoint.x, y: line.startPoint.y },
|
|
190
|
+
endPoint: { x: line.endPoint.x, y: line.endPoint.y },
|
|
191
|
+
controlPoint: line.controlPoint ? { x: line.controlPoint.x, y: line.controlPoint.y } : null,
|
|
192
|
+
isCurved: line.isCurved || false,
|
|
193
|
+
parentFrame: line.parentFrame,
|
|
194
|
+
options: cloneOptions(line.options)
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const handleMouseMove = (e) => {
|
|
199
|
+
const { x, y } = getSVGCoordsFromMouse(e);
|
|
200
|
+
|
|
201
|
+
// Keep lastMousePos in screen coordinates for other functions
|
|
202
|
+
const svgRect = svg.getBoundingClientRect();
|
|
203
|
+
lastMousePos = {
|
|
204
|
+
x: e.clientX - svgRect.left,
|
|
205
|
+
y: e.clientY - svgRect.top
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
if (isDrawingLine && currentLine) {
|
|
209
|
+
let endX = x, endY = y;
|
|
210
|
+
if (e.shiftKey) {
|
|
211
|
+
const dx = x - currentLine.startPoint.x;
|
|
212
|
+
const dy = y - currentLine.startPoint.y;
|
|
213
|
+
const angle = Math.atan2(dy, dx);
|
|
214
|
+
const snapAngle = Math.round(angle / (Math.PI / 4)) * (Math.PI / 4);
|
|
215
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
216
|
+
endX = currentLine.startPoint.x + dist * Math.cos(snapAngle);
|
|
217
|
+
endY = currentLine.startPoint.y + dist * Math.sin(snapAngle);
|
|
218
|
+
}
|
|
219
|
+
currentLine.endPoint = { x: endX, y: endY };
|
|
220
|
+
currentLine.draw();
|
|
221
|
+
|
|
222
|
+
// Check for frame containment while drawing (but don't apply clipping yet)
|
|
223
|
+
shapes.forEach(frame => {
|
|
224
|
+
if (frame.shapeName === 'frame') {
|
|
225
|
+
if (frame.isShapeInFrame(currentLine)) {
|
|
226
|
+
frame.highlightFrame();
|
|
227
|
+
hoveredFrameLine = frame;
|
|
228
|
+
} else if (hoveredFrameLine === frame) {
|
|
229
|
+
frame.removeHighlight();
|
|
230
|
+
hoveredFrameLine = null;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
} else if (isDraggingLine && currentShape && currentShape.isSelected) {
|
|
235
|
+
const dx = x - startX;
|
|
236
|
+
const dy = y - startY;
|
|
237
|
+
currentShape.move(dx, dy);
|
|
238
|
+
startX = x;
|
|
239
|
+
startY = y;
|
|
240
|
+
|
|
241
|
+
// Snap guides
|
|
242
|
+
if (window.__sketchStoreApi && window.__sketchStoreApi.getState().snapToObjects) {
|
|
243
|
+
const snap = calculateSnap(currentShape, e.shiftKey, e.clientX, e.clientY);
|
|
244
|
+
if (snap.dx || snap.dy) {
|
|
245
|
+
currentShape.move(snap.dx, snap.dy);
|
|
246
|
+
}
|
|
247
|
+
} else {
|
|
248
|
+
clearSnapGuides();
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
const handleMouseUp = (e) => {
|
|
254
|
+
if (isDrawingLine) {
|
|
255
|
+
isDrawingLine = false;
|
|
256
|
+
|
|
257
|
+
// Check if line is too small
|
|
258
|
+
const dx = currentLine.endPoint.x - currentLine.startPoint.x;
|
|
259
|
+
const dy = currentLine.endPoint.y - currentLine.startPoint.y;
|
|
260
|
+
const lengthSq = dx * dx + dy * dy;
|
|
261
|
+
|
|
262
|
+
if (lengthSq < (5 / currentZoom) ** 2) {
|
|
263
|
+
shapes.pop();
|
|
264
|
+
if (currentLine.group.parentNode) {
|
|
265
|
+
currentLine.group.parentNode.removeChild(currentLine.group);
|
|
266
|
+
}
|
|
267
|
+
currentLine = null;
|
|
268
|
+
currentShape = null;
|
|
269
|
+
} else {
|
|
270
|
+
// Finalize: apply roughness now that drawing is done
|
|
271
|
+
currentLine.isBeingDrawn = false;
|
|
272
|
+
currentLine.draw();
|
|
273
|
+
|
|
274
|
+
// Push create action for undo/redo
|
|
275
|
+
pushCreateAction(currentLine);
|
|
276
|
+
|
|
277
|
+
// Check for frame containment and track attachment
|
|
278
|
+
const finalFrame = hoveredFrameLine;
|
|
279
|
+
if (finalFrame) {
|
|
280
|
+
finalFrame.addShapeToFrame(currentLine);
|
|
281
|
+
// Track the attachment for undo
|
|
282
|
+
pushFrameAttachmentAction(finalFrame, currentLine, 'attach', null);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Auto-select the drawn line and switch to selection tool
|
|
286
|
+
const drawnLine = currentLine;
|
|
287
|
+
if (window.__sketchStoreApi) window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });
|
|
288
|
+
currentShape = drawnLine;
|
|
289
|
+
drawnLine.selectLine();
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Clear frame highlighting
|
|
293
|
+
if (hoveredFrameLine) {
|
|
294
|
+
hoveredFrameLine.removeHighlight();
|
|
295
|
+
hoveredFrameLine = null;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
currentLine = null;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (isDraggingLine && dragOldPosLine && currentShape) {
|
|
302
|
+
const newPos = {
|
|
303
|
+
startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },
|
|
304
|
+
endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },
|
|
305
|
+
controlPoint: currentShape.controlPoint ? { x: currentShape.controlPoint.x, y: currentShape.controlPoint.y } : null,
|
|
306
|
+
parentFrame: currentShape.parentFrame
|
|
307
|
+
};
|
|
308
|
+
const oldPos = {
|
|
309
|
+
...dragOldPosLine,
|
|
310
|
+
parentFrame: draggedShapeInitialFrameLine
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const stateChanged = dragOldPosLine.startPoint.x !== newPos.startPoint.x ||
|
|
314
|
+
dragOldPosLine.startPoint.y !== newPos.startPoint.y ||
|
|
315
|
+
dragOldPosLine.endPoint.x !== newPos.endPoint.x ||
|
|
316
|
+
dragOldPosLine.endPoint.y !== newPos.endPoint.y;
|
|
317
|
+
|
|
318
|
+
const frameChanged = oldPos.parentFrame !== newPos.parentFrame;
|
|
319
|
+
|
|
320
|
+
if (stateChanged || frameChanged) {
|
|
321
|
+
pushTransformAction(currentShape, oldPos, newPos);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Handle frame containment changes after drag
|
|
325
|
+
if (isDraggingLine) {
|
|
326
|
+
const finalFrame = hoveredFrameLine;
|
|
327
|
+
|
|
328
|
+
// If shape moved to a different frame
|
|
329
|
+
if (draggedShapeInitialFrameLine !== finalFrame) {
|
|
330
|
+
// Remove from initial frame
|
|
331
|
+
if (draggedShapeInitialFrameLine) {
|
|
332
|
+
draggedShapeInitialFrameLine.removeShapeFromFrame(currentShape);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Add to new frame
|
|
336
|
+
if (finalFrame) {
|
|
337
|
+
finalFrame.addShapeToFrame(currentShape);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Track the frame change for undo
|
|
341
|
+
if (frameChanged) {
|
|
342
|
+
pushFrameAttachmentAction(finalFrame || draggedShapeInitialFrameLine, currentShape,
|
|
343
|
+
finalFrame ? 'attach' : 'detach', draggedShapeInitialFrameLine);
|
|
344
|
+
}
|
|
345
|
+
} else if (draggedShapeInitialFrameLine) {
|
|
346
|
+
// Shape stayed in same frame, restore clipping
|
|
347
|
+
draggedShapeInitialFrameLine.restoreToFrame(currentShape);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
dragOldPosLine = null;
|
|
352
|
+
draggedShapeInitialFrameLine = null;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Clear frame highlighting
|
|
356
|
+
if (hoveredFrameLine) {
|
|
357
|
+
hoveredFrameLine.removeHighlight();
|
|
358
|
+
hoveredFrameLine = null;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
clearSnapGuides();
|
|
362
|
+
isDraggingLine = false;
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
// --- Event Handlers ---
|
|
366
|
+
|
|
367
|
+
// --- Style Option Event Listeners ---
|
|
368
|
+
lineColorOptions.forEach((span) => {
|
|
369
|
+
span.addEventListener("click", (event) => {
|
|
370
|
+
event.stopPropagation();
|
|
371
|
+
lineColorOptions.forEach((el) => el.classList.remove("selected"));
|
|
372
|
+
span.classList.add("selected");
|
|
373
|
+
|
|
374
|
+
if (currentShape instanceof Line && currentShape.isSelected) {
|
|
375
|
+
const oldOptions = {...currentShape.options};
|
|
376
|
+
currentShape.options.stroke = span.getAttribute("data-id");
|
|
377
|
+
currentShape.draw();
|
|
378
|
+
pushOptionsChangeAction(currentShape, oldOptions);
|
|
379
|
+
} else {
|
|
380
|
+
lineColor = span.getAttribute("data-id");
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
lineThicknessOptions.forEach((span) => {
|
|
386
|
+
span.addEventListener("click", (event) => {
|
|
387
|
+
event.stopPropagation();
|
|
388
|
+
lineThicknessOptions.forEach((el) => el.classList.remove("selected"));
|
|
389
|
+
span.classList.add("selected");
|
|
390
|
+
|
|
391
|
+
if (currentShape instanceof Line && currentShape.isSelected) {
|
|
392
|
+
const oldOptions = {...currentShape.options};
|
|
393
|
+
currentShape.options.strokeWidth = parseInt(span.getAttribute("data-id"));
|
|
394
|
+
currentShape.draw();
|
|
395
|
+
pushOptionsChangeAction(currentShape, oldOptions);
|
|
396
|
+
} else {
|
|
397
|
+
lineStrokeWidth = parseInt(span.getAttribute("data-id"));
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
lineOutlineOptions.forEach((span) => {
|
|
403
|
+
span.addEventListener("click", (event) => {
|
|
404
|
+
event.stopPropagation();
|
|
405
|
+
lineOutlineOptions.forEach((el) => el.classList.remove("selected"));
|
|
406
|
+
span.classList.add("selected");
|
|
407
|
+
|
|
408
|
+
if (currentShape instanceof Line && currentShape.isSelected) {
|
|
409
|
+
const oldOptions = {...currentShape.options};
|
|
410
|
+
const style = span.getAttribute("data-id");
|
|
411
|
+
currentShape.options.strokeDasharray =
|
|
412
|
+
style === "dashed" ? "5,5" :
|
|
413
|
+
(style === "dotted" ? "2,12" : "");
|
|
414
|
+
currentShape.draw();
|
|
415
|
+
pushOptionsChangeAction(currentShape, oldOptions);
|
|
416
|
+
} else {
|
|
417
|
+
lineStrokeStyle = span.getAttribute("data-id");
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
lineSlopeOptions.forEach((span) => {
|
|
423
|
+
span.addEventListener("click", (event) => {
|
|
424
|
+
event.stopPropagation();
|
|
425
|
+
lineSlopeOptions.forEach((el) => el.classList.remove("selected"));
|
|
426
|
+
span.classList.add("selected");
|
|
427
|
+
|
|
428
|
+
if (currentShape instanceof Line && currentShape.isSelected) {
|
|
429
|
+
const oldOptions = {...currentShape.options};
|
|
430
|
+
currentShape.options.roughness = parseFloat(span.getAttribute("data-id"));
|
|
431
|
+
currentShape.draw();
|
|
432
|
+
pushOptionsChangeAction(currentShape, oldOptions);
|
|
433
|
+
} else {
|
|
434
|
+
lineSktetchRate = parseFloat(span.getAttribute("data-id"));
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
lineEdgeOptions.forEach((span) => {
|
|
440
|
+
span.addEventListener("click", (event) => {
|
|
441
|
+
event.stopPropagation();
|
|
442
|
+
lineEdgeOptions.forEach((el) => el.classList.remove("selected"));
|
|
443
|
+
span.classList.add("selected");
|
|
444
|
+
|
|
445
|
+
if (currentShape instanceof Line && currentShape.isSelected) {
|
|
446
|
+
const oldOptions = {...currentShape.options};
|
|
447
|
+
currentShape.options.bowing = parseFloat(span.getAttribute("data-id"));
|
|
448
|
+
currentShape.draw();
|
|
449
|
+
pushOptionsChangeAction(currentShape, oldOptions);
|
|
450
|
+
} else {
|
|
451
|
+
lineEdgeType = parseFloat(span.getAttribute("data-id"));
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
// Add copy/paste functionality
|
|
457
|
+
function cloneOptions(options) {
|
|
458
|
+
return JSON.parse(JSON.stringify(options));
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
window.Line = Line;
|
|
462
|
+
|
|
463
|
+
// Bridge line tool settings to React sidebar
|
|
464
|
+
window.lineToolSettings = {
|
|
465
|
+
get strokeColor() { return lineColor; },
|
|
466
|
+
set strokeColor(v) { lineColor = v; },
|
|
467
|
+
get strokeWidth() { return lineStrokeWidth; },
|
|
468
|
+
set strokeWidth(v) { lineStrokeWidth = v; },
|
|
469
|
+
get strokeStyle() { return lineStrokeStyle; },
|
|
470
|
+
set strokeStyle(v) { lineStrokeStyle = v; },
|
|
471
|
+
get sloppiness() { return lineSktetchRate; },
|
|
472
|
+
set sloppiness(v) { lineSktetchRate = v; },
|
|
473
|
+
get edge() { return lineEdgeType; },
|
|
474
|
+
set edge(v) { lineEdgeType = v; },
|
|
475
|
+
};
|
|
476
|
+
window.updateSelectedLineStyle = function(changes) {
|
|
477
|
+
if (currentShape instanceof Line && currentShape.isSelected) {
|
|
478
|
+
const oldOptions = {...currentShape.options};
|
|
479
|
+
if (changes.stroke !== undefined) { lineColor = changes.stroke; currentShape.options.stroke = changes.stroke; }
|
|
480
|
+
if (changes.strokeWidth !== undefined) { lineStrokeWidth = changes.strokeWidth; currentShape.options.strokeWidth = changes.strokeWidth; }
|
|
481
|
+
if (changes.strokeStyle !== undefined) {
|
|
482
|
+
lineStrokeStyle = changes.strokeStyle;
|
|
483
|
+
currentShape.options.strokeDasharray = changes.strokeStyle === "dashed" ? "5,5" : (changes.strokeStyle === "dotted" ? "2,12" : "");
|
|
484
|
+
}
|
|
485
|
+
if (changes.sloppiness !== undefined) { lineSktetchRate = changes.sloppiness; currentShape.options.roughness = changes.sloppiness; }
|
|
486
|
+
if (changes.edge !== undefined) { lineEdgeType = changes.edge; currentShape.options.bowing = changes.edge; }
|
|
487
|
+
currentShape.draw();
|
|
488
|
+
pushOptionsChangeAction(currentShape, oldOptions);
|
|
489
|
+
} else {
|
|
490
|
+
if (changes.stroke !== undefined) lineColor = changes.stroke;
|
|
491
|
+
if (changes.strokeWidth !== undefined) lineStrokeWidth = changes.strokeWidth;
|
|
492
|
+
if (changes.strokeStyle !== undefined) lineStrokeStyle = changes.strokeStyle;
|
|
493
|
+
if (changes.sloppiness !== undefined) lineSktetchRate = changes.sloppiness;
|
|
494
|
+
if (changes.edge !== undefined) lineEdgeType = changes.edge;
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
export {
|
|
499
|
+
handleMouseDown as handleMouseDownLine,
|
|
500
|
+
handleMouseMove as handleMouseMoveLine,
|
|
501
|
+
handleMouseUp as handleMouseUpLine,
|
|
502
|
+
};
|