@svgedit/svgcanvas 7.1.4
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/blur-event.js +156 -0
- package/clear.js +43 -0
- package/coords.js +298 -0
- package/copy-elem.js +45 -0
- package/dataStorage.js +28 -0
- package/dist/svgcanvas.js +515 -0
- package/dist/svgcanvas.js.map +1 -0
- package/draw.js +1064 -0
- package/elem-get-set.js +1077 -0
- package/event.js +1388 -0
- package/history.js +619 -0
- package/historyrecording.js +161 -0
- package/json.js +110 -0
- package/layer.js +228 -0
- package/math.js +221 -0
- package/namespaces.js +40 -0
- package/package.json +54 -0
- package/paint.js +88 -0
- package/paste-elem.js +127 -0
- package/path-actions.js +1237 -0
- package/path-method.js +1012 -0
- package/path.js +781 -0
- package/recalculate.js +794 -0
- package/rollup.config.js +40 -0
- package/sanitize.js +252 -0
- package/select.js +543 -0
- package/selected-elem.js +1297 -0
- package/selection.js +482 -0
- package/svg-exec.js +1289 -0
- package/svgcanvas.js +1347 -0
- package/svgroot.js +36 -0
- package/text-actions.js +530 -0
- package/touch.js +51 -0
- package/undo.js +279 -0
- package/utilities.js +1214 -0
package/svgcanvas.js
ADDED
|
@@ -0,0 +1,1347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Numerous tools for working with the editor's "canvas".
|
|
3
|
+
* @module svgcanvas
|
|
4
|
+
*
|
|
5
|
+
* @license MIT
|
|
6
|
+
*
|
|
7
|
+
* @copyright 2010 Alexis Deveria, 2010 Pavol Rusnak, 2010 Jeff Schiller, 2021 OptimistikSAS
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
import 'pathseg' // SVGPathSeg Polyfill (see https://github.com/progers/pathseg)
|
|
11
|
+
|
|
12
|
+
import Paint from './paint.js'
|
|
13
|
+
import * as pathModule from './path.js'
|
|
14
|
+
import * as history from './history.js'
|
|
15
|
+
import * as draw from './draw.js'
|
|
16
|
+
import { init as pasteInit, pasteElementsMethod } from './paste-elem.js'
|
|
17
|
+
import { init as touchInit } from './touch.js'
|
|
18
|
+
import { svgRootElement } from './svgroot.js'
|
|
19
|
+
import {
|
|
20
|
+
init as undoInit,
|
|
21
|
+
changeSelectedAttributeNoUndoMethod,
|
|
22
|
+
changeSelectedAttributeMethod
|
|
23
|
+
} from './undo.js'
|
|
24
|
+
import { init as selectionInit } from './selection.js'
|
|
25
|
+
import { init as textActionsInit, textActionsMethod } from './text-actions.js'
|
|
26
|
+
import { init as eventInit } from './event.js'
|
|
27
|
+
import {
|
|
28
|
+
init as jsonInit,
|
|
29
|
+
getJsonFromSvgElements,
|
|
30
|
+
addSVGElementsFromJson
|
|
31
|
+
} from './json.js'
|
|
32
|
+
import * as elemGetSet from './elem-get-set.js'
|
|
33
|
+
import { init as selectedElemInit } from './selected-elem.js'
|
|
34
|
+
import {
|
|
35
|
+
init as blurInit,
|
|
36
|
+
setBlurNoUndo,
|
|
37
|
+
setBlurOffsets,
|
|
38
|
+
setBlur
|
|
39
|
+
} from './blur-event.js'
|
|
40
|
+
import { sanitizeSvg } from './sanitize.js'
|
|
41
|
+
import { getReverseNS, NS } from './namespaces.js'
|
|
42
|
+
import {
|
|
43
|
+
assignAttributes,
|
|
44
|
+
cleanupElement,
|
|
45
|
+
getElement,
|
|
46
|
+
getUrlFromAttr,
|
|
47
|
+
findDefs,
|
|
48
|
+
getHref,
|
|
49
|
+
setHref,
|
|
50
|
+
getRefElem,
|
|
51
|
+
getRotationAngle,
|
|
52
|
+
getBBoxOfElementAsPath,
|
|
53
|
+
convertToPath,
|
|
54
|
+
encode64,
|
|
55
|
+
decode64,
|
|
56
|
+
getVisibleElements,
|
|
57
|
+
init as utilsInit,
|
|
58
|
+
getBBox as utilsGetBBox,
|
|
59
|
+
getStrokedBBoxDefaultVisible,
|
|
60
|
+
blankPageObjectURL,
|
|
61
|
+
$id,
|
|
62
|
+
$qa,
|
|
63
|
+
$qq,
|
|
64
|
+
$click,
|
|
65
|
+
getFeGaussianBlur,
|
|
66
|
+
stringToHTML,
|
|
67
|
+
insertChildAtIndex
|
|
68
|
+
} from './utilities.js'
|
|
69
|
+
import {
|
|
70
|
+
matrixMultiply,
|
|
71
|
+
hasMatrixTransform,
|
|
72
|
+
transformListToTransform
|
|
73
|
+
} from './math.js'
|
|
74
|
+
import { convertToNum, init as unitsInit, getTypeMap } from '../../src/common/units.js'
|
|
75
|
+
import { init as svgInit } from './svg-exec.js'
|
|
76
|
+
import { remapElement, init as coordsInit } from './coords.js'
|
|
77
|
+
import {
|
|
78
|
+
recalculateDimensions,
|
|
79
|
+
init as recalculateInit
|
|
80
|
+
} from './recalculate.js'
|
|
81
|
+
import { getSelectorManager, Selector, init as selectInit } from './select.js'
|
|
82
|
+
import { clearSvgContentElementInit, init as clearInit } from './clear.js'
|
|
83
|
+
import {
|
|
84
|
+
getClosest,
|
|
85
|
+
getParents,
|
|
86
|
+
mergeDeep
|
|
87
|
+
} from '../../src/common/util.js'
|
|
88
|
+
|
|
89
|
+
import dataStorage from './dataStorage.js'
|
|
90
|
+
|
|
91
|
+
const visElems =
|
|
92
|
+
'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'
|
|
93
|
+
const refAttrs = [
|
|
94
|
+
'clip-path',
|
|
95
|
+
'fill',
|
|
96
|
+
'filter',
|
|
97
|
+
'marker-end',
|
|
98
|
+
'marker-mid',
|
|
99
|
+
'marker-start',
|
|
100
|
+
'mask',
|
|
101
|
+
'stroke'
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
const THRESHOLD_DIST = 0.8
|
|
105
|
+
const STEP_COUNT = 10
|
|
106
|
+
const CLIPBOARD_ID = 'svgedit_clipboard'
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The main SvgCanvas class that manages all SVG-related functions.
|
|
110
|
+
* @memberof module:svgcanvas
|
|
111
|
+
*
|
|
112
|
+
*/
|
|
113
|
+
class SvgCanvas {
|
|
114
|
+
/**
|
|
115
|
+
* @param {HTMLElement} container - The container HTML element that should hold the SVG root element
|
|
116
|
+
* @param {module:SVGeditor.configObj.curConfig} config - An object that contains configuration data
|
|
117
|
+
*/
|
|
118
|
+
constructor (container, config) {
|
|
119
|
+
// imported function made available as methods
|
|
120
|
+
this.initializeSvgCanvasMethods()
|
|
121
|
+
const { pathActions } = pathModule
|
|
122
|
+
|
|
123
|
+
// initialize class variables
|
|
124
|
+
this.saveOptions = { round_digits: 2 } // Object with save options
|
|
125
|
+
this.importIds = {} // Object with IDs for imported files, to see if one was already added
|
|
126
|
+
this.extensions = {} // Object to contain all included extensions
|
|
127
|
+
this.removedElements = {} // Map of deleted reference elements
|
|
128
|
+
this.started = false // Boolean indicating whether or not a draw action has been this.started
|
|
129
|
+
this.startTransform = null // String with an element's initial transform attribute value
|
|
130
|
+
this.currentMode = 'select' // String indicating the current editor mode
|
|
131
|
+
this.currentResizeMode = 'none' // String with the current direction in which an element is being resized
|
|
132
|
+
this.justSelected = null // The DOM element that was just selected
|
|
133
|
+
this.rubberBox = null // DOM element for selection rectangle drawn by the user
|
|
134
|
+
this.curBBoxes = [] // Array of current BBoxes, used in getIntersectionList().
|
|
135
|
+
this.lastClickPoint = null // Canvas point for the most recent right click
|
|
136
|
+
this.events = {} // Object to contain editor event names and callback functions
|
|
137
|
+
this.rootSctm = null // Root Current Transformation Matrix in user units
|
|
138
|
+
this.drawnPath = null
|
|
139
|
+
this.freehand = {
|
|
140
|
+
// Mouse events
|
|
141
|
+
minx: null,
|
|
142
|
+
miny: null,
|
|
143
|
+
maxx: null,
|
|
144
|
+
maxy: null
|
|
145
|
+
}
|
|
146
|
+
this.dAttr = null
|
|
147
|
+
this.startX = null
|
|
148
|
+
this.startY = null
|
|
149
|
+
this.rStartX = null
|
|
150
|
+
this.rStartY = null
|
|
151
|
+
this.initBbox = {}
|
|
152
|
+
this.sumDistance = 0
|
|
153
|
+
this.controllPoint2 = { x: 0, y: 0 }
|
|
154
|
+
this.controllPoint1 = { x: 0, y: 0 }
|
|
155
|
+
this.start = { x: 0, y: 0 }
|
|
156
|
+
this.end = { x: 0, y: 0 }
|
|
157
|
+
this.bSpline = { x: 0, y: 0 }
|
|
158
|
+
this.nextPos = { x: 0, y: 0 }
|
|
159
|
+
this.idprefix = 'svg_' // Prefix string for element IDs
|
|
160
|
+
this.encodableImages = {}
|
|
161
|
+
|
|
162
|
+
this.curConfig = {
|
|
163
|
+
// Default configuration options
|
|
164
|
+
show_outside_canvas: true,
|
|
165
|
+
selectNew: true,
|
|
166
|
+
dimensions: [640, 480]
|
|
167
|
+
}
|
|
168
|
+
// Update config with new one if given
|
|
169
|
+
if (config) {
|
|
170
|
+
this.curConfig = SvgCanvas.mergeDeep(this.curConfig, config)
|
|
171
|
+
}
|
|
172
|
+
this.lastGoodImgUrl = `${this.curConfig.imgPath}/logo.svg` // String with image URL of last loadable image
|
|
173
|
+
const { dimensions } = this.curConfig // Array with width/height of canvas
|
|
174
|
+
|
|
175
|
+
// "document" element associated with the container (same as window.document using default svg-editor.js)
|
|
176
|
+
// NOTE: This is not actually a SVG document, but an HTML document.
|
|
177
|
+
this.svgdoc = window.document
|
|
178
|
+
this.container = container
|
|
179
|
+
// This is a container for the document being edited, not the document itself.
|
|
180
|
+
this.svgroot = svgRootElement(this.svgdoc, dimensions)
|
|
181
|
+
container.append(this.svgroot)
|
|
182
|
+
// The actual element that represents the final output SVG element.
|
|
183
|
+
this.svgContent = this.svgdoc.createElementNS(NS.SVG, 'svg')
|
|
184
|
+
touchInit(this)
|
|
185
|
+
clearInit(this)
|
|
186
|
+
this.clearSvgContentElement()
|
|
187
|
+
// Current `draw.Drawing` object.
|
|
188
|
+
this.current_drawing_ = new draw.Drawing(this.svgContent, this.idprefix)
|
|
189
|
+
// Float displaying the current zoom level (1 = 100%, .5 = 50%, etc.).
|
|
190
|
+
this.zoom = 1
|
|
191
|
+
|
|
192
|
+
// pointer to current group (for in-group editing)
|
|
193
|
+
this.currentGroup = null
|
|
194
|
+
|
|
195
|
+
// Object containing data for the currently selected styles
|
|
196
|
+
const allProperties = {
|
|
197
|
+
shape: {
|
|
198
|
+
fill:
|
|
199
|
+
(this.curConfig.initFill.color === 'none' ? '' : '#') +
|
|
200
|
+
this.curConfig.initFill.color,
|
|
201
|
+
fill_paint: null,
|
|
202
|
+
fill_opacity: this.curConfig.initFill.opacity,
|
|
203
|
+
stroke: '#' + this.curConfig.initStroke.color,
|
|
204
|
+
stroke_paint: null,
|
|
205
|
+
stroke_opacity: this.curConfig.initStroke.opacity,
|
|
206
|
+
stroke_width: this.curConfig.initStroke.width,
|
|
207
|
+
stroke_dasharray: 'none',
|
|
208
|
+
stroke_linejoin: 'miter',
|
|
209
|
+
stroke_linecap: 'butt',
|
|
210
|
+
opacity: this.curConfig.initOpacity
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
allProperties.text = SvgCanvas.mergeDeep({}, allProperties.shape)
|
|
214
|
+
allProperties.text = SvgCanvas.mergeDeep(allProperties.text, {
|
|
215
|
+
fill: '#000000',
|
|
216
|
+
stroke_width: this.curConfig.text?.stroke_width,
|
|
217
|
+
font_size: this.curConfig.text?.font_size,
|
|
218
|
+
font_family: this.curConfig.text?.font_family
|
|
219
|
+
})
|
|
220
|
+
this.curText = allProperties.text // Current text style properties
|
|
221
|
+
|
|
222
|
+
// Current shape style properties
|
|
223
|
+
this.curShape = allProperties.shape
|
|
224
|
+
this.curProperties = this.curShape // Current general properties
|
|
225
|
+
|
|
226
|
+
// Array with all the currently selected elements
|
|
227
|
+
// default size of 1 until it needs to grow bigger
|
|
228
|
+
this.selectedElements = []
|
|
229
|
+
|
|
230
|
+
jsonInit(this)
|
|
231
|
+
unitsInit(this)
|
|
232
|
+
utilsInit(this)
|
|
233
|
+
coordsInit(this)
|
|
234
|
+
recalculateInit(this)
|
|
235
|
+
selectInit(this)
|
|
236
|
+
undoInit(this)
|
|
237
|
+
selectionInit(this)
|
|
238
|
+
|
|
239
|
+
this.nsMap = getReverseNS()
|
|
240
|
+
this.selectorManager = getSelectorManager()
|
|
241
|
+
|
|
242
|
+
this.pathActions = pathActions
|
|
243
|
+
pathModule.init(this)
|
|
244
|
+
// Interface strings, usually for title elements
|
|
245
|
+
this.uiStrings = {}
|
|
246
|
+
|
|
247
|
+
// Animation element to change the opacity of any newly created element
|
|
248
|
+
this.opacAni = document.createElementNS(NS.SVG, 'animate')
|
|
249
|
+
this.opacAni.setAttribute('attributeName', 'opacity')
|
|
250
|
+
this.opacAni.setAttribute('begin', 'indefinite')
|
|
251
|
+
this.opacAni.setAttribute('dur', 1)
|
|
252
|
+
this.opacAni.setAttribute('fill', 'freeze')
|
|
253
|
+
this.svgroot.appendChild(this.opacAni)
|
|
254
|
+
|
|
255
|
+
eventInit(this)
|
|
256
|
+
textActionsInit(this)
|
|
257
|
+
svgInit(this)
|
|
258
|
+
draw.init(this)
|
|
259
|
+
elemGetSet.init(this)
|
|
260
|
+
|
|
261
|
+
// prevent links from being followed in the canvas
|
|
262
|
+
const handleLinkInCanvas = e => {
|
|
263
|
+
e.preventDefault()
|
|
264
|
+
return false
|
|
265
|
+
}
|
|
266
|
+
container.addEventListener('mousedown', this.mouseDownEvent)
|
|
267
|
+
container.addEventListener('mousemove', this.mouseMoveEvent)
|
|
268
|
+
$click(container, handleLinkInCanvas)
|
|
269
|
+
container.addEventListener('dblclick', this.dblClickEvent)
|
|
270
|
+
container.addEventListener('mouseup', this.mouseUpEvent)
|
|
271
|
+
container.addEventListener('mouseleave', this.mouseOutEvent)
|
|
272
|
+
container.addEventListener('mousewheel', this.DOMMouseScrollEvent)
|
|
273
|
+
container.addEventListener('DOMMouseScroll', this.DOMMouseScrollEvent)
|
|
274
|
+
|
|
275
|
+
// Alias function
|
|
276
|
+
this.linkControlPoints = pathActions.linkControlPoints
|
|
277
|
+
this.curCommand = null
|
|
278
|
+
this.filter = null
|
|
279
|
+
this.filterHidden = false
|
|
280
|
+
|
|
281
|
+
blurInit(this)
|
|
282
|
+
selectedElemInit(this)
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Transfers sessionStorage from one tab to another.
|
|
286
|
+
* @param {!Event} ev Storage event.
|
|
287
|
+
* @returns {void}
|
|
288
|
+
*/
|
|
289
|
+
const storageChange = ev => {
|
|
290
|
+
if (!ev.newValue) return // This is a call from removeItem.
|
|
291
|
+
if (ev.key === CLIPBOARD_ID + '_startup') {
|
|
292
|
+
// Another tab asked for our sessionStorage.
|
|
293
|
+
localStorage.removeItem(CLIPBOARD_ID + '_startup')
|
|
294
|
+
this.flashStorage()
|
|
295
|
+
} else if (ev.key === CLIPBOARD_ID) {
|
|
296
|
+
// Another tab sent data.
|
|
297
|
+
sessionStorage.setItem(CLIPBOARD_ID, ev.newValue)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Listen for changes to localStorage.
|
|
302
|
+
window.addEventListener('storage', storageChange, false)
|
|
303
|
+
// Ask other tabs for sessionStorage (this is ONLY to trigger event).
|
|
304
|
+
localStorage.setItem(CLIPBOARD_ID + '_startup', Math.random())
|
|
305
|
+
|
|
306
|
+
pasteInit(this)
|
|
307
|
+
|
|
308
|
+
this.contentW = this.getResolution().w
|
|
309
|
+
this.contentH = this.getResolution().h
|
|
310
|
+
this.clear()
|
|
311
|
+
} // End constructor
|
|
312
|
+
|
|
313
|
+
getSvgOption () {
|
|
314
|
+
return this.saveOptions
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
setSvgOption (key, value) {
|
|
318
|
+
this.saveOptions[key] = value
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
getSelectedElements () {
|
|
322
|
+
return this.selectedElements
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
setSelectedElements (key, value) {
|
|
326
|
+
this.selectedElements[key] = value
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
setEmptySelectedElements () {
|
|
330
|
+
this.selectedElements = []
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
getSvgRoot () {
|
|
334
|
+
return this.svgroot
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
getDOMDocument () {
|
|
338
|
+
return this.svgdoc
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
getDOMContainer () {
|
|
342
|
+
return this.container
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
getCurConfig () {
|
|
346
|
+
return this.curConfig
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
setIdPrefix (p) {
|
|
350
|
+
this.idprefix = p
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
getCurrentDrawing () {
|
|
354
|
+
return this.current_drawing_
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
getCurShape () {
|
|
358
|
+
return this.curShape
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
getCurrentGroup () {
|
|
362
|
+
return this.currentGroup
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
getBaseUnit () {
|
|
366
|
+
return this.curConfig.baseUnit
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
getHeight () {
|
|
370
|
+
return this.svgContent.getAttribute('height') / this.zoom
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
getWidth () {
|
|
374
|
+
return this.svgContent.getAttribute('width') / this.zoom
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
getRoundDigits () {
|
|
378
|
+
return this.saveOptions.round_digits
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
getSnappingStep () {
|
|
382
|
+
return this.curConfig.snappingStep
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
getGridSnapping () {
|
|
386
|
+
return this.curConfig.gridSnapping
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
getStartTransform () {
|
|
390
|
+
return this.startTransform
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
setStartTransform (transform) {
|
|
394
|
+
this.startTransform = transform
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
getZoom () {
|
|
398
|
+
return this.zoom
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
round (val) {
|
|
402
|
+
return Number.parseInt(val * this.zoom) / this.zoom
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
createSVGElement (jsonMap) {
|
|
406
|
+
return this.addSVGElementsFromJson(jsonMap)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
getContainer () {
|
|
410
|
+
return this.container
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
setStarted (s) {
|
|
414
|
+
this.started = s
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
getRubberBox () {
|
|
418
|
+
return this.rubberBox
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
setRubberBox (rb) {
|
|
422
|
+
this.rubberBox = rb
|
|
423
|
+
return this.rubberBox
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
addPtsToSelection ({ closedSubpath, grips }) {
|
|
427
|
+
// TODO: Correct this:
|
|
428
|
+
this.pathActions.canDeleteNodes = true
|
|
429
|
+
this.pathActions.closed_subpath = closedSubpath
|
|
430
|
+
this.call('pointsAdded', { closedSubpath, grips })
|
|
431
|
+
this.call('selected', grips)
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* @param {PlainObject} changes
|
|
436
|
+
* @param {ChangeElementCommand} changes.cmd
|
|
437
|
+
* @param {SVGPathElement} changes.elem
|
|
438
|
+
* @fires module:svgcanvas.SvgCanvas#event:changed
|
|
439
|
+
* @returns {void}
|
|
440
|
+
*/
|
|
441
|
+
endChanges ({ cmd, elem }) {
|
|
442
|
+
this.addCommandToHistory(cmd)
|
|
443
|
+
this.call('changed', [elem])
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
getCurrentMode () {
|
|
447
|
+
return this.currentMode
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
setCurrentMode (cm) {
|
|
451
|
+
this.currentMode = cm
|
|
452
|
+
return this.currentMode
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
getDrawnPath () {
|
|
456
|
+
return this.drawnPath
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
setDrawnPath (dp) {
|
|
460
|
+
this.drawnPath = dp
|
|
461
|
+
return this.drawnPath
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
setCurrentGroup (cg) {
|
|
465
|
+
this.currentGroup = cg
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
changeSvgContent () {
|
|
469
|
+
this.call('changed', [this.svgContent])
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
getStarted () {
|
|
473
|
+
return this.started
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
getCanvas () {
|
|
477
|
+
return this
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
getrootSctm () {
|
|
481
|
+
return this.rootSctm
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
getStartX () {
|
|
485
|
+
return this.startX
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
setStartX (value) {
|
|
489
|
+
this.startX = value
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
getStartY () {
|
|
493
|
+
return this.startY
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
setStartY (value) {
|
|
497
|
+
this.startY = value
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
getRStartX () {
|
|
501
|
+
return this.rStartX
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
getRStartY () {
|
|
505
|
+
return this.rStartY
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
getInitBbox () {
|
|
509
|
+
return this.initBbox
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
getCurrentResizeMode () {
|
|
513
|
+
return this.currentResizeMode
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
getJustSelected () {
|
|
517
|
+
return this.justSelected
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
getOpacAni () {
|
|
521
|
+
return this.opacAni
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
getParameter () {
|
|
525
|
+
return this.parameter
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
getNextParameter () {
|
|
529
|
+
return this.nextParameter
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
getStepCount () {
|
|
533
|
+
return STEP_COUNT
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
getThreSholdDist () {
|
|
537
|
+
return THRESHOLD_DIST
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
getSumDistance () {
|
|
541
|
+
return this.sumDistance
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
getStart (key) {
|
|
545
|
+
return this.start[key]
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
getEnd (key) {
|
|
549
|
+
return this.end[key]
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
getbSpline (key) {
|
|
553
|
+
return this.bSpline[key]
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
getNextPos (key) {
|
|
557
|
+
return this.nextPos[key]
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
getControllPoint1 (key) {
|
|
561
|
+
return this.controllPoint1[key]
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
getControllPoint2 (key) {
|
|
565
|
+
return this.controllPoint2[key]
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
getFreehand (key) {
|
|
569
|
+
return this.freehand[key]
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
getDrawing () {
|
|
573
|
+
return this.getCurrentDrawing()
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
getDAttr () {
|
|
577
|
+
return this.dAttr
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
getLastGoodImgUrl () {
|
|
581
|
+
return this.lastGoodImgUrl
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
getCurText (key) {
|
|
585
|
+
return this.curText[key]
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
setDAttr (value) {
|
|
589
|
+
this.dAttr = value
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
setEnd (key, value) {
|
|
593
|
+
this.end[key] = value
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
setControllPoint1 (key, value) {
|
|
597
|
+
this.controllPoint1[key] = value
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
setControllPoint2 (key, value) {
|
|
601
|
+
this.controllPoint2[key] = value
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
setJustSelected (value) {
|
|
605
|
+
this.justSelected = value
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
setParameter (value) {
|
|
609
|
+
this.parameter = value
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
setStart (value) {
|
|
613
|
+
this.start = value
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
setRStartX (value) {
|
|
617
|
+
this.rStartX = value
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
setRStartY (value) {
|
|
621
|
+
this.rStartY = value
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
setSumDistance (value) {
|
|
625
|
+
this.sumDistance = value
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
setbSpline (value) {
|
|
629
|
+
this.bSpline = value
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
setNextPos (value) {
|
|
633
|
+
this.nextPos = value
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
setNextParameter (value) {
|
|
637
|
+
this.nextParameter = value
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
setCurText (key, value) {
|
|
641
|
+
this.curText[key] = value
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
setFreehand (key, value) {
|
|
645
|
+
this.freehand[key] = value
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
setCurBBoxes (value) {
|
|
649
|
+
this.curBBoxes = value
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
getCurBBoxes () {
|
|
653
|
+
return this.curBBoxes
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
setInitBbox (value) {
|
|
657
|
+
this.initBbox = value
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
setRootSctm (value) {
|
|
661
|
+
this.rootSctm = value
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
setCurrentResizeMode (value) {
|
|
665
|
+
this.currentResizeMode = value
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
getLastClickPoint (key) {
|
|
669
|
+
return this.lastClickPoint[key]
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
setLastClickPoint (value) {
|
|
673
|
+
this.lastClickPoint = value
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
getId () {
|
|
677
|
+
return this.getCurrentDrawing().getId()
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
getUIStrings () {
|
|
681
|
+
return this.uiStrings
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
getNsMap () {
|
|
685
|
+
return this.nsMap
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
getSvgOptionApply () {
|
|
689
|
+
return this.saveOptions.apply
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
getSvgOptionImages () {
|
|
693
|
+
return this.saveOptions.images
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
getEncodableImages (key) {
|
|
697
|
+
return this.encodableImages[key]
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
setEncodableImages (key, value) {
|
|
701
|
+
this.encodableImages[key] = value
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
getVisElems () {
|
|
705
|
+
return visElems
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
getIdPrefix () {
|
|
709
|
+
return this.idprefix
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
getDataStorage () {
|
|
713
|
+
return dataStorage
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
setZoom (value) {
|
|
717
|
+
this.zoom = value
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
getImportIds (key) {
|
|
721
|
+
return this.importIds[key]
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
setImportIds (key, value) {
|
|
725
|
+
this.importIds[key] = value
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
setRemovedElements (key, value) {
|
|
729
|
+
this.removedElements[key] = value
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
setSvgContent (value) {
|
|
733
|
+
this.svgContent = value
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
getrefAttrs () {
|
|
737
|
+
return refAttrs
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
setCanvas (key, value) {
|
|
741
|
+
this[key] = value
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
setCurProperties (key, value) {
|
|
745
|
+
this.curProperties[key] = value
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
getCurProperties (key) {
|
|
749
|
+
return this.curProperties[key]
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
setCurShape (key, value) {
|
|
753
|
+
this.curShape[key] = value
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
gettingSelectorManager () {
|
|
757
|
+
return this.selectorManager
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
getContentW () {
|
|
761
|
+
return this.contentW
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
getContentH () {
|
|
765
|
+
return this.contentH
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
getClipboardID () {
|
|
769
|
+
return CLIPBOARD_ID
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
getSvgContent () {
|
|
773
|
+
return this.svgContent
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
getExtensions () {
|
|
777
|
+
return this.extensions
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
getSelector () {
|
|
781
|
+
return Selector
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
getMode () {
|
|
785
|
+
return this.currentMode
|
|
786
|
+
} // The current editor mode string
|
|
787
|
+
|
|
788
|
+
getNextId () {
|
|
789
|
+
return this.getCurrentDrawing().getNextId()
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
getCurCommand () {
|
|
793
|
+
return this.curCommand
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
setCurCommand (value) {
|
|
797
|
+
this.curCommand = value
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
getFilter () {
|
|
801
|
+
return this.filter
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
setFilter (value) {
|
|
805
|
+
this.filter = value
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
getFilterHidden () {
|
|
809
|
+
return this.filterHidden
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
setFilterHidden (value) {
|
|
813
|
+
this.filterHidden = value
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
/**
|
|
817
|
+
* Sets the editor's mode to the given string.
|
|
818
|
+
* @function module:svgcanvas.SvgCanvas#setMode
|
|
819
|
+
* @param {string} name - String with the new mode to change to
|
|
820
|
+
* @returns {void}
|
|
821
|
+
*/
|
|
822
|
+
setMode (name) {
|
|
823
|
+
this.pathActions.clear(true)
|
|
824
|
+
this.textActions.clear()
|
|
825
|
+
this.curProperties =
|
|
826
|
+
this.selectedElements[0]?.nodeName === 'text'
|
|
827
|
+
? this.curText
|
|
828
|
+
: this.curShape
|
|
829
|
+
this.currentMode = name
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* Clears the current document. This is not an undoable action.
|
|
834
|
+
* @function module:svgcanvas.SvgCanvas#clear
|
|
835
|
+
* @fires module:svgcanvas.SvgCanvas#event:beforeClear|afterClear
|
|
836
|
+
* @returns {void}
|
|
837
|
+
*/
|
|
838
|
+
clear () {
|
|
839
|
+
this.call('beforeClear')
|
|
840
|
+
this.pathActions.clear()
|
|
841
|
+
this.clearSelection()
|
|
842
|
+
// clear the svgcontent node
|
|
843
|
+
this.clearSvgContentElement()
|
|
844
|
+
// create new document
|
|
845
|
+
this.current_drawing_ = new draw.Drawing(this.svgContent)
|
|
846
|
+
// create empty first layer
|
|
847
|
+
this.createLayer('Layer 1')
|
|
848
|
+
// clear the undo stack
|
|
849
|
+
this.undoMgr.resetUndoStack()
|
|
850
|
+
// reset the selector manager
|
|
851
|
+
this.selectorManager.initGroup()
|
|
852
|
+
// reset the rubber band box
|
|
853
|
+
this.rubberBox = this.selectorManager.getRubberBandBox()
|
|
854
|
+
this.call('afterClear')
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
async addExtension (name, extInitFunc, { importLocale }) {
|
|
858
|
+
if (typeof extInitFunc !== 'function') {
|
|
859
|
+
throw new TypeError(
|
|
860
|
+
'Function argument expected for `svgcanvas.addExtension`'
|
|
861
|
+
)
|
|
862
|
+
}
|
|
863
|
+
if (name in this.extensions) {
|
|
864
|
+
throw new Error(
|
|
865
|
+
'Cannot add extension "' +
|
|
866
|
+
name +
|
|
867
|
+
'", an extension by that name already exists.'
|
|
868
|
+
)
|
|
869
|
+
}
|
|
870
|
+
const argObj = {
|
|
871
|
+
importLocale,
|
|
872
|
+
svgroot: this.svgroot,
|
|
873
|
+
svgContent: this.svgContent,
|
|
874
|
+
nonce: this.getCurrentDrawing().getNonce(),
|
|
875
|
+
selectorManager: this.selectorManager
|
|
876
|
+
}
|
|
877
|
+
const extObj = await extInitFunc(argObj)
|
|
878
|
+
if (extObj) {
|
|
879
|
+
extObj.name = name
|
|
880
|
+
}
|
|
881
|
+
this.extensions[name] = extObj
|
|
882
|
+
return this.call('extension_added', extObj)
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
addCommandToHistory (cmd) {
|
|
886
|
+
this.undoMgr.addCommandToHistory(cmd)
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
restoreRefElements (elem) {
|
|
890
|
+
// Look for missing reference elements, restore any found
|
|
891
|
+
const attrs = {}
|
|
892
|
+
refAttrs.forEach((item, _) => {
|
|
893
|
+
attrs[item] = elem.getAttribute(item)
|
|
894
|
+
})
|
|
895
|
+
Object.values(attrs).forEach(val => {
|
|
896
|
+
if (val?.startsWith('url(')) {
|
|
897
|
+
const id = getUrlFromAttr(val).substr(1)
|
|
898
|
+
const ref = getElement(id)
|
|
899
|
+
if (!ref) {
|
|
900
|
+
findDefs().append(this.removedElements[id])
|
|
901
|
+
delete this.removedElements[id]
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
})
|
|
905
|
+
const childs = elem.getElementsByTagName('*')
|
|
906
|
+
|
|
907
|
+
if (childs.length) {
|
|
908
|
+
for (let i = 0, l = childs.length; i < l; i++) {
|
|
909
|
+
this.restoreRefElements(childs[i])
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
call (ev, arg) {
|
|
915
|
+
if (this.events[ev]) {
|
|
916
|
+
return this.events[ev](window, arg)
|
|
917
|
+
}
|
|
918
|
+
return undefined
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
/**
|
|
922
|
+
* Attaches a callback function to an event.
|
|
923
|
+
* @function module:svgcanvas.SvgCanvas#bind
|
|
924
|
+
* @param {string} ev - String indicating the name of the event
|
|
925
|
+
* @param {module:svgcanvas.EventHandler} f - The callback function to bind to the event
|
|
926
|
+
* @returns {module:svgcanvas.EventHandler} The previous event
|
|
927
|
+
*/
|
|
928
|
+
bind (ev, f) {
|
|
929
|
+
const old = this.events[ev]
|
|
930
|
+
this.events[ev] = f
|
|
931
|
+
return old
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
/**
|
|
935
|
+
* Flash the clipboard data momentarily on localStorage so all tabs can see.
|
|
936
|
+
* @returns {void}
|
|
937
|
+
*/
|
|
938
|
+
flashStorage () {
|
|
939
|
+
const data = sessionStorage.getItem(CLIPBOARD_ID)
|
|
940
|
+
localStorage.setItem(CLIPBOARD_ID, data)
|
|
941
|
+
setTimeout(() => {
|
|
942
|
+
localStorage.removeItem(CLIPBOARD_ID)
|
|
943
|
+
}, 1)
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
/**
|
|
947
|
+
* Selects only the given elements, shortcut for `clearSelection(); addToSelection()`.
|
|
948
|
+
* @function module:svgcanvas.SvgCanvas#selectOnly
|
|
949
|
+
* @param {Element[]} elems - an array of DOM elements to be selected
|
|
950
|
+
* @param {boolean} showGrips - Indicates whether the resize grips should be shown
|
|
951
|
+
* @returns {void}
|
|
952
|
+
*/
|
|
953
|
+
selectOnly (elems, showGrips) {
|
|
954
|
+
this.clearSelection(true)
|
|
955
|
+
this.addToSelection(elems, showGrips)
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/**
|
|
959
|
+
* Removes elements from the selection.
|
|
960
|
+
* @function module:svgcanvas.SvgCanvas#removeFromSelection
|
|
961
|
+
* @param {Element[]} elemsToRemove - An array of elements to remove from selection
|
|
962
|
+
* @returns {void}
|
|
963
|
+
*/
|
|
964
|
+
removeFromSelection (elemsToRemove) {
|
|
965
|
+
if (!this.selectedElements[0]) {
|
|
966
|
+
return
|
|
967
|
+
}
|
|
968
|
+
if (!elemsToRemove.length) {
|
|
969
|
+
return
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
// find every element and remove it from our array copy
|
|
973
|
+
const newSelectedItems = []
|
|
974
|
+
const len = this.selectedElements.length
|
|
975
|
+
for (let i = 0; i < len; ++i) {
|
|
976
|
+
const elem = this.selectedElements[i]
|
|
977
|
+
if (elem) {
|
|
978
|
+
// keep the item
|
|
979
|
+
if (!elemsToRemove.includes(elem)) {
|
|
980
|
+
newSelectedItems.push(elem)
|
|
981
|
+
} else {
|
|
982
|
+
// remove the item and its selector
|
|
983
|
+
this.selectorManager.releaseSelector(elem)
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
// the copy becomes the master now
|
|
988
|
+
this.selectedElements = newSelectedItems
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
/**
|
|
992
|
+
* Clears the selection, then adds all elements in the current layer to the selection.
|
|
993
|
+
* @function module:svgcanvas.SvgCanvas#selectAllInCurrentLayer
|
|
994
|
+
* @returns {void}
|
|
995
|
+
*/
|
|
996
|
+
selectAllInCurrentLayer () {
|
|
997
|
+
const currentLayer = this.getCurrentDrawing().getCurrentLayer()
|
|
998
|
+
if (currentLayer) {
|
|
999
|
+
this.currentMode = 'select'
|
|
1000
|
+
if (this.currentGroup) {
|
|
1001
|
+
this.selectOnly(this.currentGroup.children)
|
|
1002
|
+
} else {
|
|
1003
|
+
this.selectOnly(currentLayer.children)
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
getOpacity () {
|
|
1009
|
+
return this.curShape.opacity
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
/**
|
|
1013
|
+
* @function module:svgcanvas.SvgCanvas#getSnapToGrid
|
|
1014
|
+
* @returns {boolean} The current snap to grid setting
|
|
1015
|
+
*/
|
|
1016
|
+
getSnapToGrid () {
|
|
1017
|
+
return this.curConfig.gridSnapping
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* @function module:svgcanvas.SvgCanvas#getVersion
|
|
1022
|
+
* @returns {string} A string which describes the revision number of SvgCanvas.
|
|
1023
|
+
*/
|
|
1024
|
+
getVersion () {
|
|
1025
|
+
return 'svgcanvas.js ($Rev$)'
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* Update interface strings with given values.
|
|
1030
|
+
* @function module:svgcanvas.SvgCanvas#setUiStrings
|
|
1031
|
+
* @param {module:path.uiStrings} strs - Object with strings (see the [locales API]{@link module:locale.LocaleStrings} and the [tutorial]{@tutorial LocaleDocs})
|
|
1032
|
+
* @returns {void}
|
|
1033
|
+
*/
|
|
1034
|
+
setUiStrings (strs) {
|
|
1035
|
+
Object.assign(this.uiStrings, strs.notification)
|
|
1036
|
+
pathModule.setUiStrings(strs)
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* Update configuration options with given values.
|
|
1041
|
+
* @function module:svgcanvas.SvgCanvas#setConfig
|
|
1042
|
+
* @param {module:SVGEditor.Config} opts - Object with options
|
|
1043
|
+
* @returns {void}
|
|
1044
|
+
*/
|
|
1045
|
+
setConfig (opts) {
|
|
1046
|
+
Object.assign(this.curConfig, opts)
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
/**
|
|
1050
|
+
* @function module:svgcanvas.SvgCanvas#getDocumentTitle
|
|
1051
|
+
* @returns {string|void} The current document title or an empty string if not found
|
|
1052
|
+
*/
|
|
1053
|
+
getDocumentTitle () {
|
|
1054
|
+
return this.getTitle(this.svgContent)
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
getOffset () {
|
|
1058
|
+
return {
|
|
1059
|
+
x: Number(this.svgContent.getAttribute('x')),
|
|
1060
|
+
y: Number(this.svgContent.getAttribute('y'))
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
getColor (type) {
|
|
1065
|
+
return this.curProperties[type]
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
setStrokePaint (paint) {
|
|
1069
|
+
this.setPaint('stroke', paint)
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
/**
|
|
1073
|
+
* @function module:svgcanvas.SvgCanvas#setFillPaint
|
|
1074
|
+
* @param {module:jGraduate~Paint} paint
|
|
1075
|
+
* @returns {void}
|
|
1076
|
+
*/
|
|
1077
|
+
setFillPaint (paint) {
|
|
1078
|
+
this.setPaint('fill', paint)
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* @function module:svgcanvas.SvgCanvas#getStrokeWidth
|
|
1083
|
+
* @returns {Float|string} The current stroke-width value
|
|
1084
|
+
*/
|
|
1085
|
+
getStrokeWidth () {
|
|
1086
|
+
return this.curProperties.stroke_width
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
/**
|
|
1090
|
+
* @function module:svgcanvas.SvgCanvas#getStyle
|
|
1091
|
+
* @returns {module:svgcanvas.StyleOptions} current style options
|
|
1092
|
+
*/
|
|
1093
|
+
getStyle () {
|
|
1094
|
+
return this.curShape
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
/**
|
|
1098
|
+
* Sets the given opacity on the current selected elements.
|
|
1099
|
+
* @function module:svgcanvas.SvgCanvas#setOpacity
|
|
1100
|
+
* @param {string} val
|
|
1101
|
+
* @returns {void}
|
|
1102
|
+
*/
|
|
1103
|
+
setOpacity (val) {
|
|
1104
|
+
this.curShape.opacity = val
|
|
1105
|
+
this.changeSelectedAttribute('opacity', val)
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
/**
|
|
1109
|
+
* @function module:svgcanvas.SvgCanvas#getFillOpacity
|
|
1110
|
+
* @returns {Float} the current fill opacity
|
|
1111
|
+
*/
|
|
1112
|
+
getFillOpacity () {
|
|
1113
|
+
return this.curShape.fill_opacity
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
/**
|
|
1117
|
+
* @function module:svgcanvas.SvgCanvas#getStrokeOpacity
|
|
1118
|
+
* @returns {string} the current stroke opacity
|
|
1119
|
+
*/
|
|
1120
|
+
getStrokeOpacity () {
|
|
1121
|
+
return this.curShape.stroke_opacity
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
/**
|
|
1125
|
+
* Sets the current fill/stroke opacity.
|
|
1126
|
+
* @function module:svgcanvas.SvgCanvas#setPaintOpacity
|
|
1127
|
+
* @param {string} type - String with "fill" or "stroke"
|
|
1128
|
+
* @param {Float} val - Float with the new opacity value
|
|
1129
|
+
* @param {boolean} preventUndo - Indicates whether or not this should be an undoable action
|
|
1130
|
+
* @returns {void}
|
|
1131
|
+
*/
|
|
1132
|
+
setPaintOpacity (type, val, preventUndo) {
|
|
1133
|
+
this.curShape[type + '_opacity'] = val
|
|
1134
|
+
if (!preventUndo) {
|
|
1135
|
+
this.changeSelectedAttribute(type + '-opacity', val)
|
|
1136
|
+
} else {
|
|
1137
|
+
this.changeSelectedAttributeNoUndo(type + '-opacity', val)
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
/**
|
|
1142
|
+
* Gets the current fill/stroke opacity.
|
|
1143
|
+
* @function module:svgcanvas.SvgCanvas#getPaintOpacity
|
|
1144
|
+
* @param {"fill"|"stroke"} type - String with "fill" or "stroke"
|
|
1145
|
+
* @returns {Float} Fill/stroke opacity
|
|
1146
|
+
*/
|
|
1147
|
+
getPaintOpacity (type) {
|
|
1148
|
+
return type === 'fill' ? this.getFillOpacity() : this.getStrokeOpacity()
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
* Gets the `stdDeviation` blur value of the given element.
|
|
1153
|
+
* @function module:svgcanvas.SvgCanvas#getBlur
|
|
1154
|
+
* @param {Element} elem - The element to check the blur value for
|
|
1155
|
+
* @returns {string} stdDeviation blur attribute value
|
|
1156
|
+
*/
|
|
1157
|
+
getBlur (elem) {
|
|
1158
|
+
let val = 0
|
|
1159
|
+
if (elem) {
|
|
1160
|
+
const filterUrl = elem.getAttribute('filter')
|
|
1161
|
+
if (filterUrl) {
|
|
1162
|
+
const blur = getElement(elem.id + '_blur')
|
|
1163
|
+
if (blur) {
|
|
1164
|
+
val = blur.firstChild.getAttribute('stdDeviation')
|
|
1165
|
+
} else {
|
|
1166
|
+
const filterElem = getRefElem(filterUrl)
|
|
1167
|
+
const blurElem = getFeGaussianBlur(filterElem)
|
|
1168
|
+
if (blurElem !== null) {
|
|
1169
|
+
val = blurElem.getAttribute('stdDeviation')
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
return val
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
/**
|
|
1178
|
+
* Sets a given URL to be a "last good image" URL.
|
|
1179
|
+
* @function module:svgcanvas.SvgCanvas#setGoodImage
|
|
1180
|
+
* @param {string} val
|
|
1181
|
+
* @returns {void}
|
|
1182
|
+
*/
|
|
1183
|
+
setGoodImage (val) {
|
|
1184
|
+
this.lastGoodImgUrl = val
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
/**
|
|
1188
|
+
* Returns the current drawing as raw SVG XML text.
|
|
1189
|
+
* @function module:svgcanvas.SvgCanvas#getSvgString
|
|
1190
|
+
* @returns {string} The current drawing as raw SVG XML text.
|
|
1191
|
+
*/
|
|
1192
|
+
getSvgString () {
|
|
1193
|
+
this.saveOptions.apply = false
|
|
1194
|
+
return this.svgCanvasToString()
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
/**
|
|
1198
|
+
* This function determines whether to use a nonce in the prefix, when
|
|
1199
|
+
* generating IDs for future documents in SVG-Edit.
|
|
1200
|
+
* If you're controlling SVG-Edit externally, and want randomized IDs, call
|
|
1201
|
+
* this BEFORE calling `svgCanvas.setSvgString`.
|
|
1202
|
+
* @function module:svgcanvas.SvgCanvas#randomizeIds
|
|
1203
|
+
* @param {boolean} [enableRandomization] If true, adds a nonce to the prefix. Thus
|
|
1204
|
+
* `svgCanvas.randomizeIds() <==> svgCanvas.randomizeIds(true)`
|
|
1205
|
+
* @returns {void}
|
|
1206
|
+
*/
|
|
1207
|
+
randomizeIds (enableRandomization) {
|
|
1208
|
+
if (arguments.length > 0 && enableRandomization === false) {
|
|
1209
|
+
draw.randomizeIds(false, this.getCurrentDrawing())
|
|
1210
|
+
} else {
|
|
1211
|
+
draw.randomizeIds(true, this.getCurrentDrawing())
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
/**
|
|
1216
|
+
* Convert selected element to a path, or get the BBox of an element-as-path.
|
|
1217
|
+
* @function module:svgcanvas.SvgCanvas#convertToPath
|
|
1218
|
+
* @todo (codedread): Remove the getBBox argument and split this function into two.
|
|
1219
|
+
* @param {Element} elem - The DOM element to be converted
|
|
1220
|
+
* @param {boolean} getBBox - Boolean on whether or not to only return the path's BBox
|
|
1221
|
+
* @returns {void|DOMRect|false|SVGPathElement|null} If the getBBox flag is true, the resulting path's bounding box object.
|
|
1222
|
+
* Otherwise the resulting path element is returned.
|
|
1223
|
+
*/
|
|
1224
|
+
convertToPath (elem, getBBox) {
|
|
1225
|
+
// if elems not given, recursively call convertPath for all selected elements.
|
|
1226
|
+
if (!elem) {
|
|
1227
|
+
const elems = this.selectedElements
|
|
1228
|
+
elems.forEach(el => {
|
|
1229
|
+
if (el) {
|
|
1230
|
+
this.convertToPath(el)
|
|
1231
|
+
}
|
|
1232
|
+
})
|
|
1233
|
+
return undefined
|
|
1234
|
+
}
|
|
1235
|
+
if (getBBox) {
|
|
1236
|
+
return getBBoxOfElementAsPath(
|
|
1237
|
+
elem,
|
|
1238
|
+
this.addSVGElementsFromJson,
|
|
1239
|
+
this.pathActions
|
|
1240
|
+
)
|
|
1241
|
+
}
|
|
1242
|
+
// TODO: Why is this applying attributes from this.curShape, then inside utilities.convertToPath it's pulling addition attributes from elem?
|
|
1243
|
+
// TODO: If convertToPath is called with one elem, this.curShape and elem are probably the same; but calling with multiple is a bug or cool feature.
|
|
1244
|
+
const attrs = {
|
|
1245
|
+
fill: this.curShape.fill,
|
|
1246
|
+
'fill-opacity': this.curShape.fill_opacity,
|
|
1247
|
+
stroke: this.curShape.stroke,
|
|
1248
|
+
'stroke-width': this.curShape.stroke_width,
|
|
1249
|
+
'stroke-dasharray': this.curShape.stroke_dasharray,
|
|
1250
|
+
'stroke-linejoin': this.curShape.stroke_linejoin,
|
|
1251
|
+
'stroke-linecap': this.curShape.stroke_linecap,
|
|
1252
|
+
'stroke-opacity': this.curShape.stroke_opacity,
|
|
1253
|
+
opacity: this.curShape.opacity,
|
|
1254
|
+
visibility: 'hidden'
|
|
1255
|
+
}
|
|
1256
|
+
return convertToPath(elem, attrs, this) // call convertToPath from utilities.js
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
/**
|
|
1260
|
+
* Removes all selected elements from the DOM and adds the change to the
|
|
1261
|
+
* history stack. Remembers removed elements on the clipboard.
|
|
1262
|
+
* @function module:svgcanvas.SvgCanvas#cutSelectedElements
|
|
1263
|
+
* @returns {void}
|
|
1264
|
+
*/
|
|
1265
|
+
cutSelectedElements () {
|
|
1266
|
+
this.copySelectedElements()
|
|
1267
|
+
this.deleteSelectedElements()
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
initializeSvgCanvasMethods () {
|
|
1271
|
+
this.getJsonFromSvgElements = getJsonFromSvgElements
|
|
1272
|
+
this.addSVGElementsFromJson = addSVGElementsFromJson
|
|
1273
|
+
this.clearSvgContentElement = clearSvgContentElementInit
|
|
1274
|
+
this.textActions = textActionsMethod
|
|
1275
|
+
this.getStrokedBBox = getStrokedBBoxDefaultVisible
|
|
1276
|
+
this.getVisibleElements = getVisibleElements
|
|
1277
|
+
this.stringToHTML = stringToHTML
|
|
1278
|
+
this.insertChildAtIndex = insertChildAtIndex
|
|
1279
|
+
this.getClosest = getClosest
|
|
1280
|
+
this.getParents = getParents
|
|
1281
|
+
this.isLayer = draw.Layer.isLayer
|
|
1282
|
+
this.matrixMultiply = matrixMultiply
|
|
1283
|
+
this.hasMatrixTransform = hasMatrixTransform
|
|
1284
|
+
this.transformListToTransform = transformListToTransform
|
|
1285
|
+
this.convertToNum = convertToNum
|
|
1286
|
+
this.findDefs = findDefs
|
|
1287
|
+
this.getUrlFromAttr = getUrlFromAttr
|
|
1288
|
+
this.getHref = getHref
|
|
1289
|
+
this.setHref = setHref
|
|
1290
|
+
this.getBBox = utilsGetBBox
|
|
1291
|
+
this.getRotationAngle = getRotationAngle
|
|
1292
|
+
this.getElement = getElement
|
|
1293
|
+
this.getRefElem = getRefElem
|
|
1294
|
+
this.assignAttributes = assignAttributes
|
|
1295
|
+
this.cleanupElement = cleanupElement
|
|
1296
|
+
this.remapElement = remapElement
|
|
1297
|
+
this.recalculateDimensions = recalculateDimensions
|
|
1298
|
+
this.sanitizeSvg = sanitizeSvg
|
|
1299
|
+
this.pasteElements = pasteElementsMethod // Remembers the current selected elements on the clipboard.
|
|
1300
|
+
this.identifyLayers = draw.identifyLayers
|
|
1301
|
+
this.createLayer = draw.createLayer
|
|
1302
|
+
this.cloneLayer = draw.cloneLayer
|
|
1303
|
+
this.deleteCurrentLayer = draw.deleteCurrentLayer
|
|
1304
|
+
this.setCurrentLayer = draw.setCurrentLayer
|
|
1305
|
+
this.renameCurrentLayer = draw.renameCurrentLayer
|
|
1306
|
+
this.setCurrentLayerPosition = draw.setCurrentLayerPosition
|
|
1307
|
+
this.indexCurrentLayer = draw.indexCurrentLayer
|
|
1308
|
+
this.setLayerVisibility = draw.setLayerVisibility
|
|
1309
|
+
this.moveSelectedToLayer = draw.moveSelectedToLayer
|
|
1310
|
+
this.mergeLayer = draw.mergeLayer
|
|
1311
|
+
this.mergeAllLayers = draw.mergeAllLayers
|
|
1312
|
+
this.leaveContext = draw.leaveContext
|
|
1313
|
+
this.setContext = draw.setContext
|
|
1314
|
+
this.changeSelectedAttributeNoUndo = changeSelectedAttributeNoUndoMethod // This function makes the changes to the elements. It does not add the change to the history stack.
|
|
1315
|
+
this.changeSelectedAttribute = changeSelectedAttributeMethod // Change the given/selected element and add the original value to the history stack.
|
|
1316
|
+
this.setBlurNoUndo = setBlurNoUndo // Sets the `stdDeviation` blur value on the selected element without being undoable.
|
|
1317
|
+
this.setBlurOffsets = setBlurOffsets // Sets the `x`, `y`, `width`, `height` values of the filter element in order to make the blur not be clipped. Removes them if not neeeded.
|
|
1318
|
+
this.setBlur = setBlur // Adds/updates the blur filter to the selected element.
|
|
1319
|
+
this.smoothControlPoints = pathModule.smoothControlPoints
|
|
1320
|
+
this.getTypeMap = getTypeMap
|
|
1321
|
+
this.history = history // object with all histor methods
|
|
1322
|
+
this.NS = NS
|
|
1323
|
+
this.$id = $id
|
|
1324
|
+
this.$qq = $qq
|
|
1325
|
+
this.$qa = $qa
|
|
1326
|
+
this.$click = $click
|
|
1327
|
+
this.encode64 = encode64
|
|
1328
|
+
this.decode64 = decode64
|
|
1329
|
+
this.mergeDeep = mergeDeep
|
|
1330
|
+
}
|
|
1331
|
+
} // End class
|
|
1332
|
+
|
|
1333
|
+
// attach utilities function to the class that are used by SvgEdit so
|
|
1334
|
+
// we can avoid using the whole utilities.js file in svgEdit.js
|
|
1335
|
+
SvgCanvas.$id = $id
|
|
1336
|
+
SvgCanvas.$qq = $qq
|
|
1337
|
+
SvgCanvas.$qa = $qa
|
|
1338
|
+
SvgCanvas.$click = $click
|
|
1339
|
+
SvgCanvas.encode64 = encode64
|
|
1340
|
+
SvgCanvas.decode64 = decode64
|
|
1341
|
+
SvgCanvas.mergeDeep = mergeDeep
|
|
1342
|
+
SvgCanvas.getClosest = getClosest
|
|
1343
|
+
SvgCanvas.getParents = getParents
|
|
1344
|
+
SvgCanvas.blankPageObjectURL = blankPageObjectURL
|
|
1345
|
+
SvgCanvas.Paint = Paint
|
|
1346
|
+
|
|
1347
|
+
export default SvgCanvas
|