@svgedit/svgcanvas 7.1.4 → 7.1.5
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/demos/canvas.html +70 -0
- package/dist/svgcanvas.js +33 -33
- package/dist/svgcanvas.js.map +1 -1
- package/elem-get-set.js +1 -1
- package/event.js +1 -1
- package/package.json +4 -4
- package/path-actions.js +1 -1
- package/path.js +1 -1
- package/recalculate.js +1 -1
- package/rollup.config.js +0 -2
- package/svg-exec.js +1 -1
- package/svgcanvas.js +6 -2
- package/units.js +260 -0
- package/utilities.js +1 -1
package/elem-get-set.js
CHANGED
package/event.js
CHANGED
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svgedit/svgcanvas",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.5",
|
|
4
4
|
"description": "SVG Canvas",
|
|
5
5
|
"main": "dist/svgcanvas.js",
|
|
6
6
|
"author": "Narendra Sisodiya",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
|
-
|
|
9
|
+
},
|
|
10
10
|
"bugs": {
|
|
11
11
|
"url": "https://github.com/SVG-Edit/svgedit/issues"
|
|
12
12
|
},
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
15
|
"url": "git+https://github.com/SVG-Edit/svgedit.git"
|
|
16
|
-
|
|
16
|
+
},
|
|
17
17
|
"homepage": "https://github.com/SVG-Edit/svgedit#readme",
|
|
18
18
|
"contributors": [
|
|
19
19
|
"Pavol Rusnak",
|
|
@@ -51,4 +51,4 @@
|
|
|
51
51
|
"scripts": {
|
|
52
52
|
"build": "rollup -c"
|
|
53
53
|
}
|
|
54
|
-
}
|
|
54
|
+
}
|
package/path-actions.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { NS } from './namespaces.js'
|
|
10
|
-
import { shortFloat } from '
|
|
10
|
+
import { shortFloat } from './units.js'
|
|
11
11
|
import { ChangeElementCommand, BatchCommand } from './history.js'
|
|
12
12
|
import {
|
|
13
13
|
transformPoint, snapToAngle, rectsIntersect,
|
package/path.js
CHANGED
package/recalculate.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { NS } from './namespaces.js'
|
|
8
|
-
import { convertToNum } from '
|
|
8
|
+
import { convertToNum } from './units.js'
|
|
9
9
|
import { getRotationAngle, getHref, getBBox, getRefElem } from './utilities.js'
|
|
10
10
|
import { BatchCommand, ChangeElementCommand } from './history.js'
|
|
11
11
|
import { remapElement } from './coords.js'
|
package/rollup.config.js
CHANGED
|
@@ -10,8 +10,6 @@ import { terser } from 'rollup-plugin-terser'
|
|
|
10
10
|
// import progress from 'rollup-plugin-progress';
|
|
11
11
|
import filesize from 'rollup-plugin-filesize'
|
|
12
12
|
|
|
13
|
-
const dest = ['dist/svgcanvas']
|
|
14
|
-
|
|
15
13
|
// remove existing distribution
|
|
16
14
|
rimraf('./dist', () => console.info('recreating dist'))
|
|
17
15
|
|
package/svg-exec.js
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
hashCode
|
|
25
25
|
} from './utilities.js'
|
|
26
26
|
import { transformPoint, transformListToTransform } from './math.js'
|
|
27
|
-
import { convertUnit, shortFloat, convertToNum } from '
|
|
27
|
+
import { convertUnit, shortFloat, convertToNum } from './units.js'
|
|
28
28
|
import { isGecko, isChrome, isWebkit } from '../../src/common/browser.js'
|
|
29
29
|
import * as pathModule from './path.js'
|
|
30
30
|
import { NS } from './namespaces.js'
|
package/svgcanvas.js
CHANGED
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
hasMatrixTransform,
|
|
72
72
|
transformListToTransform
|
|
73
73
|
} from './math.js'
|
|
74
|
-
import { convertToNum, init as unitsInit, getTypeMap } from '
|
|
74
|
+
import { convertToNum, init as unitsInit, getTypeMap, isValidUnit, convertUnit } from './units.js'
|
|
75
75
|
import { init as svgInit } from './svg-exec.js'
|
|
76
76
|
import { remapElement, init as coordsInit } from './coords.js'
|
|
77
77
|
import {
|
|
@@ -118,6 +118,7 @@ class SvgCanvas {
|
|
|
118
118
|
constructor (container, config) {
|
|
119
119
|
// imported function made available as methods
|
|
120
120
|
this.initializeSvgCanvasMethods()
|
|
121
|
+
unitsInit(this)
|
|
121
122
|
const { pathActions } = pathModule
|
|
122
123
|
|
|
123
124
|
// initialize class variables
|
|
@@ -228,7 +229,6 @@ class SvgCanvas {
|
|
|
228
229
|
this.selectedElements = []
|
|
229
230
|
|
|
230
231
|
jsonInit(this)
|
|
231
|
-
unitsInit(this)
|
|
232
232
|
utilsInit(this)
|
|
233
233
|
coordsInit(this)
|
|
234
234
|
recalculateInit(this)
|
|
@@ -1343,5 +1343,9 @@ SvgCanvas.getClosest = getClosest
|
|
|
1343
1343
|
SvgCanvas.getParents = getParents
|
|
1344
1344
|
SvgCanvas.blankPageObjectURL = blankPageObjectURL
|
|
1345
1345
|
SvgCanvas.Paint = Paint
|
|
1346
|
+
SvgCanvas.getTypeMap = getTypeMap
|
|
1347
|
+
SvgCanvas.convertToNum = convertToNum
|
|
1348
|
+
SvgCanvas.isValidUnit = isValidUnit
|
|
1349
|
+
SvgCanvas.convertUnit = convertUnit
|
|
1346
1350
|
|
|
1347
1351
|
export default SvgCanvas
|
package/units.js
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tools for working with units.
|
|
3
|
+
* @module units
|
|
4
|
+
* @license MIT
|
|
5
|
+
*
|
|
6
|
+
* @copyright 2010 Alexis Deveria, 2010 Jeff Schiller
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const NSSVG = 'http://www.w3.org/2000/svg'
|
|
10
|
+
|
|
11
|
+
const wAttrs = ['x', 'x1', 'cx', 'rx', 'width']
|
|
12
|
+
const hAttrs = ['y', 'y1', 'cy', 'ry', 'height']
|
|
13
|
+
const unitAttrs = ['r', 'radius', ...wAttrs, ...hAttrs]
|
|
14
|
+
|
|
15
|
+
// Container of elements.
|
|
16
|
+
let elementContainer_
|
|
17
|
+
|
|
18
|
+
// Stores mapping of unit type to user coordinates.
|
|
19
|
+
let typeMap_ = {}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @interface module:units.ElementContainer
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* @function module:units.ElementContainer#getBaseUnit
|
|
26
|
+
* @returns {string} The base unit type of the container ('em')
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* @function module:units.ElementContainer#getElement
|
|
30
|
+
* @returns {?Element} An element in the container given an id
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* @function module:units.ElementContainer#getHeight
|
|
34
|
+
* @returns {Float} The container's height
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* @function module:units.ElementContainer#getWidth
|
|
38
|
+
* @returns {Float} The container's width
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* @function module:units.ElementContainer#getRoundDigits
|
|
42
|
+
* @returns {Integer} The number of digits number should be rounded to
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @typedef {PlainObject} module:units.TypeMap
|
|
47
|
+
* @property {Float} em
|
|
48
|
+
* @property {Float} ex
|
|
49
|
+
* @property {Float} in
|
|
50
|
+
* @property {Float} cm
|
|
51
|
+
* @property {Float} mm
|
|
52
|
+
* @property {Float} pt
|
|
53
|
+
* @property {Float} pc
|
|
54
|
+
* @property {Integer} px
|
|
55
|
+
* @property {0} %
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Initializes this module.
|
|
60
|
+
*
|
|
61
|
+
* @function module:units.init
|
|
62
|
+
* @param {module:units.ElementContainer} elementContainer - An object implementing the ElementContainer interface.
|
|
63
|
+
* @returns {void}
|
|
64
|
+
*/
|
|
65
|
+
export const init = function (elementContainer) {
|
|
66
|
+
elementContainer_ = elementContainer
|
|
67
|
+
|
|
68
|
+
// Get correct em/ex values by creating a temporary SVG.
|
|
69
|
+
const svg = document.createElementNS(NSSVG, 'svg')
|
|
70
|
+
document.body.append(svg)
|
|
71
|
+
const rect = document.createElementNS(NSSVG, 'rect')
|
|
72
|
+
rect.setAttribute('width', '1em')
|
|
73
|
+
rect.setAttribute('height', '1ex')
|
|
74
|
+
rect.setAttribute('x', '1in')
|
|
75
|
+
svg.append(rect)
|
|
76
|
+
const bb = rect.getBBox()
|
|
77
|
+
svg.remove()
|
|
78
|
+
|
|
79
|
+
const inch = bb.x
|
|
80
|
+
typeMap_ = {
|
|
81
|
+
em: bb.width,
|
|
82
|
+
ex: bb.height,
|
|
83
|
+
in: inch,
|
|
84
|
+
cm: inch / 2.54,
|
|
85
|
+
mm: inch / 25.4,
|
|
86
|
+
pt: inch / 72,
|
|
87
|
+
pc: inch / 6,
|
|
88
|
+
px: 1,
|
|
89
|
+
'%': 0
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Group: Unit conversion functions.
|
|
95
|
+
*/
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @function module:units.getTypeMap
|
|
99
|
+
* @returns {module:units.TypeMap} The unit object with values for each unit
|
|
100
|
+
*/
|
|
101
|
+
export const getTypeMap = () => {
|
|
102
|
+
return typeMap_
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @typedef {GenericArray} module:units.CompareNumbers
|
|
107
|
+
* @property {Integer} length 2
|
|
108
|
+
* @property {Float} 0
|
|
109
|
+
* @property {Float} 1
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Rounds a given value to a float with number of digits defined in
|
|
114
|
+
* `round_digits` of `saveOptions`
|
|
115
|
+
*
|
|
116
|
+
* @function module:units.shortFloat
|
|
117
|
+
* @param {string|Float|module:units.CompareNumbers} val - The value (or Array of two numbers) to be rounded
|
|
118
|
+
* @returns {Float|string} If a string/number was given, returns a Float. If an array, return a string
|
|
119
|
+
* with comma-separated floats
|
|
120
|
+
*/
|
|
121
|
+
export const shortFloat = (val) => {
|
|
122
|
+
const digits = elementContainer_.getRoundDigits()
|
|
123
|
+
if (!isNaN(val)) {
|
|
124
|
+
return Number(Number(val).toFixed(digits))
|
|
125
|
+
}
|
|
126
|
+
if (Array.isArray(val)) {
|
|
127
|
+
return shortFloat(val[0]) + ',' + shortFloat(val[1])
|
|
128
|
+
}
|
|
129
|
+
return Number.parseFloat(val).toFixed(digits) - 0
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Converts the number to given unit or baseUnit.
|
|
134
|
+
* @function module:units.convertUnit
|
|
135
|
+
* @param {string|Float} val
|
|
136
|
+
* @param {"em"|"ex"|"in"|"cm"|"mm"|"pt"|"pc"|"px"|"%"} [unit]
|
|
137
|
+
* @returns {Float}
|
|
138
|
+
*/
|
|
139
|
+
export const convertUnit = (val, unit) => {
|
|
140
|
+
unit = unit || elementContainer_.getBaseUnit()
|
|
141
|
+
// baseVal.convertToSpecifiedUnits(unitNumMap[unit]);
|
|
142
|
+
// const val = baseVal.valueInSpecifiedUnits;
|
|
143
|
+
// baseVal.convertToSpecifiedUnits(1);
|
|
144
|
+
return shortFloat(val / typeMap_[unit])
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Sets an element's attribute based on the unit in its current value.
|
|
149
|
+
*
|
|
150
|
+
* @function module:units.setUnitAttr
|
|
151
|
+
* @param {Element} elem - DOM element to be changed
|
|
152
|
+
* @param {string} attr - Name of the attribute associated with the value
|
|
153
|
+
* @param {string} val - Attribute value to convert
|
|
154
|
+
* @returns {void}
|
|
155
|
+
*/
|
|
156
|
+
export const setUnitAttr = (elem, attr, val) => {
|
|
157
|
+
elem.setAttribute(attr, val)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const attrsToConvert = {
|
|
161
|
+
line: ['x1', 'x2', 'y1', 'y2'],
|
|
162
|
+
circle: ['cx', 'cy', 'r'],
|
|
163
|
+
ellipse: ['cx', 'cy', 'rx', 'ry'],
|
|
164
|
+
foreignObject: ['x', 'y', 'width', 'height'],
|
|
165
|
+
rect: ['x', 'y', 'width', 'height'],
|
|
166
|
+
image: ['x', 'y', 'width', 'height'],
|
|
167
|
+
use: ['x', 'y', 'width', 'height'],
|
|
168
|
+
text: ['x', 'y']
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Converts all applicable attributes to the configured baseUnit.
|
|
173
|
+
* @function module:units.convertAttrs
|
|
174
|
+
* @param {Element} element - A DOM element whose attributes should be converted
|
|
175
|
+
* @returns {void}
|
|
176
|
+
*/
|
|
177
|
+
export const convertAttrs = (element) => {
|
|
178
|
+
const elName = element.tagName
|
|
179
|
+
const unit = elementContainer_.getBaseUnit()
|
|
180
|
+
const attrs = attrsToConvert[elName]
|
|
181
|
+
if (!attrs) { return }
|
|
182
|
+
|
|
183
|
+
attrs.forEach((attr) => {
|
|
184
|
+
const cur = element.getAttribute(attr)
|
|
185
|
+
if (cur && !isNaN(cur)) {
|
|
186
|
+
element.setAttribute(attr, (cur / typeMap_[unit]) + unit)
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Converts given values to numbers. Attributes must be supplied in
|
|
193
|
+
* case a percentage is given.
|
|
194
|
+
*
|
|
195
|
+
* @function module:units.convertToNum
|
|
196
|
+
* @param {string} attr - Name of the attribute associated with the value
|
|
197
|
+
* @param {string} val - Attribute value to convert
|
|
198
|
+
* @returns {Float} The converted number
|
|
199
|
+
*/
|
|
200
|
+
export const convertToNum = (attr, val) => {
|
|
201
|
+
// Return a number if that's what it already is
|
|
202
|
+
if (!isNaN(val)) { return val - 0 }
|
|
203
|
+
if (val.substr(-1) === '%') {
|
|
204
|
+
// Deal with percentage, depends on attribute
|
|
205
|
+
const num = val.substr(0, val.length - 1) / 100
|
|
206
|
+
const width = elementContainer_.getWidth()
|
|
207
|
+
const height = elementContainer_.getHeight()
|
|
208
|
+
|
|
209
|
+
if (wAttrs.includes(attr)) {
|
|
210
|
+
return num * width
|
|
211
|
+
}
|
|
212
|
+
if (hAttrs.includes(attr)) {
|
|
213
|
+
return num * height
|
|
214
|
+
}
|
|
215
|
+
return num * Math.sqrt((width * width) + (height * height)) / Math.sqrt(2)
|
|
216
|
+
}
|
|
217
|
+
const unit = val.substr(-2)
|
|
218
|
+
const num = val.substr(0, val.length - 2)
|
|
219
|
+
// Note that this multiplication turns the string into a number
|
|
220
|
+
return num * typeMap_[unit]
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Check if an attribute's value is in a valid format.
|
|
225
|
+
* @function module:units.isValidUnit
|
|
226
|
+
* @param {string} attr - The name of the attribute associated with the value
|
|
227
|
+
* @param {string} val - The attribute value to check
|
|
228
|
+
* @param {Element} selectedElement
|
|
229
|
+
* @returns {boolean} Whether the unit is valid
|
|
230
|
+
*/
|
|
231
|
+
export const isValidUnit = (attr, val, selectedElement) => {
|
|
232
|
+
if (unitAttrs.includes(attr)) {
|
|
233
|
+
// True if it's just a number
|
|
234
|
+
if (!isNaN(val)) {
|
|
235
|
+
return true
|
|
236
|
+
}
|
|
237
|
+
// Not a number, check if it has a valid unit
|
|
238
|
+
val = val.toLowerCase()
|
|
239
|
+
return Object.keys(typeMap_).some((unit) => {
|
|
240
|
+
const re = new RegExp('^-?[\\d\\.]+' + unit + '$')
|
|
241
|
+
return re.test(val)
|
|
242
|
+
})
|
|
243
|
+
}
|
|
244
|
+
if (attr === 'id') {
|
|
245
|
+
// if we're trying to change the id, make sure it's not already present in the doc
|
|
246
|
+
// and the id value is valid.
|
|
247
|
+
|
|
248
|
+
let result = false
|
|
249
|
+
// because getElement() can throw an exception in the case of an invalid id
|
|
250
|
+
// (according to https://www.w3.org/TR/xml-id/ IDs must be a NCName)
|
|
251
|
+
// we wrap it in an exception and only return true if the ID was valid and
|
|
252
|
+
// not already present
|
|
253
|
+
try {
|
|
254
|
+
const elem = elementContainer_.getElement(val)
|
|
255
|
+
result = (!elem || elem === selectedElement)
|
|
256
|
+
} catch (e) { console.error(e) }
|
|
257
|
+
return result
|
|
258
|
+
}
|
|
259
|
+
return true
|
|
260
|
+
}
|
package/utilities.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { NS } from './namespaces.js'
|
|
10
|
-
import { setUnitAttr, getTypeMap } from '
|
|
10
|
+
import { setUnitAttr, getTypeMap } from './units.js'
|
|
11
11
|
import {
|
|
12
12
|
hasMatrixTransform, transformListToTransform, transformBox
|
|
13
13
|
} from './math.js'
|