Merge pull request #693 from SVG-Edit/fixes-#692

fix 692 and some progress on refactoring
master
JFH 2022-01-03 17:36:08 -03:00 committed by GitHub
commit 65119832ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 81 additions and 80 deletions

View File

@ -41,6 +41,9 @@ Thanks to **Netlify**, you can test the following builds:
Additional tip: you may try a version released on NPM using unpkg for example with version 7.1.0:
[https://unpkg.com/svgedit@7.1.0/dist/editor/index.html](https://unpkg.com/svgedit@7.1.0/dist/editor/index.html)
Prior V7 for example with version 3.2.0:
[https://unpkg.com/svgedit@3.2.0/editor/svg-editor.html](https://unpkg.com/svgedit@3.2.0/editor/svg-editor.html)
## Installation
### Quick install

View File

@ -32,6 +32,12 @@ let svgCanvas = null
*/
export const init = (canvas) => {
svgCanvas = canvas
svgCanvas.mouseDownEvent = mouseDownEvent
svgCanvas.mouseMoveEvent = mouseMoveEvent
svgCanvas.dblClickEvent = dblClickEvent
svgCanvas.mouseUpEvent = mouseUpEvent
svgCanvas.mouseOutEvent = mouseOutEvent
svgCanvas.DOMMouseScrollEvent = DOMMouseScrollEvent
}
const getBsplinePoint = (t) => {
@ -96,7 +102,7 @@ const updateTransformList = (svgRoot, element, dx, dy) => {
* @fires module:svgcanvas.SvgCanvas#event:ext_mouseMove
* @returns {void}
*/
export const mouseMoveEvent = (evt) => {
const mouseMoveEvent = (evt) => {
// if the mouse is move without dragging an element, just return.
if (!svgCanvas.getStarted()) { return }
if (evt.button === 1 || svgCanvas.spaceKey) { return }
@ -511,7 +517,7 @@ export const mouseMoveEvent = (evt) => {
break
}
default:
console.error(`unknown mode=${svgCanvas.getCurrentMode()}`)
// A mode can be defined by an extenstion
break
}
@ -536,7 +542,7 @@ export const mouseMoveEvent = (evt) => {
*
* @returns {void}
*/
export const mouseOutEvent = () => {
const mouseOutEvent = () => {
const { $id } = svgCanvas
if (svgCanvas.getCurrentMode() !== 'select' && svgCanvas.getStarted()) {
const event = new Event('mouseup')
@ -557,14 +563,16 @@ export const mouseOutEvent = () => {
* @fires module:svgcanvas.SvgCanvas#event:ext_mouseUp
* @returns {void}
*/
export const mouseUpEvent = (evt) => {
const mouseUpEvent = (evt) => {
if (evt.button === 2) { return }
if (!svgCanvas.getStarted()) { return }
const selectedElements = svgCanvas.getSelectedElements()
const zoom = svgCanvas.getZoom()
const tempJustSelected = svgCanvas.getJustSelected()
svgCanvas.setJustSelected(null)
const pt = transformPoint(evt.clientX, evt.clientY, svgCanvas.getrootSctm())
const mouseX = pt.x * zoom
const mouseY = pt.y * zoom
@ -625,7 +633,7 @@ export const mouseUpEvent = (evt) => {
if (realX !== svgCanvas.getRStartX() || realY !== svgCanvas.getRStartY()) {
const len = selectedElements.length
for (let i = 0; i < len; ++i) {
if (isNullish(selectedElements[i])) { break }
if (!selectedElements[i]) { break }
}
// no change in position/size, so maybe we should move to pathedit
} else {
@ -650,9 +658,7 @@ export const mouseUpEvent = (evt) => {
}
return
case 'zoom': {
if (!isNullish(svgCanvas.getRubberBox())) {
svgCanvas.getRubberBox().setAttribute('display', 'none')
}
svgCanvas.getRubberBox()?.setAttribute('display', 'none')
const factor = evt.shiftKey ? 0.5 : 2
svgCanvas.call('zoomed', {
x: Math.min(svgCanvas.getRStartX(), realX),
@ -809,7 +815,7 @@ export const mouseUpEvent = (evt) => {
}
})
if (!keep && !isNullish(element)) {
if (!keep && element) {
svgCanvas.getCurrentDrawing().releaseId(svgCanvas.getId())
element.remove()
element = null
@ -834,7 +840,7 @@ export const mouseUpEvent = (evt) => {
svgCanvas.setMode('select')
svgCanvas.selectOnly([t], true)
}
} else if (!isNullish(element)) {
} else if (element) {
/**
* @name module:svgcanvas.SvgCanvas#addedNew
* @type {boolean}
@ -885,7 +891,7 @@ export const mouseUpEvent = (evt) => {
svgCanvas.setStartTransform(null)
}
export const dblClickEvent = (evt) => {
const dblClickEvent = (evt) => {
const selectedElements = svgCanvas.getSelectedElements()
const evtTarget = evt.target
const parent = evtTarget.parentNode
@ -935,7 +941,7 @@ export const dblClickEvent = (evt) => {
* @fires module:svgcanvas.SvgCanvas#event:ext_mouseDown
* @returns {void}
*/
export const mouseDownEvent = (evt) => {
const mouseDownEvent = (evt) => {
const dataStorage = svgCanvas.getDataStorage()
const selectedElements = svgCanvas.getSelectedElements()
const zoom = svgCanvas.getZoom()
@ -993,7 +999,7 @@ export const mouseDownEvent = (evt) => {
// if it is a selector grip, then it must be a single element selected,
// set the mouseTarget to that and update the mode to rotate/resize
if (mouseTarget === svgCanvas.selectorManager.selectorParentGroup && !isNullish(selectedElements[0])) {
if (mouseTarget === svgCanvas.selectorManager.selectorParentGroup && selectedElements[0]) {
const grip = evt.target
const griptype = dataStorage.get(grip, 'type')
// rotating
@ -1043,7 +1049,7 @@ export const mouseDownEvent = (evt) => {
// insert a dummy transform so if the element(s) are moved it will have
// a transform to use for its translate
for (const selectedElement of selectedElements) {
if (isNullish(selectedElement)) { continue }
if (!selectedElement) { continue }
const slist = selectedElement.transform?.baseVal
if (slist.numberOfItems) {
slist.insertItemBefore(svgRoot.createSVGTransform(), 0)
@ -1055,7 +1061,7 @@ export const mouseDownEvent = (evt) => {
} else if (!rightClick) {
svgCanvas.clearSelection()
svgCanvas.setCurrentMode('multiselect')
if (isNullish(svgCanvas.getRubberBox())) {
if (!svgCanvas.getRubberBox()) {
svgCanvas.setRubberBox(svgCanvas.selectorManager.getRubberBandBox())
}
svgCanvas.setRStartX(svgCanvas.getRStartX() * zoom)
@ -1304,7 +1310,7 @@ export const mouseDownEvent = (evt) => {
* @fires module:event.SvgCanvas#event:zoomDone
* @returns {void}
*/
export const DOMMouseScrollEvent = (e) => {
const DOMMouseScrollEvent = (e) => {
const zoom = svgCanvas.getZoom()
const { $id } = svgCanvas
if (!e.shiftKey) { return }

View File

@ -255,7 +255,7 @@ export class RemoveElementCommand extends Command {
*/
unapply (handler) {
super.unapply(handler, () => {
if (!this.nextSibling && window.console) {
if (!this.nextSibling) {
console.error('Reference element was lost')
}
this.parent.insertBefore(this.elem, this.nextSibling) // Don't use `before` or `prepend` as `this.nextSibling` may be `null`

View File

@ -10,7 +10,7 @@ import { NS } from './namespaces.js'
import * as hstry from './history.js'
import * as pathModule from './path.js'
import {
isNullish, getStrokedBBoxDefaultVisible, setHref, getElement, getHref, getVisibleElements,
getStrokedBBoxDefaultVisible, setHref, getElement, getHref, getVisibleElements,
findDefs, getRotationAngle, getRefElem, getBBox as utilsGetBBox, walkTreePost, assignAttributes, getFeGaussianBlur
} from './utilities.js'
import {
@ -37,6 +37,19 @@ let svgCanvas = null
*/
export const init = (canvas) => {
svgCanvas = canvas
svgCanvas.copySelectedElements = copySelectedElements
svgCanvas.groupSelectedElements = groupSelectedElements // Wraps all the selected elements in a group (`g`) element.
svgCanvas.pushGroupProperties = pushGroupProperty // Pushes all appropriate parent group properties down to its children
svgCanvas.ungroupSelectedElement = ungroupSelectedElement // Unwraps all the elements in a selected group (`g`) element
svgCanvas.moveToTopSelectedElement = moveToTopSelectedElem // Repositions the selected element to the bottom in the DOM to appear on top
svgCanvas.moveToBottomSelectedElement = moveToBottomSelectedElem // Repositions the selected element to the top in the DOM to appear under other elements
svgCanvas.moveUpDownSelected = moveUpDownSelected // Moves the select element up or down the stack, based on the visibly
svgCanvas.moveSelectedElements = moveSelectedElements // Moves selected elements on the X/Y axis.
svgCanvas.cloneSelectedElements = cloneSelectedElements // Create deep DOM copies (clones) of all selected elements and move them slightly
svgCanvas.alignSelectedElements = alignSelectedElements // Aligns selected elements.
svgCanvas.updateCanvas = updateCanvas // Updates the editor canvas width/height/position after a zoom has occurred.
svgCanvas.cycleElement = cycleElement // Select the next/previous element within the current layer.
svgCanvas.deleteSelectedElements = deleteSelectedElements // Removes all selected elements from the DOM and adds the change to the history
}
/**
@ -46,9 +59,9 @@ export const init = (canvas) => {
* @fires module:selected-elem.SvgCanvas#event:changed
* @returns {void}
*/
export const moveToTopSelectedElem = function () {
const moveToTopSelectedElem = () => {
const [selected] = svgCanvas.getSelectedElements()
if (!isNullish(selected)) {
if (selected) {
const t = selected
const oldParent = t.parentNode
const oldNextSibling = t.nextSibling
@ -69,9 +82,9 @@ export const moveToTopSelectedElem = function () {
* @fires module:selected-elem.SvgCanvas#event:changed
* @returns {void}
*/
export const moveToBottomSelectedElem = function () {
const moveToBottomSelectedElem = () => {
const [selected] = svgCanvas.getSelectedElements()
if (!isNullish(selected)) {
if (selected) {
let t = selected
const oldParent = t.parentNode
const oldNextSibling = t.nextSibling
@ -102,7 +115,7 @@ export const moveToBottomSelectedElem = function () {
* @fires module:selected-elem.SvgCanvas#event:changed
* @returns {void}
*/
export const moveUpDownSelected = function (dir) {
const moveUpDownSelected = (dir) => {
const selectedElements = svgCanvas.getSelectedElements()
const selected = selectedElements[0]
if (!selected) { return }
@ -113,7 +126,7 @@ export const moveUpDownSelected = function (dir) {
const list = svgCanvas.getIntersectionList(getStrokedBBoxDefaultVisible([selected]))
if (dir === 'Down') { list.reverse() }
Array.prototype.forEach.call(list, function (el) {
Array.prototype.forEach.call(list, (el) => {
if (!foundCur) {
if (el === selected) {
foundCur = true
@ -151,7 +164,7 @@ export const moveUpDownSelected = function (dir) {
* @returns {BatchCommand|void} Batch command for the move
*/
export const moveSelectedElements = function (dx, dy, undoable = true) {
const moveSelectedElements = (dx, dy, undoable = true) => {
const selectedElements = svgCanvas.getSelectedElements()
const zoom = svgCanvas.getZoom()
// if undoable is not sent, default to true
@ -206,7 +219,7 @@ export const moveSelectedElements = function (dx, dy, undoable = true) {
* @param {Float} y Float with the distance to move on the y-axis
* @returns {void}
*/
export const cloneSelectedElements = function (x, y) {
const cloneSelectedElements = (x, y) => {
const selectedElements = svgCanvas.getSelectedElements()
const currentGroup = svgCanvas.getCurrentGroup()
let i; let elem
@ -214,7 +227,7 @@ export const cloneSelectedElements = function (x, y) {
// find all the elements selected (stop at first null)
const len = selectedElements.length
function index (el) {
const index = (el) => {
if (!el) return -1
let i = 0
do {
@ -229,13 +242,13 @@ export const cloneSelectedElements = function (x, y) {
* @param {Element} b
* @returns {Integer}
*/
function sortfunction (a, b) {
const sortfunction = (a, b) => {
return (index(b) - index(a))
}
selectedElements.sort(sortfunction)
for (i = 0; i < len; ++i) {
elem = selectedElements[i]
if (isNullish(elem)) { break }
if (!elem) { break }
}
// use slice to quickly get the subset of elements we need
const copiedElements = selectedElements.slice(0, i)
@ -264,7 +277,7 @@ export const cloneSelectedElements = function (x, y) {
* @param {"selected"|"largest"|"smallest"|"page"} relativeTo
* @returns {void}
*/
export const alignSelectedElements = function (type, relativeTo) {
const alignSelectedElements = (type, relativeTo) => {
const selectedElements = svgCanvas.getSelectedElements()
const bboxes = [] // angles = [];
const len = selectedElements.length
@ -273,7 +286,7 @@ export const alignSelectedElements = function (type, relativeTo) {
let miny = Number.MAX_VALUE; let maxy = Number.MIN_VALUE
let curwidth = Number.MIN_VALUE; let curheight = Number.MIN_VALUE
for (let i = 0; i < len; ++i) {
if (isNullish(selectedElements[i])) { break }
if (!selectedElements[i]) { break }
const elem = selectedElements[i]
bboxes[i] = getStrokedBBoxDefaultVisible([elem])
@ -326,7 +339,7 @@ export const alignSelectedElements = function (type, relativeTo) {
const dx = new Array(len)
const dy = new Array(len)
for (let i = 0; i < len; ++i) {
if (isNullish(selectedElements[i])) { break }
if (!selectedElements[i]) { break }
// const elem = selectedElements[i];
const bbox = bboxes[i]
dx[i] = 0
@ -368,7 +381,7 @@ export const alignSelectedElements = function (type, relativeTo) {
* @fires module:selected-elem.SvgCanvas#event:changed
* @returns {void}
*/
export const deleteSelectedElements = function () {
const deleteSelectedElements = () => {
const selectedElements = svgCanvas.getSelectedElements()
const batchCmd = new BatchCommand('Delete Elements')
const len = selectedElements.length
@ -376,7 +389,7 @@ export const deleteSelectedElements = function () {
for (let i = 0; i < len; ++i) {
const selected = selectedElements[i]
if (isNullish(selected)) { break }
if (!selected) { break }
let parent = selected.parentNode
let t = selected
@ -411,7 +424,7 @@ export const deleteSelectedElements = function () {
* @function module:selected-elem.SvgCanvas#copySelectedElements
* @returns {void}
*/
export const copySelectedElements = function () {
const copySelectedElements = () => {
const selectedElements = svgCanvas.getSelectedElements()
const data =
JSON.stringify(selectedElements.map((x) => svgCanvas.getJsonFromSvgElements(x)))
@ -431,7 +444,7 @@ export const copySelectedElements = function () {
* @param {string} [urlArg]
* @returns {void}
*/
export const groupSelectedElements = function (type, urlArg) {
const groupSelectedElements = (type, urlArg) => {
const selectedElements = svgCanvas.getSelectedElements()
if (!type) { type = 'g' }
let cmdStr = ''
@ -467,7 +480,7 @@ export const groupSelectedElements = function (type, urlArg) {
let i = selectedElements.length
while (i--) {
let elem = selectedElements[i]
if (isNullish(elem)) { continue }
if (!elem) { continue }
if (elem.parentNode.tagName === 'a' && elem.parentNode.childNodes.length === 1) {
elem = elem.parentNode
@ -492,7 +505,7 @@ export const groupSelectedElements = function (type, urlArg) {
* @param {boolean} undoable
* @returns {BatchCommand|void}
*/
export const pushGroupProperty = function (g, undoable) {
const pushGroupProperty = (g, undoable) => {
const children = g.childNodes
const len = children.length
const xform = g.getAttribute('transform')
@ -686,7 +699,7 @@ export const pushGroupProperty = function (g, undoable) {
* @fires module:selected-elem.SvgCanvas#event:selected
* @returns {void}
*/
export const convertToGroup = function (elem) {
const convertToGroup = (elem) => {
const selectedElements = svgCanvas.getSelectedElements()
if (!elem) {
elem = selectedElements[0]
@ -807,7 +820,7 @@ export const convertToGroup = function (elem) {
// recalculate dimensions on the top-level children so that unnecessary transforms
// are removed
walkTreePost(g, function (n) {
walkTreePost(g, (n) => {
try {
recalculateDimensions(n)
} catch (e) {
@ -817,7 +830,7 @@ export const convertToGroup = function (elem) {
// Give ID for any visible element missing one
const visElems = g.querySelectorAll(svgCanvas.getVisElems())
Array.prototype.forEach.call(visElems, function (el) {
Array.prototype.forEach.call(visElems, (el) => {
if (!el.id) { el.id = svgCanvas.getNextId() }
})
@ -840,7 +853,7 @@ export const convertToGroup = function (elem) {
* @function module:selected-elem.SvgCanvas#ungroupSelectedElement
* @returns {void}
*/
export const ungroupSelectedElement = function () {
const ungroupSelectedElement = () => {
const selectedElements = svgCanvas.getSelectedElements()
const dataStorage = svgCanvas.getDataStorage()
let g = selectedElements[0]
@ -915,22 +928,22 @@ export const ungroupSelectedElement = function () {
* @fires module:svgcanvas.SvgCanvas#event:ext_canvasUpdated
* @returns {module:svgcanvas.CanvasInfo}
*/
export const updateCanvas = function (w, h) {
const updateCanvas = (w, h) => {
svgCanvas.getSvgRoot().setAttribute('width', w)
svgCanvas.getSvgRoot().setAttribute('height', h)
const zoom = svgCanvas.getZoom()
const bg = document.getElementById('canvasBackground')
const oldX = Number(svgCanvas.getSvgContent().getAttribute('x'))
const oldY = Number(svgCanvas.getSvgContent().getAttribute('y'))
const x = ((w - this.contentW * zoom) / 2)
const y = ((h - this.contentH * zoom) / 2)
const x = ((w - svgCanvas.contentW * zoom) / 2)
const y = ((h - svgCanvas.contentH * zoom) / 2)
assignAttributes(svgCanvas.getSvgContent(), {
width: this.contentW * zoom,
height: this.contentH * zoom,
width: svgCanvas.contentW * zoom,
height: svgCanvas.contentH * zoom,
x,
y,
viewBox: '0 0 ' + this.contentW + ' ' + this.contentH
viewBox: '0 0 ' + svgCanvas.contentW + ' ' + svgCanvas.contentH
})
assignAttributes(bg, {
@ -977,7 +990,7 @@ export const updateCanvas = function (w, h) {
* @fires module:svgcanvas.SvgCanvas#event:selected
* @returns {void}
*/
export const cycleElement = function (next) {
const cycleElement = (next) => {
const selectedElements = svgCanvas.getSelectedElements()
const currentGroup = svgCanvas.getCurrentGroup()
let num
@ -985,7 +998,7 @@ export const cycleElement = function (next) {
let elem = false
const allElems = getVisibleElements(currentGroup || svgCanvas.getCurrentDrawing().getCurrentLayer())
if (!allElems.length) { return }
if (isNullish(curElem)) {
if (!curElem) {
num = next ? allElems.length - 1 : 0
elem = allElems[num]
} else {

View File

@ -30,18 +30,10 @@ import {
import {
init as textActionsInit, textActionsMethod
} from './text-actions.js'
import {
init as eventInit, mouseMoveEvent, mouseUpEvent, mouseOutEvent,
dblClickEvent, mouseDownEvent, DOMMouseScrollEvent
} from './event.js'
import { init as eventInit } from './event.js'
import { init as jsonInit, getJsonFromSvgElements, addSVGElementsFromJson } from './json.js'
import * as elemGetSet from './elem-get-set.js'
import {
init as selectedElemInit, moveToTopSelectedElem, moveToBottomSelectedElem,
moveUpDownSelected, moveSelectedElements, cloneSelectedElements, alignSelectedElements,
deleteSelectedElements, copySelectedElements, groupSelectedElements, pushGroupProperty,
ungroupSelectedElement, cycleElement, updateCanvas
} from './selected-elem.js'
import { init as selectedElemInit } from './selected-elem.js'
import {
init as blurInit, setBlurNoUndo, setBlurOffsets, setBlur
} from './blur-event.js'
@ -249,14 +241,14 @@ class SvgCanvas {
e.preventDefault()
return false
}
container.addEventListener('mousedown', mouseDownEvent)
container.addEventListener('mousemove', mouseMoveEvent)
container.addEventListener('mousedown', this.mouseDownEvent)
container.addEventListener('mousemove', this.mouseMoveEvent)
container.addEventListener('click', handleLinkInCanvas)
container.addEventListener('dblclick', dblClickEvent)
container.addEventListener('mouseup', mouseUpEvent)
container.addEventListener('mouseleave', mouseOutEvent)
container.addEventListener('mousewheel', DOMMouseScrollEvent)
container.addEventListener('DOMMouseScroll', DOMMouseScrollEvent)
container.addEventListener('dblclick', this.dblClickEvent)
container.addEventListener('mouseup', this.mouseUpEvent)
container.addEventListener('mouseleave', this.mouseOutEvent)
container.addEventListener('mousewheel', this.DOMMouseScrollEvent)
container.addEventListener('DOMMouseScroll', this.DOMMouseScrollEvent)
// Alias function
this.linkControlPoints = pathActions.linkControlPoints
@ -886,19 +878,7 @@ class SvgCanvas {
this.prepareSvg = prepareSvg // Runs the SVG Document through the sanitizer and then updates its paths.
this.setRotationAngle = setRotationAngle // Removes any old rotations if present, prepends a new rotation at the transformed center.
this.recalculateAllSelectedDimensions = recalculateAllSelectedDimensions // Runs `recalculateDimensions` on selected elements,adding changes to a single batch command.
this.copySelectedElements = copySelectedElements
this.pasteElements = pasteElementsMethod // Remembers the current selected elements on the clipboard.
this.groupSelectedElements = groupSelectedElements // Wraps all the selected elements in a group (`g`) element.
this.pushGroupProperties = pushGroupProperty // Pushes all appropriate parent group properties down to its children
this.ungroupSelectedElement = ungroupSelectedElement // Unwraps all the elements in a selected group (`g`) element
this.moveToTopSelectedElement = moveToTopSelectedElem // Repositions the selected element to the bottom in the DOM to appear on top
this.moveToBottomSelectedElement = moveToBottomSelectedElem // Repositions the selected element to the top in the DOM to appear under other elements
this.moveUpDownSelected = moveUpDownSelected // Moves the select element up or down the stack, based on the visibly
this.moveSelectedElements = moveSelectedElements // Moves selected elements on the X/Y axis.
this.cloneSelectedElements = cloneSelectedElements // Create deep DOM copies (clones) of all selected elements and move them slightly
this.alignSelectedElements = alignSelectedElements // Aligns selected elements.
this.updateCanvas = updateCanvas // Updates the editor canvas width/height/position after a zoom has occurred.
this.cycleElement = cycleElement // Select the next/previous element within the current layer.
this.getMouseTarget = getMouseTargetMethod
this.removeUnusedDefElems = removeUnusedDefElemsMethod // remove DOM elements inside the `<defs>` if they are notreferred to,
this.svgCanvasToString = svgCanvasToString // Main function to set up the SVG content for output.
@ -954,7 +934,6 @@ class SvgCanvas {
this.setPaint = elemGetSet.setPaintMethod // Set a color/gradient to a fill/stroke.
this.changeSelectedAttributeNoUndo = changeSelectedAttributeNoUndoMethod // This function makes the changes to the elements. It does not add the change to the history stack.
this.changeSelectedAttribute = changeSelectedAttributeMethod // Change the given/selected element and add the original value to the history stack.
this.deleteSelectedElements = deleteSelectedElements // Removes all selected elements from the DOM and adds the change to the history
this.setBlurNoUndo = setBlurNoUndo // Sets the `stdDeviation` blur value on the selected element without being undoable.
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.
this.setBlur = setBlur // Adds/updates the blur filter to the selected element.