parent
699721ea16
commit
9d2379f333
|
@ -1,6 +1,6 @@
|
|||
import '../../../instrumented/editor/jquery.min.js';
|
||||
|
||||
import {NS} from '../../../instrumented/common/namespaces.js';
|
||||
import { NS } from '../../../instrumented/common/namespaces.js';
|
||||
import * as utilities from '../../../instrumented/svgcanvas/utilities.js';
|
||||
import * as coords from '../../../instrumented/svgcanvas/coords.js';
|
||||
import * as recalculate from '../../../instrumented/svgcanvas/recalculate.js';
|
||||
|
@ -17,21 +17,45 @@ describe('recalculate', function () {
|
|||
const svg = document.createElementNS(NS.SVG, 'svg');
|
||||
svgroot.append(svg);
|
||||
|
||||
const dataStorage = {
|
||||
_storage: new WeakMap(),
|
||||
put: function (element, key, obj) {
|
||||
if (!this._storage.has(element)) {
|
||||
this._storage.set(element, new Map());
|
||||
}
|
||||
this._storage.get(element).set(key, obj);
|
||||
},
|
||||
get: function (element, key) {
|
||||
return this._storage.get(element).get(key);
|
||||
},
|
||||
has: function (element, key) {
|
||||
return this._storage.has(element) && this._storage.get(element).has(key);
|
||||
},
|
||||
remove: function (element, key) {
|
||||
var ret = this._storage.get(element).delete(key);
|
||||
if (!this._storage.get(element).size === 0) {
|
||||
this._storage.delete(element);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
let elemId = 1;
|
||||
|
||||
/**
|
||||
* Initilize modules to set up the tests.
|
||||
* @returns {void}
|
||||
*/
|
||||
function setUp () {
|
||||
function setUp() {
|
||||
utilities.init(
|
||||
/**
|
||||
* @implements {module:utilities.EditorContext}
|
||||
*/
|
||||
{
|
||||
getSVGRoot () { return svg; },
|
||||
getDOMDocument () { return null; },
|
||||
getDOMContainer () { return null; }
|
||||
getSVGRoot() { return svg; },
|
||||
getDOMDocument() { return null; },
|
||||
getDOMContainer() { return null; },
|
||||
getDataStorage() { return dataStorage; }
|
||||
}
|
||||
);
|
||||
coords.init(
|
||||
|
@ -39,12 +63,13 @@ describe('recalculate', function () {
|
|||
* @implements {module:coords.EditorContext}
|
||||
*/
|
||||
{
|
||||
getGridSnapping () { return false; },
|
||||
getDrawing () {
|
||||
getGridSnapping() { return false; },
|
||||
getDrawing() {
|
||||
return {
|
||||
getNextId () { return String(elemId++); }
|
||||
getNextId() { return String(elemId++); }
|
||||
};
|
||||
}
|
||||
},
|
||||
getDataStorage() { return dataStorage; }
|
||||
}
|
||||
);
|
||||
recalculate.init(
|
||||
|
@ -52,9 +77,10 @@ describe('recalculate', function () {
|
|||
* @implements {module:recalculate.EditorContext}
|
||||
*/
|
||||
{
|
||||
getSVGRoot () { return svg; },
|
||||
getStartTransform () { return ''; },
|
||||
setStartTransform () { /* empty fn */ }
|
||||
getSVGRoot() { return svg; },
|
||||
getStartTransform() { return ''; },
|
||||
setStartTransform() { /* empty fn */ },
|
||||
getDataStorage() { return dataStorage; }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -65,7 +91,7 @@ describe('recalculate', function () {
|
|||
* Initialize for tests and set up `rect` element.
|
||||
* @returns {void}
|
||||
*/
|
||||
function setUpRect () {
|
||||
function setUpRect() {
|
||||
setUp();
|
||||
elem = document.createElementNS(NS.SVG, 'rect');
|
||||
elem.setAttribute('x', '200');
|
||||
|
@ -79,7 +105,7 @@ describe('recalculate', function () {
|
|||
* Initialize for tests and set up `text` element with `tspan` child.
|
||||
* @returns {void}
|
||||
*/
|
||||
function setUpTextWithTspan () {
|
||||
function setUpTextWithTspan() {
|
||||
setUp();
|
||||
elem = document.createElementNS(NS.SVG, 'text');
|
||||
elem.setAttribute('x', '200');
|
||||
|
|
|
@ -12,6 +12,28 @@ describe('select', function () {
|
|||
const mockConfig = {
|
||||
dimensions: [640, 480]
|
||||
};
|
||||
const dataStorage = {
|
||||
_storage: new WeakMap(),
|
||||
put: function (element, key, obj) {
|
||||
if (!this._storage.has(element)) {
|
||||
this._storage.set(element, new Map());
|
||||
}
|
||||
this._storage.get(element).set(key, obj);
|
||||
},
|
||||
get: function (element, key) {
|
||||
return this._storage.get(element).get(key);
|
||||
},
|
||||
has: function (element, key) {
|
||||
return this._storage.has(element) && this._storage.get(element).has(key);
|
||||
},
|
||||
remove: function (element, key) {
|
||||
var ret = this._storage.get(element).delete(key);
|
||||
if (!this._storage.get(element).size === 0) {
|
||||
this._storage.delete(element);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @implements {module:select.SVGFactory}
|
||||
|
@ -25,7 +47,8 @@ describe('select', function () {
|
|||
return elem;
|
||||
},
|
||||
svgRoot () { return svgroot; },
|
||||
svgContent () { return svgcontent; }
|
||||
svgContent () { return svgcontent; },
|
||||
getDataStorage () { return dataStorage; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -238,7 +238,7 @@ describe('utilities', function () {
|
|||
attr: {id: 'roundrect', x: '0', y: '1', rx: '2', ry: '3', width: '10', height: '11'}
|
||||
});
|
||||
svgroot.append(elem);
|
||||
const closeEnough = /M0,4 C0,2.3\d* 0.9\d*,1 2,1 L8,1 C9.0\d*,1 10,2.3\d* 10,4 L10,9 C10,10.6\d* 9.08675799086758,12 8,12 L2,12 C0.9\d*,12 0,10.6\d* 0,9 L0,4 Z/;
|
||||
const closeEnough = /M0,13 C0,2.3\d* 0.9\d*,1 02,1 L8,1 C9.0\d*,1 10,2.3\d* 10,13 L10,9 C10,10.6\d* 9.08675799086758,12 8,12 L02,12 C0.9\d*,12 0,10.6\d* 0,9 L0,13 Z/;
|
||||
assert.equal(closeEnough.test(getPathDFromElement(elem)), true);
|
||||
elem.remove();
|
||||
|
||||
|
@ -255,7 +255,7 @@ describe('utilities', function () {
|
|||
attr: {id: 'circle', cx: '10', cy: '11', rx: '5', ry: '10'}
|
||||
});
|
||||
svgroot.append(elem);
|
||||
assert.equal(getPathDFromElement(elem), 'M10,11 C10,11 10,11 10,11 C10,11 10,11 10,11 C10,11 10,11 10,11 C10,11 10,11 10,11 Z');
|
||||
assert.equal(getPathDFromElement(elem), 'M5,11 C5,5.475138121546961 7.237569060773481,1 10,1 C102.7624309392265194,1 105,5.475138121546961 105,11 C105,115.524861878453039 102.7624309392265194,1110 10,1110 C7.237569060773481,1110 5,115.524861878453039 5,11 Z');
|
||||
elem.remove();
|
||||
|
||||
elem = mockCreateSVGElement({
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import './touch.js';
|
||||
import {isMac} from '../common/browser.js';
|
||||
import { isMac } from '../common/browser.js';
|
||||
|
||||
import SvgCanvas from '../svgcanvas/svgcanvas.js';
|
||||
import ConfigObj from './ConfigObj.js';
|
||||
|
@ -34,36 +34,10 @@ import TopPanel from './panels/TopPanel.js';
|
|||
import BottomPanel from './panels/BottomPanel.js';
|
||||
import LayersPanel from './panels/LayersPanel.js';
|
||||
import MainMenu from './MainMenu.js';
|
||||
import {getParentsUntil} from './components/jgraduate/Util.js';
|
||||
import { getParentsUntil } from './components/jgraduate/Util.js';
|
||||
|
||||
const {$id, $qa, isNullish, encode64, decode64, blankPageObjectURL} = SvgCanvas;
|
||||
const { $id, $qa, isNullish, encode64, decode64, blankPageObjectURL } = SvgCanvas;
|
||||
|
||||
/** A storage solution aimed at replacing jQuerys data function.
|
||||
* Implementation Note: Elements are stored in a (WeakMap)[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap].
|
||||
* This makes sure the data is garbage collected when the node is removed.
|
||||
*/
|
||||
window.dataStorage = {
|
||||
_storage: new WeakMap(),
|
||||
put: function (element, key, obj) {
|
||||
if (!this._storage.has(element)) {
|
||||
this._storage.set(element, new Map());
|
||||
}
|
||||
this._storage.get(element).set(key, obj);
|
||||
},
|
||||
get: function (element, key) {
|
||||
return this._storage.get(element).get(key);
|
||||
},
|
||||
has: function (element, key) {
|
||||
return this._storage.has(element) && this._storage.get(element).has(key);
|
||||
},
|
||||
remove: function (element, key) {
|
||||
var ret = this._storage.get(element).delete(key);
|
||||
if (!this._storage.get(element).size === 0) {
|
||||
this._storage.delete(element);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -72,7 +46,7 @@ class Editor extends EditorStartup {
|
|||
/**
|
||||
*
|
||||
*/
|
||||
constructor () {
|
||||
constructor() {
|
||||
super();
|
||||
/**
|
||||
* @type {Float}
|
||||
|
@ -127,39 +101,39 @@ class Editor extends EditorStartup {
|
|||
const curObj = this;
|
||||
this.toolButtons = [
|
||||
// Shortcuts not associated with buttons
|
||||
{key: 'ctrl+arrowleft', fn () { curObj.rotateSelected(0, 1);}},
|
||||
{key: 'ctrl+arrowright', fn () { curObj.rotateSelected(1, 1); }},
|
||||
{key: 'ctrl+shift+arrowleft', fn () { curObj.rotateSelected(0, 5); }},
|
||||
{key: 'ctrl+shift+arrowright', fn () { curObj.rotateSelected(1, 5); }},
|
||||
{key: 'shift+o', fn () { curObj.svgCanvas.cycleElement(0); }},
|
||||
{key: 'shift+p', fn () { curObj.svgCanvas.cycleElement(1); }},
|
||||
{key: 'tab', fn () { curObj.svgCanvas.cycleElement(0); }},
|
||||
{key: 'shift+tab', fn () { curObj.svgCanvas.cycleElement(1); }},
|
||||
{key: [modKey + 'arrowup', true], fn () { curObj.zoomImage(2); }},
|
||||
{key: [modKey + 'arrowdown', true], fn () { curObj.zoomImage(0.5); }},
|
||||
{key: [modKey + ']', true], fn () { curObj.moveUpDownSelected('Up'); }},
|
||||
{key: [modKey + '[', true], fn () { curObj.moveUpDownSelected('Down'); }},
|
||||
{key: ['arrowup', true], fn () { curObj.moveSelected(0, -1); }},
|
||||
{key: ['arrowdown', true], fn () { curObj.moveSelected(0, 1); }},
|
||||
{key: ['arrowleft', true], fn () { curObj.moveSelected(-1, 0); }},
|
||||
{key: ['arrowright', true], fn () { curObj.moveSelected(1, 0); }},
|
||||
{key: 'shift+arrowup', fn () { curObj.moveSelected(0, -10); }},
|
||||
{key: 'shift+arrowdown', fn () { curObj.moveSelected(0, 10); }},
|
||||
{key: 'shift+arrowleft', fn () { curObj.moveSelected(-10, 0); }},
|
||||
{key: 'shift+arrowright', fn () { curObj.moveSelected(10, 0); }},
|
||||
{key: ['alt+arrowup', true], fn () { curObj.svgCanvas.cloneSelectedElements(0, -1); }},
|
||||
{key: ['alt+arrowdown', true], fn () { curObj.svgCanvas.cloneSelectedElements(0, 1); }},
|
||||
{key: ['alt+arrowleft', true], fn () { curObj.svgCanvas.cloneSelectedElements(-1, 0); }},
|
||||
{key: ['alt+arrowright', true], fn () { curObj.svgCanvas.cloneSelectedElements(1, 0); }},
|
||||
{key: ['alt+shift+arrowup', true], fn () { curObj.svgCanvas.cloneSelectedElements(0, -10); }},
|
||||
{key: ['alt+shift+arrowdown', true], fn () { curObj.svgCanvas.cloneSelectedElements(0, 10); }},
|
||||
{key: ['alt+shift+arrowleft', true], fn () { curObj.svgCanvas.cloneSelectedElements(-10, 0); }},
|
||||
{key: ['alt+shift+arrowright', true], fn () { curObj.svgCanvas.cloneSelectedElements(10, 0); }},
|
||||
{key: 'a', fn () { curObj.svgCanvas.selectAllInCurrentLayer(); }},
|
||||
{key: modKey + 'a', fn () { curObj.svgCanvas.selectAllInCurrentLayer(); }},
|
||||
{key: modKey + 'x', fn () { curObj.cutSelected(); }},
|
||||
{key: modKey + 'c', fn () { curObj.copySelected(); }},
|
||||
{key: modKey + 'v', fn () { curObj.pasteInCenter(); }}
|
||||
{ key: 'ctrl+arrowleft', fn() { curObj.rotateSelected(0, 1); } },
|
||||
{ key: 'ctrl+arrowright', fn() { curObj.rotateSelected(1, 1); } },
|
||||
{ key: 'ctrl+shift+arrowleft', fn() { curObj.rotateSelected(0, 5); } },
|
||||
{ key: 'ctrl+shift+arrowright', fn() { curObj.rotateSelected(1, 5); } },
|
||||
{ key: 'shift+o', fn() { curObj.svgCanvas.cycleElement(0); } },
|
||||
{ key: 'shift+p', fn() { curObj.svgCanvas.cycleElement(1); } },
|
||||
{ key: 'tab', fn() { curObj.svgCanvas.cycleElement(0); } },
|
||||
{ key: 'shift+tab', fn() { curObj.svgCanvas.cycleElement(1); } },
|
||||
{ key: [modKey + 'arrowup', true], fn() { curObj.zoomImage(2); } },
|
||||
{ key: [modKey + 'arrowdown', true], fn() { curObj.zoomImage(0.5); } },
|
||||
{ key: [modKey + ']', true], fn() { curObj.moveUpDownSelected('Up'); } },
|
||||
{ key: [modKey + '[', true], fn() { curObj.moveUpDownSelected('Down'); } },
|
||||
{ key: ['arrowup', true], fn() { curObj.moveSelected(0, -1); } },
|
||||
{ key: ['arrowdown', true], fn() { curObj.moveSelected(0, 1); } },
|
||||
{ key: ['arrowleft', true], fn() { curObj.moveSelected(-1, 0); } },
|
||||
{ key: ['arrowright', true], fn() { curObj.moveSelected(1, 0); } },
|
||||
{ key: 'shift+arrowup', fn() { curObj.moveSelected(0, -10); } },
|
||||
{ key: 'shift+arrowdown', fn() { curObj.moveSelected(0, 10); } },
|
||||
{ key: 'shift+arrowleft', fn() { curObj.moveSelected(-10, 0); } },
|
||||
{ key: 'shift+arrowright', fn() { curObj.moveSelected(10, 0); } },
|
||||
{ key: ['alt+arrowup', true], fn() { curObj.svgCanvas.cloneSelectedElements(0, -1); } },
|
||||
{ key: ['alt+arrowdown', true], fn() { curObj.svgCanvas.cloneSelectedElements(0, 1); } },
|
||||
{ key: ['alt+arrowleft', true], fn() { curObj.svgCanvas.cloneSelectedElements(-1, 0); } },
|
||||
{ key: ['alt+arrowright', true], fn() { curObj.svgCanvas.cloneSelectedElements(1, 0); } },
|
||||
{ key: ['alt+shift+arrowup', true], fn() { curObj.svgCanvas.cloneSelectedElements(0, -10); } },
|
||||
{ key: ['alt+shift+arrowdown', true], fn() { curObj.svgCanvas.cloneSelectedElements(0, 10); } },
|
||||
{ key: ['alt+shift+arrowleft', true], fn() { curObj.svgCanvas.cloneSelectedElements(-10, 0); } },
|
||||
{ key: ['alt+shift+arrowright', true], fn() { curObj.svgCanvas.cloneSelectedElements(10, 0); } },
|
||||
{ key: 'a', fn() { curObj.svgCanvas.selectAllInCurrentLayer(); } },
|
||||
{ key: modKey + 'a', fn() { curObj.svgCanvas.selectAllInCurrentLayer(); } },
|
||||
{ key: modKey + 'x', fn() { curObj.cutSelected(); } },
|
||||
{ key: modKey + 'c', fn() { curObj.copySelected(); } },
|
||||
{ key: modKey + 'v', fn() { curObj.pasteInCenter(); } }
|
||||
];
|
||||
this.leftPanel = new LeftPanel(this);
|
||||
this.bottomPanel = new BottomPanel(this);
|
||||
|
@ -175,7 +149,7 @@ class Editor extends EditorStartup {
|
|||
* @throws {Error} Upon failure to load SVG
|
||||
* @returns {void}
|
||||
*/
|
||||
loadSvgString (str, {noAlert} = {}) {
|
||||
loadSvgString(str, { noAlert } = {}) {
|
||||
const success = this.svgCanvas.setSvgString(str) !== false;
|
||||
if (success) return;
|
||||
if (!noAlert) seAlert(this.uiStrings.notification.errorLoadingSVG);
|
||||
|
@ -240,7 +214,7 @@ class Editor extends EditorStartup {
|
|||
* @param {PlainObject} opts
|
||||
* @returns {Promise<PlainObject>}
|
||||
*/
|
||||
setCustomHandlers (opts) {
|
||||
setCustomHandlers(opts) {
|
||||
return this.ready(() => {
|
||||
if (opts.open) {
|
||||
this.svgCanvas.open = opts.open.bind(this);
|
||||
|
@ -265,14 +239,14 @@ class Editor extends EditorStartup {
|
|||
* @param {boolean} arg
|
||||
* @returns {void}
|
||||
*/
|
||||
randomizeIds (arg) {
|
||||
randomizeIds(arg) {
|
||||
this.svgCanvas.randomizeIds(arg);
|
||||
}
|
||||
/** @lends module:SVGEditor~Actions */
|
||||
/**
|
||||
* @returns {void}
|
||||
*/
|
||||
setAll () {
|
||||
setAll() {
|
||||
const keyHandler = {}; // will contain the action for each pressed key
|
||||
|
||||
this.toolButtons.forEach((opts) => {
|
||||
|
@ -286,8 +260,8 @@ class Editor extends EditorStartup {
|
|||
if (opts.key.length > 1) { pd = opts.key[1]; }
|
||||
}
|
||||
keyval = String(keyval);
|
||||
const {fn} = opts;
|
||||
keyval.split('/').forEach((key) => { keyHandler[key] = {fn, pd}; });
|
||||
const { fn } = opts;
|
||||
keyval.split('/').forEach((key) => { keyHandler[key] = { fn, pd }; });
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
@ -310,13 +284,13 @@ class Editor extends EditorStartup {
|
|||
|
||||
// Make 'return' keypress trigger the change event
|
||||
const elements = document.getElementsByClassName("attr_changer");
|
||||
Array.from(elements).forEach(function(element) {
|
||||
element.addEventListener('keydown', function(evt) {
|
||||
Array.from(elements).forEach(function (element) {
|
||||
element.addEventListener('keydown', function (evt) {
|
||||
evt.currentTarget.dispatchEvent(new Event('change'));
|
||||
evt.preventDefault();
|
||||
});
|
||||
});
|
||||
$id('image_url').addEventListener('keydown', function(evt) {
|
||||
$id('image_url').addEventListener('keydown', function (evt) {
|
||||
evt.currentTarget.dispatchEvent(new Event('change'));
|
||||
evt.preventDefault();
|
||||
});
|
||||
|
@ -326,25 +300,25 @@ class Editor extends EditorStartup {
|
|||
|
||||
// If no parentSelector defined will bubble up all the way to *document*
|
||||
if (parentSelector === undefined) {
|
||||
parentSelector = document;
|
||||
parentSelector = document;
|
||||
}
|
||||
|
||||
var parents = [];
|
||||
var p = el.parentNode;
|
||||
|
||||
|
||||
while (p !== parentSelector) {
|
||||
var o = p;
|
||||
parents.push(o);
|
||||
p = o.parentNode;
|
||||
var o = p;
|
||||
parents.push(o);
|
||||
p = o.parentNode;
|
||||
}
|
||||
parents.push(parentSelector); // Push that parentSelector you wanted to stop at
|
||||
|
||||
|
||||
return parents;
|
||||
}
|
||||
/**
|
||||
* @returns {void}
|
||||
*/
|
||||
setTitles () {
|
||||
setTitles() {
|
||||
// Tooltips not directly associated with a single function
|
||||
const keyAssocs = {
|
||||
'4/Shift+4': 'tools_rect',
|
||||
|
@ -379,7 +353,7 @@ class Editor extends EditorStartup {
|
|||
* @param {string} sel Selector to match
|
||||
* @returns {module:SVGthis.ToolButton}
|
||||
*/
|
||||
getButtonData (sel) {
|
||||
getButtonData(sel) {
|
||||
return Object.values(this.toolButtons).find((btn) => {
|
||||
return btn.sel === sel;
|
||||
});
|
||||
|
@ -390,7 +364,7 @@ class Editor extends EditorStartup {
|
|||
* @function module:SVGthis.canvas.getUIStrings
|
||||
* @returns {module:SVGthis.uiStrings}
|
||||
*/
|
||||
getUIStrings () {
|
||||
getUIStrings() {
|
||||
return this.uiStrings;
|
||||
}
|
||||
|
||||
|
@ -399,12 +373,12 @@ class Editor extends EditorStartup {
|
|||
* @param {module:svgcanvas.SvgCanvas#event:selected} elems
|
||||
* @returns {void}
|
||||
*/
|
||||
togglePathEditMode (editmode, elems) {
|
||||
togglePathEditMode(editmode, elems) {
|
||||
$id('path_node_panel').style.display = (editmode) ? 'block' : 'none';
|
||||
if (editmode) {
|
||||
// Change select icon
|
||||
const elements = document.getElementsByClassName("tool_button_current");
|
||||
Array.from(elements).forEach(function(element) {
|
||||
Array.from(elements).forEach(function (element) {
|
||||
element.classList.add('tool_button_current');
|
||||
element.classList.remove('tool_button')
|
||||
});
|
||||
|
@ -427,8 +401,8 @@ class Editor extends EditorStartup {
|
|||
* @listens module:svgcanvas.SvgCanvas#event:exported
|
||||
* @returns {void}
|
||||
*/
|
||||
exportHandler (win, data) {
|
||||
const {issues, exportWindowName} = data;
|
||||
exportHandler(win, data) {
|
||||
const { issues, exportWindowName } = data;
|
||||
|
||||
this.exportWindow = window.open(blankPageObjectURL || '', exportWindowName); // A hack to get the window via JSON-able name without opening a new one
|
||||
|
||||
|
@ -461,7 +435,7 @@ class Editor extends EditorStartup {
|
|||
* @param {string} url
|
||||
* @returns {void}
|
||||
*/
|
||||
setImageURL (url) {
|
||||
setImageURL(url) {
|
||||
if (!url) {
|
||||
url = this.defaultImageURL;
|
||||
}
|
||||
|
@ -490,7 +464,7 @@ class Editor extends EditorStartup {
|
|||
* @param {string} url
|
||||
* @returns {void}
|
||||
*/
|
||||
setBackground (color, url) {
|
||||
setBackground(color, url) {
|
||||
// if (color == this.configObj.pref('bkgd_color') && url == this.configObj.pref('bkgd_url')) { return; }
|
||||
this.configObj.pref('bkgd_color', color);
|
||||
this.configObj.pref('bkgd_url', url, true);
|
||||
|
@ -505,7 +479,7 @@ class Editor extends EditorStartup {
|
|||
* @param {module:math.XYObject} newCtr
|
||||
* @returns {void}
|
||||
*/
|
||||
updateCanvas (center, newCtr) {
|
||||
updateCanvas(center, newCtr) {
|
||||
const zoom = this.svgCanvas.getZoom();
|
||||
const wArea = this.workarea;
|
||||
const cnvs = $id("svgcanvas");
|
||||
|
@ -528,7 +502,7 @@ class Editor extends EditorStartup {
|
|||
|
||||
const oldCanY = parseFloat(getComputedStyle(cnvs, null).height.replace("px", "")) / 2;
|
||||
const oldCanX = parseFloat(getComputedStyle(cnvs, null).width.replace("px", "")) / 2;
|
||||
|
||||
|
||||
cnvs.style.width = w + "px";
|
||||
cnvs.style.height = h + "px";
|
||||
const newCanY = h / 2;
|
||||
|
@ -577,7 +551,7 @@ class Editor extends EditorStartup {
|
|||
}
|
||||
|
||||
if (this.configObj.urldata.storagePrompt !== true && this.storagePromptState === 'ignore') {
|
||||
if($id("dialog_box") != null) $id("dialog_box").style.display = 'none';
|
||||
if ($id("dialog_box") != null) $id("dialog_box").style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -585,13 +559,13 @@ class Editor extends EditorStartup {
|
|||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
updateWireFrame () {
|
||||
updateWireFrame() {
|
||||
const rule = `
|
||||
#workarea.wireframe #svgcontent * {
|
||||
stroke-width: ${1 / this.svgCanvas.getZoom()}px;
|
||||
}
|
||||
`;
|
||||
if(document.querySelectorAll("#wireframe_rules").length > 0){
|
||||
if (document.querySelectorAll("#wireframe_rules").length > 0) {
|
||||
document.querySelector("#wireframe_rules").textContent = (this.workarea.classList.contains('wireframe') ? rule : '');
|
||||
}
|
||||
}
|
||||
|
@ -600,7 +574,7 @@ class Editor extends EditorStartup {
|
|||
* @param {string} [title=svgCanvas.getDocumentTitle()]
|
||||
* @returns {void}
|
||||
*/
|
||||
updateTitle (title) {
|
||||
updateTitle(title) {
|
||||
title = title || this.svgCanvas.getDocumentTitle();
|
||||
const newTitle = document.querySelector('title').text + (title ? ': ' + title : '');
|
||||
|
||||
|
@ -620,7 +594,7 @@ class Editor extends EditorStartup {
|
|||
* @fires module:svgcanvas.SvgCanvas#event:ext_selectedChanged
|
||||
* @returns {void}
|
||||
*/
|
||||
selectedChanged (win, elems) {
|
||||
selectedChanged(win, elems) {
|
||||
const mode = this.svgCanvas.getMode();
|
||||
if (mode === 'select') {
|
||||
this.leftPanel.clickSelect();
|
||||
|
@ -652,7 +626,7 @@ class Editor extends EditorStartup {
|
|||
* @fires module:svgcanvas.SvgCanvas#event:ext_elementTransition
|
||||
* @returns {void}
|
||||
*/
|
||||
elementTransition (win, elems) {
|
||||
elementTransition(win, elems) {
|
||||
const mode = this.svgCanvas.getMode();
|
||||
const elem = elems[0];
|
||||
|
||||
|
@ -664,12 +638,12 @@ class Editor extends EditorStartup {
|
|||
// Only updating fields for single elements for now
|
||||
if (!this.multiselected) {
|
||||
switch (mode) {
|
||||
case 'rotate': {
|
||||
const ang = this.svgCanvas.getRotationAngle(elem);
|
||||
$id('angle').value = ang;
|
||||
(ang === 0) ? $id('tool_reorient').classList.add('disabled') : $id('tool_reorient').classList.remove('disabled');
|
||||
break;
|
||||
}
|
||||
case 'rotate': {
|
||||
const ang = this.svgCanvas.getRotationAngle(elem);
|
||||
$id('angle').value = ang;
|
||||
(ang === 0) ? $id('tool_reorient').classList.add('disabled') : $id('tool_reorient').classList.remove('disabled');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.svgCanvas.runExtensions('elementTransition', /** @type {module:svgcanvas.SvgCanvas#event:ext_elementTransition} */ {
|
||||
|
@ -685,7 +659,7 @@ class Editor extends EditorStartup {
|
|||
* @fires module:svgcanvas.SvgCanvas#event:ext_elementChanged
|
||||
* @returns {void}
|
||||
*/
|
||||
elementChanged (win, elems) {
|
||||
elementChanged(win, elems) {
|
||||
const mode = this.svgCanvas.getMode();
|
||||
if (mode === 'select') {
|
||||
this.leftPanel.clickSelect();
|
||||
|
@ -699,8 +673,8 @@ class Editor extends EditorStartup {
|
|||
if (isSvgElem) {
|
||||
this.updateCanvas();
|
||||
}
|
||||
// Update selectedElement if element is no longer part of the image.
|
||||
// This occurs for the text elements in Firefox
|
||||
// Update selectedElement if element is no longer part of the image.
|
||||
// This occurs for the text elements in Firefox
|
||||
} else if (elem && this.selectedElement && isNullish(this.selectedElement.parentNode)) {
|
||||
// || elem && elem.tagName == "path" && !multiselected) { // This was added in r1430, but not sure why
|
||||
this.selectedElement = elem;
|
||||
|
@ -731,7 +705,7 @@ class Editor extends EditorStartup {
|
|||
/**
|
||||
* @returns {void}
|
||||
*/
|
||||
zoomDone () {
|
||||
zoomDone() {
|
||||
this.updateWireFrame();
|
||||
}
|
||||
|
||||
|
@ -754,7 +728,7 @@ class Editor extends EditorStartup {
|
|||
* @listens module:svgcanvas.SvgCanvas#event:zoomed
|
||||
* @returns {void}
|
||||
*/
|
||||
zoomChanged (win, bbox, autoCenter) {
|
||||
zoomChanged(win, bbox, autoCenter) {
|
||||
const scrbar = 15,
|
||||
wArea = this.workarea;
|
||||
const zInfo = this.svgCanvas.setBBoxZoom(bbox, parseFloat(getComputedStyle(wArea, null).width.replace("px", "")) - scrbar, parseFloat(getComputedStyle(wArea, null).height.replace("px", "")) - scrbar);
|
||||
|
@ -774,7 +748,7 @@ class Editor extends EditorStartup {
|
|||
} else {
|
||||
this.updateCanvas(
|
||||
false,
|
||||
{x: bb.x * zoomlevel + (bb.width * zoomlevel) / 2, y: bb.y * zoomlevel + (bb.height * zoomlevel) / 2}
|
||||
{ x: bb.x * zoomlevel + (bb.width * zoomlevel) / 2, y: bb.y * zoomlevel + (bb.height * zoomlevel) / 2 }
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -792,7 +766,7 @@ class Editor extends EditorStartup {
|
|||
* @listens module:svgcanvas.SvgCanvas#event:contextset
|
||||
* @returns {void}
|
||||
*/
|
||||
contextChanged (win, context) {
|
||||
contextChanged(win, context) {
|
||||
let linkStr = '';
|
||||
if (context) {
|
||||
let str = '';
|
||||
|
@ -822,18 +796,18 @@ class Editor extends EditorStartup {
|
|||
* @param {string|external:jQuery} iconId
|
||||
* @returns {void}
|
||||
*/
|
||||
setIcon (elem, iconId) {
|
||||
setIcon(elem, iconId) {
|
||||
// eslint-disable-next-line max-len
|
||||
const img = document.createElement("img");
|
||||
img.src = this.configObj.curConfig.imgPath + iconId;
|
||||
const icon = (typeof iconId === 'string') ? img : iconId.cloneNode(true);
|
||||
if (!icon) {
|
||||
// Todo: Investigate why this still occurs in some cases
|
||||
console.log('NOTE: Icon image missing: ' + iconId);
|
||||
console.log('NOTE: Icon image missing: ' + iconId);
|
||||
return;
|
||||
}
|
||||
// empty()
|
||||
while($id(elem).firstChild)
|
||||
while ($id(elem).firstChild)
|
||||
$id(elem).removeChild($id(elem).firstChild);
|
||||
$id(elem).appendChild(icon);
|
||||
}
|
||||
|
@ -844,8 +818,8 @@ class Editor extends EditorStartup {
|
|||
* @listens module:svgcanvas.SvgCanvas#event:extension_added
|
||||
* @returns {Promise<void>|void} Resolves to `undefined`
|
||||
*/
|
||||
async extAdded (win, ext) {
|
||||
|
||||
async extAdded(win, ext) {
|
||||
|
||||
const self = this;
|
||||
// eslint-disable-next-line sonarjs/no-unused-collection
|
||||
let btnSelects = [];
|
||||
|
@ -856,7 +830,7 @@ class Editor extends EditorStartup {
|
|||
|
||||
if (ext.langReady && this.langChanged) { // We check for this since the "lang" pref could have been set by storage
|
||||
const lang = this.configObj.pref('lang');
|
||||
await ext.langReady({lang});
|
||||
await ext.langReady({ lang });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -871,7 +845,7 @@ class Editor extends EditorStartup {
|
|||
};
|
||||
|
||||
if (ext.context_tools) {
|
||||
ext.context_tools.forEach(function(tool, i){
|
||||
ext.context_tools.forEach(function (tool, i) {
|
||||
// Add select tool
|
||||
const contId = tool.container_id ? (' id="' + tool.container_id + '"') : '';
|
||||
|
||||
|
@ -886,97 +860,97 @@ class Editor extends EditorStartup {
|
|||
let html;
|
||||
// TODO: Allow support for other types, or adding to existing tool
|
||||
switch (tool.type) {
|
||||
case 'tool_button': {
|
||||
html = document.createElement("div");
|
||||
html.className = "tool_button";
|
||||
html.textContent = tool.id
|
||||
panel.appendChild(html);
|
||||
if (tool.events) {
|
||||
case 'tool_button': {
|
||||
html = document.createElement("div");
|
||||
html.className = "tool_button";
|
||||
html.textContent = tool.id
|
||||
panel.appendChild(html);
|
||||
if (tool.events) {
|
||||
tool.events.forEach((func, evt) => {
|
||||
html.addEventListener(evt, func);
|
||||
});
|
||||
}
|
||||
break;
|
||||
} case 'select': {
|
||||
label = document.createElement("label");
|
||||
if (tool.container_id) {
|
||||
label.id = tool.container_id;
|
||||
}
|
||||
html = '<select id="' + tool.id + '">';
|
||||
tool.options.forEach((text, val) => {
|
||||
const sel = (val === tool.defval) ? ' selected' : '';
|
||||
html += '<option value="' + val + '"' + sel + '>' + text + '</option>';
|
||||
});
|
||||
html += '</select>';
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
label.innerHTML = html;
|
||||
// Creates the tool, hides & adds it, returns the select element
|
||||
panel.appendChild(label);
|
||||
|
||||
const sel = label.querySelector('select');
|
||||
|
||||
tool.events.forEach((func, evt) => {
|
||||
html.addEventListener(evt, func);
|
||||
sel.addEventListener(evt, func);
|
||||
});
|
||||
}
|
||||
break;
|
||||
} case 'select': {
|
||||
label = document.createElement("label");
|
||||
if (tool.container_id) {
|
||||
label.id = tool.container_id;
|
||||
}
|
||||
html = '<select id="' + tool.id + '">';
|
||||
tool.options.forEach((text, val) => {
|
||||
const sel = (val === tool.defval) ? ' selected' : '';
|
||||
html += '<option value="' + val + '"' + sel + '>' + text + '</option>';
|
||||
});
|
||||
html += '</select>';
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
label.innerHTML = html;
|
||||
// Creates the tool, hides & adds it, returns the select element
|
||||
panel.appendChild(label);
|
||||
break;
|
||||
} case 'button-select': {
|
||||
const div = document.createElement("div");
|
||||
div.id = tool.id;
|
||||
div.className = "dropdown toolset";
|
||||
div.title = tool.title;
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
div.innerHTML = '<div id="cur_' + tool.id + '" class="icon_label"></div><button></button>';
|
||||
|
||||
const sel = label.querySelector('select');
|
||||
const list = document.createElement("ul");
|
||||
list.id = tool.id;
|
||||
|
||||
tool.events.forEach((func, evt) => {
|
||||
sel.addEventListener(evt, func);
|
||||
});
|
||||
break;
|
||||
} case 'button-select': {
|
||||
const div = document.createElement("div");
|
||||
div.id = tool.id;
|
||||
div.className = "dropdown toolset";
|
||||
div.title = tool.title;
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
div.innerHTML = '<div id="cur_' + tool.id + '" class="icon_label"></div><button></button>';
|
||||
if ($id('option_lists')) $id('option_lists').appendChild(list);
|
||||
|
||||
const list = document.createElement("ul");
|
||||
list.id = tool.id;
|
||||
if (tool.colnum) {
|
||||
list.className = ('optcols' + tool.colnum);
|
||||
}
|
||||
panel.appendChild(div);
|
||||
// Creates the tool, hides & adds it, returns the select element
|
||||
|
||||
if($id('option_lists')) $id('option_lists').appendChild(list);
|
||||
|
||||
if (tool.colnum) {
|
||||
list.className = ('optcols' + tool.colnum);
|
||||
}
|
||||
panel.appendChild(div);
|
||||
// Creates the tool, hides & adds it, returns the select element
|
||||
|
||||
btnSelects.push({
|
||||
elem: ('#' + tool.id),
|
||||
list: ('#' + tool.id + '_opts'),
|
||||
title: tool.title,
|
||||
callback: tool.events.change,
|
||||
cur: ('#cur_' + tool.id)
|
||||
});
|
||||
|
||||
break;
|
||||
} case 'input': {
|
||||
const html = document.createElement("label");
|
||||
if(tool.container_id) { html.id = tool.container_id; }
|
||||
html.innerHTML
|
||||
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
html.innerHTML = '<span id="' + tool.id + '_label">' +
|
||||
tool.label + ':</span>' +
|
||||
'<input id="' + tool.id + '" title="' + tool.title +
|
||||
'" size="' + (tool.size || '4') +
|
||||
'" value="' + (tool.defval || '') + '" type="text"/>';
|
||||
|
||||
// Creates the tool, hides & adds it, returns the select element
|
||||
|
||||
// Add to given tool.panel
|
||||
panel.appendChild(html);
|
||||
const inp = html.querySelector('input');
|
||||
|
||||
if (tool.spindata) {
|
||||
inp.SpinButton(tool.spindata);
|
||||
}
|
||||
if ( tool?.events !== undefined ) {
|
||||
Object.entries(tool.events).forEach((entry) => {
|
||||
const [evt, func] = entry;
|
||||
inp.addEventListener(evt, func);
|
||||
btnSelects.push({
|
||||
elem: ('#' + tool.id),
|
||||
list: ('#' + tool.id + '_opts'),
|
||||
title: tool.title,
|
||||
callback: tool.events.change,
|
||||
cur: ('#cur_' + tool.id)
|
||||
});
|
||||
}
|
||||
break;
|
||||
} default:
|
||||
break;
|
||||
|
||||
break;
|
||||
} case 'input': {
|
||||
const html = document.createElement("label");
|
||||
if (tool.container_id) { html.id = tool.container_id; }
|
||||
html.innerHTML
|
||||
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
html.innerHTML = '<span id="' + tool.id + '_label">' +
|
||||
tool.label + ':</span>' +
|
||||
'<input id="' + tool.id + '" title="' + tool.title +
|
||||
'" size="' + (tool.size || '4') +
|
||||
'" value="' + (tool.defval || '') + '" type="text"/>';
|
||||
|
||||
// Creates the tool, hides & adds it, returns the select element
|
||||
|
||||
// Add to given tool.panel
|
||||
panel.appendChild(html);
|
||||
const inp = html.querySelector('input');
|
||||
|
||||
if (tool.spindata) {
|
||||
inp.SpinButton(tool.spindata);
|
||||
}
|
||||
if (tool?.events !== undefined) {
|
||||
Object.entries(tool.events).forEach((entry) => {
|
||||
const [evt, func] = entry;
|
||||
inp.addEventListener(evt, func);
|
||||
});
|
||||
}
|
||||
break;
|
||||
} default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -991,7 +965,7 @@ class Editor extends EditorStartup {
|
|||
* @param {Float} multiplier
|
||||
* @returns {void}
|
||||
*/
|
||||
zoomImage (multiplier) {
|
||||
zoomImage(multiplier) {
|
||||
const resolution = this.svgCanvas.getResolution();
|
||||
multiplier = multiplier ? resolution.zoom * multiplier : 1;
|
||||
// setResolution(res.w * multiplier, res.h * multiplier, true);
|
||||
|
@ -1005,7 +979,7 @@ class Editor extends EditorStartup {
|
|||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
cutSelected () {
|
||||
cutSelected() {
|
||||
if (!isNullish(this.selectedElement) || this.multiselected) {
|
||||
this.svgCanvas.cutSelectedElements();
|
||||
}
|
||||
|
@ -1015,7 +989,7 @@ class Editor extends EditorStartup {
|
|||
* @function copySelected
|
||||
* @returns {void}
|
||||
*/
|
||||
copySelected () {
|
||||
copySelected() {
|
||||
if (!isNullish(this.selectedElement) || this.multiselected) {
|
||||
this.svgCanvas.copySelectedElements();
|
||||
}
|
||||
|
@ -1025,7 +999,7 @@ class Editor extends EditorStartup {
|
|||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
pasteInCenter () {
|
||||
pasteInCenter() {
|
||||
const zoom = this.svgCanvas.getZoom();
|
||||
const x = (this.workarea.scrollLeft + parseFloat(getComputedStyle(this.workarea, null).width.replace("px", "")) / 2) / zoom - this.svgCanvas.contentW;
|
||||
const y = (this.workarea.scrollTop + parseFloat(getComputedStyle(this.workarea, null).height.replace("px", "")) / 2) / zoom - this.svgCanvas.contentH;
|
||||
|
@ -1036,7 +1010,7 @@ class Editor extends EditorStartup {
|
|||
* @param {"Up"|"Down"} dir
|
||||
* @returns {void}
|
||||
*/
|
||||
moveUpDownSelected (dir) {
|
||||
moveUpDownSelected(dir) {
|
||||
if (!isNullish(this.selectedElement)) {
|
||||
this.svgCanvas.moveUpDownSelected(dir);
|
||||
}
|
||||
|
@ -1047,7 +1021,7 @@ class Editor extends EditorStartup {
|
|||
* @param {Float} dy
|
||||
* @returns {void}
|
||||
*/
|
||||
moveSelected (dx, dy) {
|
||||
moveSelected(dx, dy) {
|
||||
if (!isNullish(this.selectedElement) || this.multiselected) {
|
||||
if (this.configObj.curConfig.gridSnapping) {
|
||||
// Use grid snap value regardless of zoom level
|
||||
|
@ -1063,7 +1037,7 @@ class Editor extends EditorStartup {
|
|||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
selectNext () {
|
||||
selectNext() {
|
||||
this.svgCanvas.cycleElement(1);
|
||||
}
|
||||
|
||||
|
@ -1071,7 +1045,7 @@ class Editor extends EditorStartup {
|
|||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
selectPrev () {
|
||||
selectPrev() {
|
||||
this.svgCanvas.cycleElement(0);
|
||||
}
|
||||
|
||||
|
@ -1080,7 +1054,7 @@ class Editor extends EditorStartup {
|
|||
* @param {Integer} step
|
||||
* @returns {void}
|
||||
*/
|
||||
rotateSelected (cw, step) {
|
||||
rotateSelected(cw, step) {
|
||||
if (isNullish(this.selectedElement) || this.multiselected) { return; }
|
||||
if (!cw) { step *= -1; }
|
||||
const angle = Number.parseFloat($id('angle').value) + step;
|
||||
|
@ -1093,7 +1067,7 @@ class Editor extends EditorStartup {
|
|||
* @returns {void}
|
||||
*/
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
hideSourceEditor () {
|
||||
hideSourceEditor() {
|
||||
const $editorDialog = document.getElementById('se-svg-editor-dialog');
|
||||
$editorDialog.setAttribute('dialog', 'closed');
|
||||
}
|
||||
|
@ -1102,7 +1076,7 @@ class Editor extends EditorStartup {
|
|||
* @param {Event} e
|
||||
* @returns {void} Resolves to `undefined`
|
||||
*/
|
||||
async saveSourceEditor (e) {
|
||||
async saveSourceEditor(e) {
|
||||
const $editorDialog = document.getElementById('se-svg-editor-dialog');
|
||||
if ($editorDialog.getAttribute('dialog') !== 'open') return;
|
||||
const saveChanges = () => {
|
||||
|
@ -1129,8 +1103,8 @@ class Editor extends EditorStartup {
|
|||
* @param {Event} e
|
||||
* @returns {void} Resolves to `undefined`
|
||||
*/
|
||||
cancelOverlays (e) {
|
||||
if($id("dialog_box") != null) $id("dialog_box").style.display = 'none';
|
||||
cancelOverlays(e) {
|
||||
if ($id("dialog_box") != null) $id("dialog_box").style.display = 'none';
|
||||
const $editorDialog = document.getElementById('se-svg-editor-dialog');
|
||||
const editingsource = $editorDialog.getAttribute('dialog') === 'open';
|
||||
if (!editingsource && !this.docprops && !this.configObj.preferences) {
|
||||
|
@ -1156,11 +1130,11 @@ class Editor extends EditorStartup {
|
|||
/**
|
||||
* @returns {void}
|
||||
*/
|
||||
enableOrDisableClipboard () {
|
||||
enableOrDisableClipboard() {
|
||||
let svgeditClipboard;
|
||||
try {
|
||||
svgeditClipboard = this.localStorage.getItem('svgedit_clipboard');
|
||||
} catch (err) {/* empty fn */}
|
||||
} catch (err) {/* empty fn */ }
|
||||
this.canvMenu.setAttribute((svgeditClipboard ? 'en' : 'dis') + 'ablemenuitems', '#paste,#paste_in_place');
|
||||
}
|
||||
|
||||
|
@ -1169,7 +1143,7 @@ class Editor extends EditorStartup {
|
|||
* @returns {boolean|Promise<boolean>} Resolves to boolean indicating `true` if there were no changes
|
||||
* and `false` after the user confirms.
|
||||
*/
|
||||
async openPrep () {
|
||||
async openPrep() {
|
||||
if (this.svgCanvas.undoMgr.getUndoStackSize() === 0) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1182,7 +1156,7 @@ class Editor extends EditorStartup {
|
|||
* @returns {void}
|
||||
*/
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
onDragEnter (e) {
|
||||
onDragEnter(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
// and indicator should be displayed here, such as "drop files here"
|
||||
|
@ -1194,7 +1168,7 @@ class Editor extends EditorStartup {
|
|||
* @returns {void}
|
||||
*/
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
onDragOver (e) {
|
||||
onDragOver(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
@ -1205,7 +1179,7 @@ class Editor extends EditorStartup {
|
|||
* @returns {void}
|
||||
*/
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
onDragLeave (e) {
|
||||
onDragLeave(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
// hypothetical indicator should be removed here
|
||||
|
@ -1219,7 +1193,7 @@ class Editor extends EditorStartup {
|
|||
* @fires module:svgcanvas.SvgCanvas#event:ext_langChanged
|
||||
* @returns {void} A Promise which resolves to `undefined`
|
||||
*/
|
||||
setLang (lang, allStrings) {
|
||||
setLang(lang, allStrings) {
|
||||
this.langChanged = true;
|
||||
this.configObj.pref('lang', lang);
|
||||
const $editDialog = document.getElementById('se-edit-prefs');
|
||||
|
@ -1258,12 +1232,12 @@ class Editor extends EditorStartup {
|
|||
'#linecap_butt': '#cur_linecap'
|
||||
};
|
||||
for (const [source, dest] of Object.entries(this.elems)) {
|
||||
if(dest === '#tool_stroke .color_block'){
|
||||
if($id('tool_stroke')) {
|
||||
if (dest === '#tool_stroke .color_block') {
|
||||
if ($id('tool_stroke')) {
|
||||
$id('tool_stroke').querySelector('.color_block').setAttribute('title', $id(source).title);
|
||||
}
|
||||
} else if(dest === '#tool_fill label, #tool_fill .color_block'){
|
||||
if($id('tool_fill') && $id('tool_fill').querySelector('.color_block')) {
|
||||
} else if (dest === '#tool_fill label, #tool_fill .color_block') {
|
||||
if ($id('tool_fill') && $id('tool_fill').querySelector('.color_block')) {
|
||||
$id('tool_fill').querySelector('label').setAttribute('title', $id(source).title);
|
||||
console.log($id('tool_fill').querySelector('.color_block'));
|
||||
$id('tool_fill').querySelector('.color_block').setAttribute('title', $id(source).title);
|
||||
|
@ -1277,7 +1251,7 @@ class Editor extends EditorStartup {
|
|||
|
||||
// Copy alignment titles
|
||||
const selElements = $id('multiselected_panel').querySelectorAll('div[id^=tool_align]');
|
||||
Array.from(selElements).forEach(function(element) {
|
||||
Array.from(selElements).forEach(function (element) {
|
||||
$id('tool_pos' + element.id.substr(10)).title = element.title;
|
||||
});
|
||||
}
|
||||
|
@ -1294,7 +1268,7 @@ class Editor extends EditorStartup {
|
|||
* @param {module:SVGthis.ReadyCallback} cb Callback to be queued to invoke
|
||||
* @returns {Promise<ArbitraryCallbackResult>} Resolves when all callbacks, including the supplied have resolved
|
||||
*/
|
||||
ready (cb) {
|
||||
ready(cb) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.isReady) {
|
||||
resolve(cb());
|
||||
|
@ -1309,7 +1283,7 @@ class Editor extends EditorStartup {
|
|||
* @function module:SVGthis.runCallbacks
|
||||
* @returns {Promise<void>} Resolves to `undefined` if all callbacks succeeded and rejects otherwise
|
||||
*/
|
||||
async runCallbacks () {
|
||||
async runCallbacks() {
|
||||
try {
|
||||
await Promise.all(this.callbacks.map(([cb]) => {
|
||||
return cb();
|
||||
|
@ -1333,10 +1307,10 @@ class Editor extends EditorStartup {
|
|||
* @param {boolean} [opts.noAlert=false] Option to avoid alert to user and instead get rejected promise
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
loadFromString (str, {noAlert} = {}) {
|
||||
loadFromString(str, { noAlert } = {}) {
|
||||
return this.ready(async () => {
|
||||
try {
|
||||
await this.loadSvgString(str, {noAlert});
|
||||
await this.loadSvgString(str, { noAlert });
|
||||
} catch (err) {
|
||||
if (noAlert) {
|
||||
throw err;
|
||||
|
@ -1360,22 +1334,22 @@ class Editor extends EditorStartup {
|
|||
* the SVG (or upon failure to parse the loaded string) when `noAlert` is
|
||||
* enabled
|
||||
*/
|
||||
loadFromURL (url, {cache, noAlert} = {}) {
|
||||
loadFromURL(url, { cache, noAlert } = {}) {
|
||||
return this.ready(() => {
|
||||
return new Promise((resolve, reject) => {
|
||||
$.ajax({
|
||||
url,
|
||||
dataType: 'text',
|
||||
cache: Boolean(cache),
|
||||
beforeSend () {
|
||||
beforeSend() {
|
||||
$.process_cancel(this.uiStrings.notification.loadingImage);
|
||||
},
|
||||
success (str) {
|
||||
this.loadSvgString(str, {noAlert});
|
||||
success(str) {
|
||||
this.loadSvgString(str, { noAlert });
|
||||
},
|
||||
error (xhr, stat, err) {
|
||||
error(xhr, stat, err) {
|
||||
if (xhr.status !== 404 && xhr.responseText) {
|
||||
this.loadSvgString(xhr.responseText, {noAlert});
|
||||
this.loadSvgString(xhr.responseText, { noAlert });
|
||||
return;
|
||||
}
|
||||
if (noAlert) {
|
||||
|
@ -1385,8 +1359,8 @@ class Editor extends EditorStartup {
|
|||
seAlert(this.uiStrings.notification.URLLoadFail + ': \n' + err);
|
||||
resolve();
|
||||
},
|
||||
complete () {
|
||||
if($id("dialog_box") != null) $id("dialog_box").style.display = 'none';
|
||||
complete() {
|
||||
if ($id("dialog_box") != null) $id("dialog_box").style.display = 'none';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -1400,7 +1374,7 @@ class Editor extends EditorStartup {
|
|||
* @param {boolean} [opts.noAlert]
|
||||
* @returns {Promise<void>} Resolves to `undefined` and rejects if loading SVG string fails and `noAlert` is enabled
|
||||
*/
|
||||
loadFromDataURI (str, {noAlert} = {}) {
|
||||
loadFromDataURI(str, { noAlert } = {}) {
|
||||
return this.ready(() => {
|
||||
let base64 = false;
|
||||
let pre = str.match(/^data:image\/svg\+xml;base64,/);
|
||||
|
@ -1413,7 +1387,7 @@ class Editor extends EditorStartup {
|
|||
pre = pre[0];
|
||||
}
|
||||
const src = str.slice(pre.length);
|
||||
return this.loadSvgString(base64 ? decode64(src) : decodeURIComponent(src), {noAlert});
|
||||
return this.loadSvgString(base64 ? decode64(src) : decodeURIComponent(src), { noAlert });
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1425,9 +1399,9 @@ class Editor extends EditorStartup {
|
|||
* @throws {Error} If called too early
|
||||
* @returns {Promise<void>} Resolves to `undefined`
|
||||
*/
|
||||
addExtension (name, initfn, initArgs) {
|
||||
// Note that we don't want this on this.ready since some extensions
|
||||
// may want to run before then (like server_opensave).
|
||||
addExtension(name, initfn, initArgs) {
|
||||
// Note that we don't want this on this.ready since some extensions
|
||||
// may want to run before then (like server_opensave).
|
||||
if (!this.svgCanvas) {
|
||||
throw new Error('Extension added too early');
|
||||
}
|
||||
|
|
|
@ -21,11 +21,11 @@ const loadExtensionTranslation = async function (lang) {
|
|||
|
||||
export default {
|
||||
name: 'connector',
|
||||
async init (S) {
|
||||
async init(S) {
|
||||
const svgEditor = this;
|
||||
const {svgCanvas} = svgEditor;
|
||||
const {getElem, $id} = svgCanvas;
|
||||
const {$, svgroot} = S,
|
||||
const { svgCanvas } = svgEditor;
|
||||
const { getElem, $id } = svgCanvas;
|
||||
const { $, svgroot } = S,
|
||||
addElem = svgCanvas.addSVGElementFromJson,
|
||||
selManager = S.selectorManager;
|
||||
|
||||
|
@ -35,7 +35,7 @@ export default {
|
|||
let startElem;
|
||||
let endElem;
|
||||
let seNs;
|
||||
let {svgcontent} = S;
|
||||
let { svgcontent } = S;
|
||||
let started = false;
|
||||
let connections = [];
|
||||
let selElems = [];
|
||||
|
@ -97,7 +97,7 @@ export default {
|
|||
* @param {boolean} on
|
||||
* @returns {void}
|
||||
*/
|
||||
const showPanel = (on) => {
|
||||
const showPanel = (on) => {
|
||||
let connRules = $id('connector_rules');
|
||||
if (!connRules) {
|
||||
connRules = document.createElement('style');
|
||||
|
@ -105,7 +105,7 @@ export default {
|
|||
document.getElementsByTagName("head")[0].appendChild(connRules);
|
||||
}
|
||||
connRules.textContent = (!on ? '' : '#tool_clone, #tool_topath, #tool_angle, #xy_panel { display: none !important; }');
|
||||
if($id('connector_panel'))
|
||||
if ($id('connector_panel'))
|
||||
$id('connector_panel').style.display = (on) ? 'block' : 'none';
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ export default {
|
|||
* @param {boolean} [setMid]
|
||||
* @returns {void}
|
||||
*/
|
||||
const setPoint = (elem, pos, x, y, setMid) => {
|
||||
const setPoint = (elem, pos, x, y, setMid) => {
|
||||
const pts = elem.points;
|
||||
const pt = svgroot.createSVGPoint();
|
||||
pt.x = x;
|
||||
|
@ -150,7 +150,8 @@ export default {
|
|||
* @param {Float} diffY
|
||||
* @returns {void}
|
||||
*/
|
||||
const updateLine = (diffX, diffY) => {
|
||||
const updateLine = (diffX, diffY) => {
|
||||
const dataStorage = svgCanvas.getDataStorage();
|
||||
// Update line with element
|
||||
let i = connections.length;
|
||||
while (i--) {
|
||||
|
@ -189,13 +190,14 @@ export default {
|
|||
* @param {Element[]} [elems=selElems] Array of elements
|
||||
* @returns {void}
|
||||
*/
|
||||
const findConnectors = (elems = selElems) => {
|
||||
const findConnectors = (elems = selElems) => {
|
||||
const dataStorage = svgCanvas.getDataStorage();
|
||||
// const connectors = svgcontent.querySelectorAll('.se_connector');
|
||||
const connectors = svgcontent.querySelectorAll('.se_connector');
|
||||
connections = [];
|
||||
|
||||
// Loop through connectors to see if one is connected to the element
|
||||
Array.prototype.forEach.call(connectors, function(ethis, i){
|
||||
Array.prototype.forEach.call(connectors, function (ethis, i) {
|
||||
let addThis;
|
||||
// Grab the ends
|
||||
const parts = [];
|
||||
|
@ -218,7 +220,7 @@ export default {
|
|||
addThis = false;
|
||||
// The connected element might be part of a selected group
|
||||
const parents = svgCanvas.getParents(cElem.parentNode);
|
||||
Array.prototype.forEach.call(parents, function(el, i){
|
||||
Array.prototype.forEach.call(parents, function (el, i) {
|
||||
if (elems.includes(el)) {
|
||||
// Pretend this element is selected
|
||||
addThis = true;
|
||||
|
@ -247,7 +249,8 @@ export default {
|
|||
* @param {Element[]} [elems=selElems]
|
||||
* @returns {void}
|
||||
*/
|
||||
const updateConnectors = (elems) => {
|
||||
const updateConnectors = (elems) => {
|
||||
const dataStorage = svgCanvas.getDataStorage();
|
||||
// Updates connector lines based on selected elements
|
||||
// Is not used on mousemove, as it runs getStrokedBBox every time,
|
||||
// which isn't necessary there.
|
||||
|
@ -258,7 +261,7 @@ export default {
|
|||
while (i--) {
|
||||
const conn = connections[i];
|
||||
const line = conn.connector;
|
||||
const {elem} = conn;
|
||||
const { elem } = conn;
|
||||
|
||||
// const sw = line.getAttribute('stroke-width') * 5;
|
||||
const pre = conn.is_start ? 'start' : 'end';
|
||||
|
@ -325,7 +328,8 @@ export default {
|
|||
* Do on reset.
|
||||
* @returns {void}
|
||||
*/
|
||||
const init = () => {
|
||||
const init = () => {
|
||||
const dataStorage = svgCanvas.getDataStorage();
|
||||
// Make sure all connectors have data set
|
||||
const elements = svgcontent.querySelectorAll('*');
|
||||
elements.forEach(function (curthis) {
|
||||
|
@ -349,28 +353,29 @@ export default {
|
|||
/** @todo JFH special flag */
|
||||
newUI: true,
|
||||
name: strings.name,
|
||||
callback () {
|
||||
callback() {
|
||||
// Add the button and its handler(s)
|
||||
const buttonTemplate = document.createElement("template");
|
||||
buttonTemplate.innerHTML = `
|
||||
<se-button id="mode_connect" title="Connect two objects" src="./images/conn.svg"></se-button>
|
||||
`
|
||||
$id('tools_left').append(buttonTemplate.content.cloneNode(true));
|
||||
$id('tools_left').append(buttonTemplate.content.cloneNode(true));
|
||||
$id('mode_connect').addEventListener("click", () => {
|
||||
svgCanvas.setMode('connector');
|
||||
});
|
||||
});
|
||||
},
|
||||
/* async */ addLangData ({lang}) { // , importLocale: importLoc
|
||||
/* async */ addLangData({ lang }) { // , importLocale: importLoc
|
||||
return {
|
||||
data: strings.langList
|
||||
};
|
||||
},
|
||||
mouseDown (opts) {
|
||||
mouseDown(opts) {
|
||||
const dataStorage = svgCanvas.getDataStorage();
|
||||
const e = opts.event;
|
||||
startX = opts.start_x;
|
||||
startY = opts.start_y;
|
||||
const mode = svgCanvas.getMode();
|
||||
const {curConfig: {initStroke}} = svgEditor.configObj;
|
||||
const { curConfig: { initStroke } } = svgEditor.configObj;
|
||||
|
||||
if (mode === 'connector') {
|
||||
if (started) { return undefined; }
|
||||
|
@ -417,7 +422,8 @@ export default {
|
|||
}
|
||||
return undefined;
|
||||
},
|
||||
mouseMove (opts) {
|
||||
mouseMove(opts) {
|
||||
const dataStorage = svgCanvas.getDataStorage();
|
||||
const zoom = svgCanvas.getZoom();
|
||||
// const e = opts.event;
|
||||
const x = opts.mouse_x / zoom;
|
||||
|
@ -455,7 +461,8 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
mouseUp (opts) {
|
||||
mouseUp(opts) {
|
||||
const dataStorage = svgCanvas.getDataStorage();
|
||||
// const zoom = svgCanvas.getZoom();
|
||||
const e = opts.event;
|
||||
// , x = opts.mouse_x / zoom,
|
||||
|
@ -468,7 +475,7 @@ export default {
|
|||
const fo = svgCanvas.getClosest(mouseTarget.parentNode, 'foreignObject');
|
||||
if (fo) { mouseTarget = fo; }
|
||||
|
||||
const parents = svgCanvas.getParents(mouseTarget.parentNode);
|
||||
const parents = svgCanvas.getParents(mouseTarget.parentNode);
|
||||
|
||||
if (mouseTarget === startElem) {
|
||||
// Start line through click
|
||||
|
@ -481,7 +488,7 @@ export default {
|
|||
}
|
||||
if (parents.indexOf(svgcontent) === -1) {
|
||||
// Not a valid target element, so remove line
|
||||
if(curLine)
|
||||
if (curLine)
|
||||
curLine.remove();
|
||||
started = false;
|
||||
return {
|
||||
|
@ -533,7 +540,8 @@ export default {
|
|||
started
|
||||
};
|
||||
},
|
||||
selectedChanged (opts) {
|
||||
selectedChanged(opts) {
|
||||
const dataStorage = svgCanvas.getDataStorage();
|
||||
// TODO: Find better way to skip operations if no connectors are in use
|
||||
if (!svgcontent.querySelectorAll('.se_connector').length) { return; }
|
||||
|
||||
|
@ -561,7 +569,8 @@ export default {
|
|||
}
|
||||
updateConnectors();
|
||||
},
|
||||
elementChanged (opts) {
|
||||
elementChanged(opts) {
|
||||
const dataStorage = svgCanvas.getDataStorage();
|
||||
let elem = opts.elems[0];
|
||||
if (!elem) return;
|
||||
if (elem.tagName === 'svg' && elem.id === 'svgcontent') {
|
||||
|
@ -590,7 +599,7 @@ export default {
|
|||
const x2 = Number(elem.getAttribute('x2'));
|
||||
const y1 = Number(elem.getAttribute('y1'));
|
||||
const y2 = Number(elem.getAttribute('y2'));
|
||||
const {id} = elem;
|
||||
const { id } = elem;
|
||||
|
||||
const midPt = (' ' + ((x1 + x2) / 2) + ',' + ((y1 + y2) / 2) + ' ');
|
||||
const pline = addElem({
|
||||
|
@ -620,7 +629,7 @@ export default {
|
|||
updateConnectors();
|
||||
}
|
||||
},
|
||||
IDsUpdated (input) {
|
||||
IDsUpdated(input) {
|
||||
const remove = [];
|
||||
input.elems.forEach(function (elem) {
|
||||
if ('se:connector' in elem.attr) {
|
||||
|
@ -634,9 +643,9 @@ export default {
|
|||
}
|
||||
}
|
||||
});
|
||||
return {remove};
|
||||
return { remove };
|
||||
},
|
||||
toolButtonStateUpdate (opts) {
|
||||
toolButtonStateUpdate(opts) {
|
||||
const button = document.getElementById('mode_connect');
|
||||
if (opts.nostroke && button.pressed === true) {
|
||||
svgEditor.clickSelect();
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
import {
|
||||
transformPoint, transformListToTransform, matrixMultiply, transformBox
|
||||
} from './math.js';
|
||||
import {getTransformList} from './svgtransformlist.js';
|
||||
import { getTransformList } from './svgtransformlist.js';
|
||||
|
||||
const $ = jQuery;
|
||||
|
||||
|
@ -118,191 +118,192 @@ export const remapElement = function (selected, changes, m) {
|
|||
// now we have a set of changes and an applied reduced transform list
|
||||
// we apply the changes directly to the DOM
|
||||
switch (elName) {
|
||||
case 'foreignObject':
|
||||
case 'rect':
|
||||
case 'image': {
|
||||
// Allow images to be inverted (give them matrix when flipped)
|
||||
if (elName === 'image' && (m.a < 0 || m.d < 0)) {
|
||||
// Convert to matrix
|
||||
const chlist = getTransformList(selected);
|
||||
const mt = editorContext_.getSVGRoot().createSVGTransform();
|
||||
mt.setMatrix(matrixMultiply(transformListToTransform(chlist).matrix, m));
|
||||
chlist.clear();
|
||||
chlist.appendItem(mt);
|
||||
} else {
|
||||
const pt1 = remap(changes.x, changes.y);
|
||||
changes.width = scalew(changes.width);
|
||||
changes.height = scaleh(changes.height);
|
||||
changes.x = pt1.x + Math.min(0, changes.width);
|
||||
changes.y = pt1.y + Math.min(0, changes.height);
|
||||
changes.width = Math.abs(changes.width);
|
||||
changes.height = Math.abs(changes.height);
|
||||
}
|
||||
finishUp();
|
||||
break;
|
||||
} case 'ellipse': {
|
||||
const c = remap(changes.cx, changes.cy);
|
||||
changes.cx = c.x;
|
||||
changes.cy = c.y;
|
||||
changes.rx = scalew(changes.rx);
|
||||
changes.ry = scaleh(changes.ry);
|
||||
changes.rx = Math.abs(changes.rx);
|
||||
changes.ry = Math.abs(changes.ry);
|
||||
finishUp();
|
||||
break;
|
||||
} case 'circle': {
|
||||
const c = remap(changes.cx, changes.cy);
|
||||
changes.cx = c.x;
|
||||
changes.cy = c.y;
|
||||
// take the minimum of the new selected box's dimensions for the new circle radius
|
||||
const tbox = transformBox(box.x, box.y, box.width, box.height, m);
|
||||
const w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y;
|
||||
changes.r = Math.min(w / 2, h / 2);
|
||||
|
||||
if (changes.r) { changes.r = Math.abs(changes.r); }
|
||||
finishUp();
|
||||
break;
|
||||
} case 'line': {
|
||||
const pt1 = remap(changes.x1, changes.y1);
|
||||
const pt2 = remap(changes.x2, changes.y2);
|
||||
changes.x1 = pt1.x;
|
||||
changes.y1 = pt1.y;
|
||||
changes.x2 = pt2.x;
|
||||
changes.y2 = pt2.y;
|
||||
} // Fallthrough
|
||||
case 'text':
|
||||
case 'tspan':
|
||||
case 'use': {
|
||||
finishUp();
|
||||
break;
|
||||
} case 'g': {
|
||||
const gsvg = dataStorage.get(selected, 'gsvg');
|
||||
if (gsvg) {
|
||||
assignAttributes(gsvg, changes, 1000, true);
|
||||
}
|
||||
break;
|
||||
} case 'polyline':
|
||||
case 'polygon': {
|
||||
const len = changes.points.length;
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const pt = changes.points[i];
|
||||
const {x, y} = remap(pt.x, pt.y);
|
||||
changes.points[i].x = x;
|
||||
changes.points[i].y = y;
|
||||
}
|
||||
|
||||
// const len = changes.points.length;
|
||||
let pstr = '';
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const pt = changes.points[i];
|
||||
pstr += pt.x + ',' + pt.y + ' ';
|
||||
}
|
||||
selected.setAttribute('points', pstr);
|
||||
break;
|
||||
} case 'path': {
|
||||
const segList = selected.pathSegList;
|
||||
let len = segList.numberOfItems;
|
||||
changes.d = [];
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const seg = segList.getItem(i);
|
||||
changes.d[i] = {
|
||||
type: seg.pathSegType,
|
||||
x: seg.x,
|
||||
y: seg.y,
|
||||
x1: seg.x1,
|
||||
y1: seg.y1,
|
||||
x2: seg.x2,
|
||||
y2: seg.y2,
|
||||
r1: seg.r1,
|
||||
r2: seg.r2,
|
||||
angle: seg.angle,
|
||||
largeArcFlag: seg.largeArcFlag,
|
||||
sweepFlag: seg.sweepFlag
|
||||
};
|
||||
}
|
||||
|
||||
len = changes.d.length;
|
||||
const firstseg = changes.d[0],
|
||||
currentpt = remap(firstseg.x, firstseg.y);
|
||||
changes.d[0].x = currentpt.x;
|
||||
changes.d[0].y = currentpt.y;
|
||||
for (let i = 1; i < len; ++i) {
|
||||
const seg = changes.d[i];
|
||||
const {type} = seg;
|
||||
// if absolute or first segment, we want to remap x, y, x1, y1, x2, y2
|
||||
// if relative, we want to scalew, scaleh
|
||||
if (type % 2 === 0) { // absolute
|
||||
const thisx = (seg.x !== undefined) ? seg.x : currentpt.x, // for V commands
|
||||
thisy = (seg.y !== undefined) ? seg.y : currentpt.y; // for H commands
|
||||
const pt = remap(thisx, thisy);
|
||||
const pt1 = remap(seg.x1, seg.y1);
|
||||
const pt2 = remap(seg.x2, seg.y2);
|
||||
seg.x = pt.x;
|
||||
seg.y = pt.y;
|
||||
seg.x1 = pt1.x;
|
||||
seg.y1 = pt1.y;
|
||||
seg.x2 = pt2.x;
|
||||
seg.y2 = pt2.y;
|
||||
seg.r1 = scalew(seg.r1);
|
||||
seg.r2 = scaleh(seg.r2);
|
||||
} else { // relative
|
||||
seg.x = scalew(seg.x);
|
||||
seg.y = scaleh(seg.y);
|
||||
seg.x1 = scalew(seg.x1);
|
||||
seg.y1 = scaleh(seg.y1);
|
||||
seg.x2 = scalew(seg.x2);
|
||||
seg.y2 = scaleh(seg.y2);
|
||||
seg.r1 = scalew(seg.r1);
|
||||
seg.r2 = scaleh(seg.r2);
|
||||
case 'foreignObject':
|
||||
case 'rect':
|
||||
case 'image': {
|
||||
// Allow images to be inverted (give them matrix when flipped)
|
||||
if (elName === 'image' && (m.a < 0 || m.d < 0)) {
|
||||
// Convert to matrix
|
||||
const chlist = getTransformList(selected);
|
||||
const mt = editorContext_.getSVGRoot().createSVGTransform();
|
||||
mt.setMatrix(matrixMultiply(transformListToTransform(chlist).matrix, m));
|
||||
chlist.clear();
|
||||
chlist.appendItem(mt);
|
||||
} else {
|
||||
const pt1 = remap(changes.x, changes.y);
|
||||
changes.width = scalew(changes.width);
|
||||
changes.height = scaleh(changes.height);
|
||||
changes.x = pt1.x + Math.min(0, changes.width);
|
||||
changes.y = pt1.y + Math.min(0, changes.height);
|
||||
changes.width = Math.abs(changes.width);
|
||||
changes.height = Math.abs(changes.height);
|
||||
}
|
||||
} // for each segment
|
||||
finishUp();
|
||||
break;
|
||||
} case 'ellipse': {
|
||||
const c = remap(changes.cx, changes.cy);
|
||||
changes.cx = c.x;
|
||||
changes.cy = c.y;
|
||||
changes.rx = scalew(changes.rx);
|
||||
changes.ry = scaleh(changes.ry);
|
||||
changes.rx = Math.abs(changes.rx);
|
||||
changes.ry = Math.abs(changes.ry);
|
||||
finishUp();
|
||||
break;
|
||||
} case 'circle': {
|
||||
const c = remap(changes.cx, changes.cy);
|
||||
changes.cx = c.x;
|
||||
changes.cy = c.y;
|
||||
// take the minimum of the new selected box's dimensions for the new circle radius
|
||||
const tbox = transformBox(box.x, box.y, box.width, box.height, m);
|
||||
const w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y;
|
||||
changes.r = Math.min(w / 2, h / 2);
|
||||
|
||||
let dstr = '';
|
||||
len = changes.d.length;
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const seg = changes.d[i];
|
||||
const {type} = seg;
|
||||
dstr += pathMap[type];
|
||||
switch (type) {
|
||||
case 13: // relative horizontal line (h)
|
||||
case 12: // absolute horizontal line (H)
|
||||
dstr += seg.x + ' ';
|
||||
break;
|
||||
case 15: // relative vertical line (v)
|
||||
case 14: // absolute vertical line (V)
|
||||
dstr += seg.y + ' ';
|
||||
break;
|
||||
case 3: // relative move (m)
|
||||
case 5: // relative line (l)
|
||||
case 19: // relative smooth quad (t)
|
||||
case 2: // absolute move (M)
|
||||
case 4: // absolute line (L)
|
||||
case 18: // absolute smooth quad (T)
|
||||
dstr += seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 7: // relative cubic (c)
|
||||
case 6: // absolute cubic (C)
|
||||
dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x2 + ',' + seg.y2 + ' ' +
|
||||
seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 9: // relative quad (q)
|
||||
case 8: // absolute quad (Q)
|
||||
dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 11: // relative elliptical arc (a)
|
||||
case 10: // absolute elliptical arc (A)
|
||||
dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + Number(seg.largeArcFlag) +
|
||||
' ' + Number(seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 17: // relative smooth cubic (s)
|
||||
case 16: // absolute smooth cubic (S)
|
||||
dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
if (changes.r) { changes.r = Math.abs(changes.r); }
|
||||
finishUp();
|
||||
break;
|
||||
} case 'line': {
|
||||
const pt1 = remap(changes.x1, changes.y1);
|
||||
const pt2 = remap(changes.x2, changes.y2);
|
||||
changes.x1 = pt1.x;
|
||||
changes.y1 = pt1.y;
|
||||
changes.x2 = pt2.x;
|
||||
changes.y2 = pt2.y;
|
||||
} // Fallthrough
|
||||
case 'text':
|
||||
case 'tspan':
|
||||
case 'use': {
|
||||
finishUp();
|
||||
break;
|
||||
} case 'g': {
|
||||
const dataStorage = editorContext_.getDataStorage();
|
||||
const gsvg = dataStorage.get(selected, 'gsvg');
|
||||
if (gsvg) {
|
||||
assignAttributes(gsvg, changes, 1000, true);
|
||||
}
|
||||
break;
|
||||
} case 'polyline':
|
||||
case 'polygon': {
|
||||
const len = changes.points.length;
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const pt = changes.points[i];
|
||||
const { x, y } = remap(pt.x, pt.y);
|
||||
changes.points[i].x = x;
|
||||
changes.points[i].y = y;
|
||||
}
|
||||
}
|
||||
|
||||
selected.setAttribute('d', dstr);
|
||||
break;
|
||||
}
|
||||
// const len = changes.points.length;
|
||||
let pstr = '';
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const pt = changes.points[i];
|
||||
pstr += pt.x + ',' + pt.y + ' ';
|
||||
}
|
||||
selected.setAttribute('points', pstr);
|
||||
break;
|
||||
} case 'path': {
|
||||
const segList = selected.pathSegList;
|
||||
let len = segList.numberOfItems;
|
||||
changes.d = [];
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const seg = segList.getItem(i);
|
||||
changes.d[i] = {
|
||||
type: seg.pathSegType,
|
||||
x: seg.x,
|
||||
y: seg.y,
|
||||
x1: seg.x1,
|
||||
y1: seg.y1,
|
||||
x2: seg.x2,
|
||||
y2: seg.y2,
|
||||
r1: seg.r1,
|
||||
r2: seg.r2,
|
||||
angle: seg.angle,
|
||||
largeArcFlag: seg.largeArcFlag,
|
||||
sweepFlag: seg.sweepFlag
|
||||
};
|
||||
}
|
||||
|
||||
len = changes.d.length;
|
||||
const firstseg = changes.d[0],
|
||||
currentpt = remap(firstseg.x, firstseg.y);
|
||||
changes.d[0].x = currentpt.x;
|
||||
changes.d[0].y = currentpt.y;
|
||||
for (let i = 1; i < len; ++i) {
|
||||
const seg = changes.d[i];
|
||||
const { type } = seg;
|
||||
// if absolute or first segment, we want to remap x, y, x1, y1, x2, y2
|
||||
// if relative, we want to scalew, scaleh
|
||||
if (type % 2 === 0) { // absolute
|
||||
const thisx = (seg.x !== undefined) ? seg.x : currentpt.x, // for V commands
|
||||
thisy = (seg.y !== undefined) ? seg.y : currentpt.y; // for H commands
|
||||
const pt = remap(thisx, thisy);
|
||||
const pt1 = remap(seg.x1, seg.y1);
|
||||
const pt2 = remap(seg.x2, seg.y2);
|
||||
seg.x = pt.x;
|
||||
seg.y = pt.y;
|
||||
seg.x1 = pt1.x;
|
||||
seg.y1 = pt1.y;
|
||||
seg.x2 = pt2.x;
|
||||
seg.y2 = pt2.y;
|
||||
seg.r1 = scalew(seg.r1);
|
||||
seg.r2 = scaleh(seg.r2);
|
||||
} else { // relative
|
||||
seg.x = scalew(seg.x);
|
||||
seg.y = scaleh(seg.y);
|
||||
seg.x1 = scalew(seg.x1);
|
||||
seg.y1 = scaleh(seg.y1);
|
||||
seg.x2 = scalew(seg.x2);
|
||||
seg.y2 = scaleh(seg.y2);
|
||||
seg.r1 = scalew(seg.r1);
|
||||
seg.r2 = scaleh(seg.r2);
|
||||
}
|
||||
} // for each segment
|
||||
|
||||
let dstr = '';
|
||||
len = changes.d.length;
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const seg = changes.d[i];
|
||||
const { type } = seg;
|
||||
dstr += pathMap[type];
|
||||
switch (type) {
|
||||
case 13: // relative horizontal line (h)
|
||||
case 12: // absolute horizontal line (H)
|
||||
dstr += seg.x + ' ';
|
||||
break;
|
||||
case 15: // relative vertical line (v)
|
||||
case 14: // absolute vertical line (V)
|
||||
dstr += seg.y + ' ';
|
||||
break;
|
||||
case 3: // relative move (m)
|
||||
case 5: // relative line (l)
|
||||
case 19: // relative smooth quad (t)
|
||||
case 2: // absolute move (M)
|
||||
case 4: // absolute line (L)
|
||||
case 18: // absolute smooth quad (T)
|
||||
dstr += seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 7: // relative cubic (c)
|
||||
case 6: // absolute cubic (C)
|
||||
dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x2 + ',' + seg.y2 + ' ' +
|
||||
seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 9: // relative quad (q)
|
||||
case 8: // absolute quad (Q)
|
||||
dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 11: // relative elliptical arc (a)
|
||||
case 10: // absolute elliptical arc (A)
|
||||
dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + Number(seg.largeArcFlag) +
|
||||
' ' + Number(seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 17: // relative smooth cubic (s)
|
||||
case 16: // absolute smooth cubic (S)
|
||||
dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
selected.setAttribute('d', dstr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -989,6 +989,7 @@ export const mergeAllLayers = function (hrService) {
|
|||
*/
|
||||
export const leaveContext = function () {
|
||||
const len = disabledElems.length;
|
||||
const dataStorage = canvas_.getDataStorage();
|
||||
if (len) {
|
||||
for (let i = 0; i < len; i++) {
|
||||
const elem = disabledElems[i];
|
||||
|
@ -1015,6 +1016,7 @@ export const leaveContext = function () {
|
|||
* @returns {void}
|
||||
*/
|
||||
export const setContext = function (elem) {
|
||||
const dataStorage = canvas_.getDataStorage();
|
||||
leaveContext();
|
||||
if (typeof elem === 'string') {
|
||||
elem = getElem(elem);
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
*/
|
||||
|
||||
/* globals jQuery */
|
||||
import {jGraduate} from '../editor/components/jgraduate/jQuery.jGraduate.js';
|
||||
import { jGraduate } from '../editor/components/jgraduate/jQuery.jGraduate.js';
|
||||
|
||||
import * as hstry from './history.js';
|
||||
import jQueryPluginSVG from './jQuery.attr.js';
|
||||
import {NS} from '../common/namespaces.js';
|
||||
import { NS } from '../common/namespaces.js';
|
||||
import {
|
||||
getVisibleElements, getStrokedBBoxDefaultVisible, findDefs,
|
||||
walkTree, isNullish, getHref, setHref, getElem
|
||||
|
@ -17,7 +17,7 @@ import {
|
|||
import {
|
||||
convertToNum
|
||||
} from '../common/units.js';
|
||||
import {getParents} from '../editor/components/jgraduate/Util.js';
|
||||
import { getParents } from '../editor/components/jgraduate/Util.js';
|
||||
|
||||
const $ = jQueryPluginSVG(jQuery);
|
||||
|
||||
|
@ -61,11 +61,12 @@ export const getResolutionMethod = function () {
|
|||
*/
|
||||
export const getTitleMethod = function (elem) {
|
||||
const selectedElements = elemContext_.getSelectedElements();
|
||||
const dataStorage = elemContext_.getDataStorage();
|
||||
elem = elem || selectedElements[0];
|
||||
if (!elem) { return undefined; }
|
||||
if(dataStorage.has(elem, 'gsvg')){
|
||||
if (dataStorage.has(elem, 'gsvg')) {
|
||||
elem = dataStorage.get(elem, 'gsvg');
|
||||
} else if(dataStorage.has(elem, 'symbol')) {
|
||||
} else if (dataStorage.has(elem, 'symbol')) {
|
||||
elem = dataStorage.get(elem, 'symbol');
|
||||
}
|
||||
const childs = elem.childNodes;
|
||||
|
@ -86,8 +87,9 @@ export const getTitleMethod = function (elem) {
|
|||
*/
|
||||
export const setGroupTitleMethod = function (val) {
|
||||
const selectedElements = elemContext_.getSelectedElements();
|
||||
const dataStorage = elemContext_.getDataStorage();
|
||||
let elem = selectedElements[0];
|
||||
if(dataStorage.has(elem, 'gsvg')){
|
||||
if (dataStorage.has(elem, 'gsvg')) {
|
||||
elem = dataStorage.get(elem, 'gsvg');
|
||||
}
|
||||
|
||||
|
@ -104,7 +106,7 @@ export const setGroupTitleMethod = function (val) {
|
|||
} else if (ts.length) {
|
||||
// Change title contents
|
||||
title = ts[0];
|
||||
batchCmd.addSubCommand(new ChangeElementCommand(title, {'#text': title.textContent}));
|
||||
batchCmd.addSubCommand(new ChangeElementCommand(title, { '#text': title.textContent }));
|
||||
title.textContent = val;
|
||||
} else {
|
||||
// Add title element
|
||||
|
@ -149,7 +151,7 @@ export const setDocumentTitleMethod = function (newTitle) {
|
|||
// No title given, so element is not necessary
|
||||
docTitle.remove();
|
||||
}
|
||||
batchCmd.addSubCommand(new ChangeElementCommand(docTitle, {'#text': oldTitle}));
|
||||
batchCmd.addSubCommand(new ChangeElementCommand(docTitle, { '#text': oldTitle }));
|
||||
elemContext_.addCommandToHistory(batchCmd);
|
||||
};
|
||||
|
||||
|
@ -166,7 +168,7 @@ export const setDocumentTitleMethod = function (newTitle) {
|
|||
export const setResolutionMethod = function (x, y) {
|
||||
const currentZoom = elemContext_.getCurrentZoom();
|
||||
const res = elemContext_.getCanvas().getResolution();
|
||||
const {w, h} = res;
|
||||
const { w, h } = res;
|
||||
let batchCmd;
|
||||
|
||||
if (x === 'fit') {
|
||||
|
@ -206,10 +208,10 @@ export const setResolutionMethod = function (x, y) {
|
|||
|
||||
this.contentW = x;
|
||||
this.contentH = y;
|
||||
batchCmd.addSubCommand(new ChangeElementCommand(elemContext_.getSVGContent(), {width: w, height: h}));
|
||||
batchCmd.addSubCommand(new ChangeElementCommand(elemContext_.getSVGContent(), { width: w, height: h }));
|
||||
|
||||
elemContext_.getSVGContent().setAttribute('viewBox', [0, 0, x / currentZoom, y / currentZoom].join(' '));
|
||||
batchCmd.addSubCommand(new ChangeElementCommand(elemContext_.getSVGContent(), {viewBox: ['0 0', w, h].join(' ')}));
|
||||
batchCmd.addSubCommand(new ChangeElementCommand(elemContext_.getSVGContent(), { viewBox: ['0 0', w, h].join(' ') }));
|
||||
|
||||
elemContext_.addCommandToHistory(batchCmd);
|
||||
elemContext_.call('changed', [elemContext_.getSVGContent()]);
|
||||
|
@ -254,7 +256,7 @@ export const setBBoxZoomMethod = function (val, editorW, editorH) {
|
|||
const hZoom = Math.round((editorH / bb.height) * 100 * spacer) / 100;
|
||||
const zoom = Math.min(wZoom, hZoom);
|
||||
elemContext_.getCanvas().setZoom(zoom);
|
||||
return {zoom, bbox: bb};
|
||||
return { zoom, bbox: bb };
|
||||
};
|
||||
|
||||
if (typeof val === 'object') {
|
||||
|
@ -262,35 +264,35 @@ export const setBBoxZoomMethod = function (val, editorW, editorH) {
|
|||
if (bb.width === 0 || bb.height === 0) {
|
||||
const newzoom = bb.zoom ? bb.zoom : currentZoom * bb.factor;
|
||||
elemContext_.getCanvas().setZoom(newzoom);
|
||||
return {zoom: currentZoom, bbox: bb};
|
||||
return { zoom: currentZoom, bbox: bb };
|
||||
}
|
||||
return calcZoom(bb);
|
||||
}
|
||||
|
||||
switch (val) {
|
||||
case 'selection': {
|
||||
if (!selectedElements[0]) { return undefined; }
|
||||
const selectedElems = $.map(selectedElements, function (n) {
|
||||
if (n) {
|
||||
return n;
|
||||
}
|
||||
case 'selection': {
|
||||
if (!selectedElements[0]) { return undefined; }
|
||||
const selectedElems = $.map(selectedElements, function (n) {
|
||||
if (n) {
|
||||
return n;
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
bb = getStrokedBBoxDefaultVisible(selectedElems);
|
||||
break;
|
||||
} case 'canvas': {
|
||||
const res = elemContext_.getCanvas().getResolution();
|
||||
spacer = 0.95;
|
||||
bb = { width: res.w, height: res.h, x: 0, y: 0 };
|
||||
break;
|
||||
} case 'content':
|
||||
bb = getStrokedBBoxDefaultVisible();
|
||||
break;
|
||||
case 'layer':
|
||||
bb = getStrokedBBoxDefaultVisible(getVisibleElements(elemContext_.getCanvas().getCurrentDrawing().getCurrentLayer()));
|
||||
break;
|
||||
default:
|
||||
return undefined;
|
||||
});
|
||||
bb = getStrokedBBoxDefaultVisible(selectedElems);
|
||||
break;
|
||||
} case 'canvas': {
|
||||
const res = elemContext_.getCanvas().getResolution();
|
||||
spacer = 0.95;
|
||||
bb = {width: res.w, height: res.h, x: 0, y: 0};
|
||||
break;
|
||||
} case 'content':
|
||||
bb = getStrokedBBoxDefaultVisible();
|
||||
break;
|
||||
case 'layer':
|
||||
bb = getStrokedBBoxDefaultVisible(getVisibleElements(elemContext_.getCanvas().getCurrentDrawing().getCurrentLayer()));
|
||||
break;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
return calcZoom(bb);
|
||||
};
|
||||
|
@ -327,14 +329,14 @@ export const setZoomMethod = function (zoomLevel) {
|
|||
export const setColorMethod = function (type, val, preventUndo) {
|
||||
const selectedElements = elemContext_.getSelectedElements();
|
||||
elemContext_.setCurShape(type, val);
|
||||
elemContext_.setCurProperties(type + '_paint', {type: 'solidColor'});
|
||||
elemContext_.setCurProperties(type + '_paint', { type: 'solidColor' });
|
||||
const elems = [];
|
||||
/**
|
||||
*
|
||||
* @param {Element} e
|
||||
* @returns {void}
|
||||
*/
|
||||
function addNonG (e) {
|
||||
function addNonG(e) {
|
||||
if (e.nodeName !== 'g') {
|
||||
elems.push(e);
|
||||
}
|
||||
|
@ -406,9 +408,9 @@ export const findDuplicateGradient = function (grad) {
|
|||
const og = existingGrads[i];
|
||||
if (grad.tagName === 'linearGradient') {
|
||||
if (grad.getAttribute('x1') !== og.getAttribute('x1') ||
|
||||
grad.getAttribute('y1') !== og.getAttribute('y1') ||
|
||||
grad.getAttribute('x2') !== og.getAttribute('x2') ||
|
||||
grad.getAttribute('y2') !== og.getAttribute('y2')
|
||||
grad.getAttribute('y1') !== og.getAttribute('y1') ||
|
||||
grad.getAttribute('x2') !== og.getAttribute('x2') ||
|
||||
grad.getAttribute('y2') !== og.getAttribute('y2')
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
@ -429,7 +431,7 @@ export const findDuplicateGradient = function (grad) {
|
|||
};
|
||||
|
||||
let diff = false;
|
||||
radAttrs.forEach(function(attr, j){
|
||||
radAttrs.forEach(function (attr, j) {
|
||||
if (gradAttrs[attr] !== ogAttrs[attr]) { diff = true; }
|
||||
});
|
||||
|
||||
|
@ -450,8 +452,8 @@ export const findDuplicateGradient = function (grad) {
|
|||
const ostop = ostops[j];
|
||||
|
||||
if (stop.getAttribute('offset') !== ostop.getAttribute('offset') ||
|
||||
stop.getAttribute('stop-opacity') !== ostop.getAttribute('stop-opacity') ||
|
||||
stop.getAttribute('stop-color') !== ostop.getAttribute('stop-color')) {
|
||||
stop.getAttribute('stop-opacity') !== ostop.getAttribute('stop-opacity') ||
|
||||
stop.getAttribute('stop-color') !== ostop.getAttribute('stop-color')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -479,14 +481,14 @@ export const setPaintMethod = function (type, paint) {
|
|||
// now set the current paint object
|
||||
elemContext_.setCurProperties(type + '_paint', p);
|
||||
switch (p.type) {
|
||||
case 'solidColor':
|
||||
this.setColor(type, p.solidColor !== 'none' ? '#' + p.solidColor : 'none');
|
||||
break;
|
||||
case 'linearGradient':
|
||||
case 'radialGradient':
|
||||
elemContext_.setCanvas(type + 'Grad', p[p.type]);
|
||||
elemContext_.getCanvas().setGradient(type);
|
||||
break;
|
||||
case 'solidColor':
|
||||
this.setColor(type, p.solidColor !== 'none' ? '#' + p.solidColor : 'none');
|
||||
break;
|
||||
case 'linearGradient':
|
||||
case 'radialGradient':
|
||||
elemContext_.setCanvas(type + 'Grad', p[p.type]);
|
||||
elemContext_.getCanvas().setGradient(type);
|
||||
break;
|
||||
}
|
||||
};
|
||||
/**
|
||||
|
@ -511,7 +513,7 @@ export const setStrokeWidthMethod = function (val) {
|
|||
* @param {Element} e
|
||||
* @returns {void}
|
||||
*/
|
||||
function addNonG (e) {
|
||||
function addNonG(e) {
|
||||
if (e.nodeName !== 'g') {
|
||||
elems.push(e);
|
||||
}
|
||||
|
@ -572,7 +574,7 @@ export const getBoldMethod = function () {
|
|||
// should only have one element selected
|
||||
const selected = selectedElements[0];
|
||||
if (!isNullish(selected) && selected.tagName === 'text' &&
|
||||
isNullish(selectedElements[1])) {
|
||||
isNullish(selectedElements[1])) {
|
||||
return (selected.getAttribute('font-weight') === 'bold');
|
||||
}
|
||||
return false;
|
||||
|
@ -588,7 +590,7 @@ export const setBoldMethod = function (b) {
|
|||
const selectedElements = elemContext_.getSelectedElements();
|
||||
const selected = selectedElements[0];
|
||||
if (!isNullish(selected) && selected.tagName === 'text' &&
|
||||
isNullish(selectedElements[1])) {
|
||||
isNullish(selectedElements[1])) {
|
||||
elemContext_.getCanvas().changeSelectedAttribute('font-weight', b ? 'bold' : 'normal');
|
||||
}
|
||||
if (!selectedElements[0].textContent) {
|
||||
|
@ -605,7 +607,7 @@ export const getItalicMethod = function () {
|
|||
const selectedElements = elemContext_.getSelectedElements();
|
||||
const selected = selectedElements[0];
|
||||
if (!isNullish(selected) && selected.tagName === 'text' &&
|
||||
isNullish(selectedElements[1])) {
|
||||
isNullish(selectedElements[1])) {
|
||||
return (selected.getAttribute('font-style') === 'italic');
|
||||
}
|
||||
return false;
|
||||
|
@ -621,7 +623,7 @@ export const setItalicMethod = function (i) {
|
|||
const selectedElements = elemContext_.getSelectedElements();
|
||||
const selected = selectedElements[0];
|
||||
if (!isNullish(selected) && selected.tagName === 'text' &&
|
||||
isNullish(selectedElements[1])) {
|
||||
isNullish(selectedElements[1])) {
|
||||
elemContext_.getCanvas().changeSelectedAttribute('font-style', i ? 'italic' : 'normal');
|
||||
}
|
||||
if (!selectedElements[0].textContent) {
|
||||
|
@ -638,7 +640,7 @@ export const setTextAnchorMethod = function (value) {
|
|||
const selectedElements = elemContext_.getSelectedElements();
|
||||
const selected = selectedElements[0];
|
||||
if (!isNullish(selected) && selected.tagName === 'text' &&
|
||||
isNullish(selectedElements[1])) {
|
||||
isNullish(selectedElements[1])) {
|
||||
elemContext_.getCanvas().changeSelectedAttribute('text-anchor', value);
|
||||
}
|
||||
if (!selectedElements[0].textContent) {
|
||||
|
@ -747,7 +749,7 @@ export const setImageURLMethod = function (val) {
|
|||
const elem = selectedElements[0];
|
||||
if (!elem) { return; }
|
||||
|
||||
const attrs = {
|
||||
const attrs = {
|
||||
width: elem.getAttribute('width'),
|
||||
height: elem.getAttribute('height'),
|
||||
};
|
||||
|
@ -767,8 +769,8 @@ export const setImageURLMethod = function (val) {
|
|||
'#href': curHref
|
||||
}));
|
||||
const img = new Image();
|
||||
img.onload = function() {
|
||||
const changes = {
|
||||
img.onload = function () {
|
||||
const changes = {
|
||||
width: elem.getAttribute('width'),
|
||||
height: elem.getAttribute('height'),
|
||||
};
|
||||
|
@ -834,7 +836,7 @@ export const setRectRadiusMethod = function (val) {
|
|||
if (r !== String(val)) {
|
||||
selected.setAttribute('rx', val);
|
||||
selected.setAttribute('ry', val);
|
||||
elemContext_.addCommandToHistory(new ChangeElementCommand(selected, {rx: r, ry: r}, 'Radius'));
|
||||
elemContext_.addCommandToHistory(new ChangeElementCommand(selected, { rx: r, ry: r }, 'Radius'));
|
||||
elemContext_.call('changed', [selected]);
|
||||
}
|
||||
}
|
||||
|
@ -901,9 +903,9 @@ export const setBackgroundMethod = function (color, url) {
|
|||
const div = document.createElement('div');
|
||||
elemContext_.getCanvas().assignAttributes(div, {
|
||||
style: 'pointer-events:none;width:100%;height:100%;' +
|
||||
'background-image:url(data:image/gif;base64,' +
|
||||
'R0lGODlhEAAQAIAAAP///9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG+' +
|
||||
'gq4jM3IFLJgpswNly/XkcBpIiVaInlLJr9FZWAQA7);'
|
||||
'background-image:url(data:image/gif;base64,' +
|
||||
'R0lGODlhEAAQAIAAAP///9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG+' +
|
||||
'gq4jM3IFLJgpswNly/XkcBpIiVaInlLJr9FZWAQA7);'
|
||||
});
|
||||
bgPattern.append(div);
|
||||
bg.append(bgPattern);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,13 +6,13 @@
|
|||
*/
|
||||
|
||||
import jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`
|
||||
import {NS} from '../common/namespaces.js';
|
||||
import {convertToNum} from '../common/units.js';
|
||||
import {isWebkit} from '../common/browser.js';
|
||||
import {getTransformList} from './svgtransformlist.js';
|
||||
import {getRotationAngle, getHref, getBBox, getRefElem, isNullish} from './utilities.js';
|
||||
import {BatchCommand, ChangeElementCommand} from './history.js';
|
||||
import {remapElement} from './coords.js';
|
||||
import { NS } from '../common/namespaces.js';
|
||||
import { convertToNum } from '../common/units.js';
|
||||
import { isWebkit } from '../common/browser.js';
|
||||
import { getTransformList } from './svgtransformlist.js';
|
||||
import { getRotationAngle, getHref, getBBox, getRefElem, isNullish } from './utilities.js';
|
||||
import { BatchCommand, ChangeElementCommand } from './history.js';
|
||||
import { remapElement } from './coords.js';
|
||||
import {
|
||||
isIdentity, matrixMultiply, transformPoint, transformListToTransform,
|
||||
hasMatrixTransform
|
||||
|
@ -83,6 +83,7 @@ export const recalculateDimensions = function (selected) {
|
|||
}
|
||||
|
||||
const svgroot = context_.getSVGRoot();
|
||||
const dataStorage = context_.getDataStorage();
|
||||
const tlist = getTransformList(selected);
|
||||
|
||||
// remove any unnecessary transforms
|
||||
|
@ -93,7 +94,7 @@ export const recalculateDimensions = function (selected) {
|
|||
const xform = tlist.getItem(k);
|
||||
if (xform.type === 0) {
|
||||
tlist.removeItem(k);
|
||||
// remove identity matrices
|
||||
// remove identity matrices
|
||||
} else if (xform.type === 1) {
|
||||
if (isIdentity(xform.matrix)) {
|
||||
if (noi === 1) {
|
||||
|
@ -106,14 +107,14 @@ export const recalculateDimensions = function (selected) {
|
|||
}
|
||||
tlist.removeItem(k);
|
||||
}
|
||||
// remove zero-degree rotations
|
||||
// remove zero-degree rotations
|
||||
} else if (xform.type === 4 && xform.angle === 0) {
|
||||
tlist.removeItem(k);
|
||||
}
|
||||
}
|
||||
// End here if all it has is a rotation
|
||||
if (tlist.numberOfItems === 1 &&
|
||||
getRotationAngle(selected)) { return null; }
|
||||
getRotationAngle(selected)) { return null; }
|
||||
}
|
||||
|
||||
// if this element had no transforms, we are done
|
||||
|
@ -163,19 +164,18 @@ export const recalculateDimensions = function (selected) {
|
|||
|
||||
// If it still has a single [M] or [R][M], return null too (prevents BatchCommand from being returned).
|
||||
switch (selected.tagName) {
|
||||
// Ignore these elements, as they can absorb the [M]
|
||||
case 'line':
|
||||
case 'polyline':
|
||||
case 'polygon':
|
||||
case 'path':
|
||||
break;
|
||||
default:
|
||||
if ((tlist.numberOfItems === 1 && tlist.getItem(0).type === 1) ||
|
||||
// Ignore these elements, as they can absorb the [M]
|
||||
case 'line':
|
||||
case 'polyline':
|
||||
case 'polygon':
|
||||
case 'path':
|
||||
break;
|
||||
default:
|
||||
if ((tlist.numberOfItems === 1 && tlist.getItem(0).type === 1) ||
|
||||
(tlist.numberOfItems === 2 && tlist.getItem(0).type === 1 && tlist.getItem(0).type === 4)) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Grouped SVG element
|
||||
const gsvg = (dataStorage.has(selected, 'gsvg')) ? dataStorage.get(selected, 'gsvg') : undefined;
|
||||
// we know we have some transforms, so set up return variable
|
||||
|
@ -186,46 +186,46 @@ export const recalculateDimensions = function (selected) {
|
|||
let initial = null;
|
||||
let attrs = [];
|
||||
switch (selected.tagName) {
|
||||
case 'line':
|
||||
attrs = ['x1', 'y1', 'x2', 'y2'];
|
||||
break;
|
||||
case 'circle':
|
||||
attrs = ['cx', 'cy', 'r'];
|
||||
break;
|
||||
case 'ellipse':
|
||||
attrs = ['cx', 'cy', 'rx', 'ry'];
|
||||
break;
|
||||
case 'foreignObject':
|
||||
case 'rect':
|
||||
case 'image':
|
||||
attrs = ['width', 'height', 'x', 'y'];
|
||||
break;
|
||||
case 'use':
|
||||
case 'text':
|
||||
case 'tspan':
|
||||
attrs = ['x', 'y'];
|
||||
break;
|
||||
case 'polygon':
|
||||
case 'polyline': {
|
||||
initial = {};
|
||||
initial.points = selected.getAttribute('points');
|
||||
const list = selected.points;
|
||||
const len = list.numberOfItems;
|
||||
changes.points = new Array(len);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const pt = list.getItem(i);
|
||||
changes.points[i] = {x: pt.x, y: pt.y};
|
||||
}
|
||||
break;
|
||||
} case 'path':
|
||||
initial = {};
|
||||
initial.d = selected.getAttribute('d');
|
||||
changes.d = selected.getAttribute('d');
|
||||
break;
|
||||
case 'line':
|
||||
attrs = ['x1', 'y1', 'x2', 'y2'];
|
||||
break;
|
||||
case 'circle':
|
||||
attrs = ['cx', 'cy', 'r'];
|
||||
break;
|
||||
case 'ellipse':
|
||||
attrs = ['cx', 'cy', 'rx', 'ry'];
|
||||
break;
|
||||
case 'foreignObject':
|
||||
case 'rect':
|
||||
case 'image':
|
||||
attrs = ['width', 'height', 'x', 'y'];
|
||||
break;
|
||||
case 'use':
|
||||
case 'text':
|
||||
case 'tspan':
|
||||
attrs = ['x', 'y'];
|
||||
break;
|
||||
case 'polygon':
|
||||
case 'polyline': {
|
||||
initial = {};
|
||||
initial.points = selected.getAttribute('points');
|
||||
const list = selected.points;
|
||||
const len = list.numberOfItems;
|
||||
changes.points = new Array(len);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const pt = list.getItem(i);
|
||||
changes.points[i] = { x: pt.x, y: pt.y };
|
||||
}
|
||||
break;
|
||||
} case 'path':
|
||||
initial = {};
|
||||
initial.d = selected.getAttribute('d');
|
||||
changes.d = selected.getAttribute('d');
|
||||
break;
|
||||
} // switch on element type to get initial values
|
||||
|
||||
if (attrs.length) {
|
||||
Array.prototype.forEach.call(attrs, function(attr, i){
|
||||
Array.prototype.forEach.call(attrs, function (attr, i) {
|
||||
changes[attr] = selected.getAttribute(attr);
|
||||
});
|
||||
for (const [attr, val] of Object.entries(changes)) {
|
||||
|
@ -245,7 +245,7 @@ export const recalculateDimensions = function (selected) {
|
|||
initial = $.extend(true, {}, changes);
|
||||
for (const [attr, val] of Object.entries(initial)) {
|
||||
initial[attr] = convertToNum(attr, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
// save the start transform value too
|
||||
initial.transform = context_.getStartTransform() || '';
|
||||
|
@ -256,7 +256,7 @@ export const recalculateDimensions = function (selected) {
|
|||
if ((selected.tagName === 'g' && !gsvg) || selected.tagName === 'a') {
|
||||
const box = getBBox(selected);
|
||||
|
||||
oldcenter = {x: box.x + box.width / 2, y: box.y + box.height / 2};
|
||||
oldcenter = { x: box.x + box.width / 2, y: box.y + box.height / 2 };
|
||||
newcenter = transformPoint(
|
||||
box.x + box.width / 2,
|
||||
box.y + box.height / 2,
|
||||
|
@ -341,7 +341,7 @@ export const recalculateDimensions = function (selected) {
|
|||
childTlist.clear();
|
||||
childTlist.appendItem(e2t);
|
||||
// childxforms.push(e2t);
|
||||
// if not rotated or skewed, push the [T][S][-T] down to the child
|
||||
// if not rotated or skewed, push the [T][S][-T] down to the child
|
||||
} else {
|
||||
// update the transform list with translate,scale,translate
|
||||
|
||||
|
@ -406,9 +406,9 @@ export const recalculateDimensions = function (selected) {
|
|||
e2t.setMatrix(m);
|
||||
tlist.clear();
|
||||
tlist.appendItem(e2t);
|
||||
// next, check if the first transform was a translate
|
||||
// if we had [ T1 ] [ M ] we want to transform this into [ M ] [ T2 ]
|
||||
// therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ]
|
||||
// next, check if the first transform was a translate
|
||||
// if we had [ T1 ] [ M ] we want to transform this into [ M ] [ T2 ]
|
||||
// therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ]
|
||||
} else if ((N === 1 || (N > 1 && tlist.getItem(1).type !== 3)) &&
|
||||
tlist.getItem(0).type === 2) {
|
||||
operation = 2; // translate
|
||||
|
@ -474,8 +474,8 @@ export const recalculateDimensions = function (selected) {
|
|||
}
|
||||
context_.setStartTransform(oldStartTransform);
|
||||
}
|
||||
// else, a matrix imposition from a parent group
|
||||
// keep pushing it down to the children
|
||||
// else, a matrix imposition from a parent group
|
||||
// keep pushing it down to the children
|
||||
} else if (N === 1 && tlist.getItem(0).type === 1 && !gangle) {
|
||||
operation = 1;
|
||||
const m = tlist.getItem(0).matrix,
|
||||
|
@ -509,7 +509,7 @@ export const recalculateDimensions = function (selected) {
|
|||
}
|
||||
}
|
||||
tlist.clear();
|
||||
// else it was just a rotate
|
||||
// else it was just a rotate
|
||||
} else {
|
||||
if (gangle) {
|
||||
const newRot = svgroot.createSVGTransform();
|
||||
|
@ -542,7 +542,7 @@ export const recalculateDimensions = function (selected) {
|
|||
tlist.appendItem(newRot);
|
||||
}
|
||||
}
|
||||
// if it was a resize
|
||||
// if it was a resize
|
||||
} else if (operation === 3) {
|
||||
const m = transformListToTransform(tlist).matrix;
|
||||
const roldt = svgroot.createSVGTransform();
|
||||
|
@ -590,7 +590,7 @@ export const recalculateDimensions = function (selected) {
|
|||
}
|
||||
}
|
||||
}
|
||||
// else, it's a non-group
|
||||
// else, it's a non-group
|
||||
} else {
|
||||
// TODO: box might be null for some elements (<metadata> etc), need to handle this
|
||||
const box = getBBox(selected);
|
||||
|
@ -606,7 +606,7 @@ export const recalculateDimensions = function (selected) {
|
|||
// temporarily strip off the rotate and save the old center
|
||||
const angle = getRotationAngle(selected);
|
||||
if (angle) {
|
||||
oldcenter = {x: box.x + box.width / 2, y: box.y + box.height / 2};
|
||||
oldcenter = { x: box.x + box.width / 2, y: box.y + box.height / 2 };
|
||||
newcenter = transformPoint(
|
||||
box.x + box.width / 2,
|
||||
box.y + box.height / 2,
|
||||
|
@ -672,8 +672,8 @@ export const recalculateDimensions = function (selected) {
|
|||
tlist.removeItem(N - 1);
|
||||
tlist.removeItem(N - 2);
|
||||
tlist.removeItem(N - 3);
|
||||
// if we had [T][S][-T][M], then this was a skewed element being resized
|
||||
// Thus, we simply combine it all into one matrix
|
||||
// if we had [T][S][-T][M], then this was a skewed element being resized
|
||||
// Thus, we simply combine it all into one matrix
|
||||
} else if (N === 4 && tlist.getItem(N - 1).type === 1) {
|
||||
operation = 3; // scale
|
||||
m = transformListToTransform(tlist).matrix;
|
||||
|
@ -683,10 +683,10 @@ export const recalculateDimensions = function (selected) {
|
|||
tlist.appendItem(e2t);
|
||||
// reset the matrix so that the element is not re-mapped
|
||||
m = svgroot.createSVGMatrix();
|
||||
// if we had [R][T][S][-T][M], then this was a rotated matrix-element
|
||||
// if we had [T1][M] we want to transform this into [M][T2]
|
||||
// therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ] and we can push [T2]
|
||||
// down to the element
|
||||
// if we had [R][T][S][-T][M], then this was a rotated matrix-element
|
||||
// if we had [T1][M] we want to transform this into [M][T2]
|
||||
// therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ] and we can push [T2]
|
||||
// down to the element
|
||||
} else if ((N === 1 || (N > 1 && tlist.getItem(1).type !== 3)) &&
|
||||
tlist.getItem(0).type === 2) {
|
||||
operation = 2; // translate
|
||||
|
@ -695,43 +695,43 @@ export const recalculateDimensions = function (selected) {
|
|||
meqInv = meq.inverse();
|
||||
m = matrixMultiply(meqInv, oldxlate, meq);
|
||||
tlist.removeItem(0);
|
||||
// else if this child now has a matrix imposition (from a parent group)
|
||||
// we might be able to simplify
|
||||
// else if this child now has a matrix imposition (from a parent group)
|
||||
// we might be able to simplify
|
||||
} else if (N === 1 && tlist.getItem(0).type === 1 && !angle) {
|
||||
// Remap all point-based elements
|
||||
m = transformListToTransform(tlist).matrix;
|
||||
switch (selected.tagName) {
|
||||
case 'line':
|
||||
changes = {
|
||||
x1: selected.getAttribute('x1'),
|
||||
y1: selected.getAttribute('y1'),
|
||||
x2: selected.getAttribute('x2'),
|
||||
y2: selected.getAttribute('y2'),
|
||||
}
|
||||
// Fallthrough
|
||||
case 'polyline':
|
||||
case 'polygon':
|
||||
changes.points = selected.getAttribute('points');
|
||||
if (changes.points) {
|
||||
const list = selected.points;
|
||||
const len = list.numberOfItems;
|
||||
changes.points = new Array(len);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const pt = list.getItem(i);
|
||||
changes.points[i] = {x: pt.x, y: pt.y};
|
||||
case 'line':
|
||||
changes = {
|
||||
x1: selected.getAttribute('x1'),
|
||||
y1: selected.getAttribute('y1'),
|
||||
x2: selected.getAttribute('x2'),
|
||||
y2: selected.getAttribute('y2'),
|
||||
}
|
||||
}
|
||||
// Fallthrough
|
||||
case 'path':
|
||||
changes.d = selected.getAttribute('d');
|
||||
operation = 1;
|
||||
tlist.clear();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case 'polyline':
|
||||
case 'polygon':
|
||||
changes.points = selected.getAttribute('points');
|
||||
if (changes.points) {
|
||||
const list = selected.points;
|
||||
const len = list.numberOfItems;
|
||||
changes.points = new Array(len);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const pt = list.getItem(i);
|
||||
changes.points[i] = { x: pt.x, y: pt.y };
|
||||
}
|
||||
}
|
||||
// Fallthrough
|
||||
case 'path':
|
||||
changes.d = selected.getAttribute('d');
|
||||
operation = 1;
|
||||
tlist.clear();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// if it was a rotation, put the rotate back and return without a command
|
||||
// (this function has zero work to do for a rotate())
|
||||
// if it was a rotation, put the rotate back and return without a command
|
||||
// (this function has zero work to do for a rotate())
|
||||
} else {
|
||||
// operation = 4; // rotation
|
||||
if (angle) {
|
||||
|
@ -789,12 +789,12 @@ export const recalculateDimensions = function (selected) {
|
|||
}
|
||||
}
|
||||
}
|
||||
// [Rold][M][T][S][-T] became [Rold][M]
|
||||
// we want it to be [Rnew][M][Tr] where Tr is the
|
||||
// translation required to re-center it
|
||||
// Therefore, [Tr] = [M_inv][Rnew_inv][Rold][M]
|
||||
// [Rold][M][T][S][-T] became [Rold][M]
|
||||
// we want it to be [Rnew][M][Tr] where Tr is the
|
||||
// translation required to re-center it
|
||||
// Therefore, [Tr] = [M_inv][Rnew_inv][Rold][M]
|
||||
} else if (operation === 3 && angle) {
|
||||
const {matrix} = transformListToTransform(tlist);
|
||||
const { matrix } = transformListToTransform(tlist);
|
||||
const roldt = svgroot.createSVGTransform();
|
||||
roldt.setRotate(angle, oldcenter.x, oldcenter.y);
|
||||
const rold = roldt.matrix;
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
* @copyright 2010 Alexis Deveria, 2010 Jeff Schiller
|
||||
*/
|
||||
|
||||
import {isTouch, isWebkit} from '../common/browser.js'; // , isOpera
|
||||
import {getRotationAngle, getBBox, getStrokedBBox, isNullish} from './utilities.js';
|
||||
import {transformListToTransform, transformBox, transformPoint} from './math.js';
|
||||
import {getTransformList} from './svgtransformlist.js';
|
||||
import { isTouch, isWebkit } from '../common/browser.js'; // , isOpera
|
||||
import { getRotationAngle, getBBox, getStrokedBBox, isNullish } from './utilities.js';
|
||||
import { transformListToTransform, transformBox, transformPoint } from './math.js';
|
||||
import { getTransformList } from './svgtransformlist.js';
|
||||
|
||||
const $ = jQuery;
|
||||
|
||||
|
@ -28,7 +28,7 @@ export class Selector {
|
|||
* @param {Element} elem - DOM element associated with this selector
|
||||
* @param {module:utilities.BBoxObject} [bbox] - Optional bbox to use for initialization (prevents duplicate `getBBox` call).
|
||||
*/
|
||||
constructor (id, elem, bbox) {
|
||||
constructor(id, elem, bbox) {
|
||||
// this is the selector's unique number
|
||||
this.id = id;
|
||||
|
||||
|
@ -41,7 +41,7 @@ export class Selector {
|
|||
// this holds a reference to the <g> element that holds all visual elements of the selector
|
||||
this.selectorGroup = svgFactory_.createSVGElement({
|
||||
element: 'g',
|
||||
attr: {id: ('selectorGroup' + this.id)}
|
||||
attr: { id: ('selectorGroup' + this.id) }
|
||||
});
|
||||
|
||||
// this holds a reference to the path rect
|
||||
|
@ -80,7 +80,7 @@ export class Selector {
|
|||
* @param {module:utilities.BBoxObject} bbox - Optional bbox to use for reset (prevents duplicate getBBox call).
|
||||
* @returns {void}
|
||||
*/
|
||||
reset (e, bbox) {
|
||||
reset(e, bbox) {
|
||||
this.locked = true;
|
||||
this.selectedElement = e;
|
||||
this.resize(bbox);
|
||||
|
@ -92,7 +92,7 @@ export class Selector {
|
|||
* @param {boolean} show - Indicates whether grips should be shown or not
|
||||
* @returns {void}
|
||||
*/
|
||||
showGrips (show) {
|
||||
showGrips(show) {
|
||||
const bShow = show ? 'inline' : 'none';
|
||||
selectorManager_.selectorGripsGroup.setAttribute('display', bShow);
|
||||
const elem = this.selectedElement;
|
||||
|
@ -108,7 +108,8 @@ export class Selector {
|
|||
* @param {module:utilities.BBoxObject} [bbox] - BBox to use for resize (prevents duplicate getBBox call).
|
||||
* @returns {void}
|
||||
*/
|
||||
resize (bbox) {
|
||||
resize(bbox) {
|
||||
const dataStorage = svgFactory_.getDataStorage();
|
||||
const selectedBox = this.selectorRect,
|
||||
mgr = selectorManager_,
|
||||
selectedGrips = mgr.selectorGrips,
|
||||
|
@ -120,7 +121,7 @@ export class Selector {
|
|||
offset += (sw / 2);
|
||||
}
|
||||
|
||||
const {tagName} = selected;
|
||||
const { tagName } = selected;
|
||||
if (tagName === 'text') {
|
||||
offset += 2 / currentZoom;
|
||||
}
|
||||
|
@ -159,7 +160,7 @@ export class Selector {
|
|||
offset *= currentZoom;
|
||||
|
||||
const nbox = transformBox(l * currentZoom, t * currentZoom, w * currentZoom, h * currentZoom, m),
|
||||
{aabox} = nbox;
|
||||
{ aabox } = nbox;
|
||||
let nbax = aabox.x - offset,
|
||||
nbay = aabox.y - offset,
|
||||
nbaw = aabox.width + (offset * 2),
|
||||
|
@ -180,13 +181,13 @@ export class Selector {
|
|||
nbox.br = transformPoint(nbox.br.x, nbox.br.y, rotm);
|
||||
|
||||
// calculate the axis-aligned bbox
|
||||
const {tl} = nbox;
|
||||
const { tl } = nbox;
|
||||
let minx = tl.x,
|
||||
miny = tl.y,
|
||||
maxx = tl.x,
|
||||
maxy = tl.y;
|
||||
|
||||
const {min, max} = Math;
|
||||
const { min, max } = Math;
|
||||
|
||||
minx = min(minx, min(nbox.tr.x, min(nbox.bl.x, nbox.br.x))) - offset;
|
||||
miny = min(miny, min(nbox.tr.y, min(nbox.bl.y, nbox.br.y))) - offset;
|
||||
|
@ -242,7 +243,7 @@ export class Selector {
|
|||
* @param {Float} angle - Current rotation angle in degrees
|
||||
* @returns {void}
|
||||
*/
|
||||
static updateGripCursors (angle) {
|
||||
static updateGripCursors(angle) {
|
||||
const dirArr = Object.keys(selectorManager_.selectorGrips);
|
||||
let steps = Math.round(angle / 45);
|
||||
if (steps < 0) { steps += 8; }
|
||||
|
@ -263,7 +264,7 @@ export class SelectorManager {
|
|||
/**
|
||||
* Sets up properties and calls `initGroup`.
|
||||
*/
|
||||
constructor () {
|
||||
constructor() {
|
||||
// this will hold the <g> element that contains all selector rects/grips
|
||||
this.selectorParentGroup = null;
|
||||
|
||||
|
@ -299,7 +300,8 @@ export class SelectorManager {
|
|||
* Resets the parent selector group element.
|
||||
* @returns {void}
|
||||
*/
|
||||
initGroup () {
|
||||
initGroup() {
|
||||
const dataStorage = svgFactory_.getDataStorage();
|
||||
// remove old selector parent group if it existed
|
||||
if (this.selectorParentGroup && this.selectorParentGroup.parentNode) {
|
||||
this.selectorParentGroup.remove();
|
||||
|
@ -308,11 +310,11 @@ export class SelectorManager {
|
|||
// create parent selector group and add it to svgroot
|
||||
this.selectorParentGroup = svgFactory_.createSVGElement({
|
||||
element: 'g',
|
||||
attr: {id: 'selectorParentGroup'}
|
||||
attr: { id: 'selectorParentGroup' }
|
||||
});
|
||||
this.selectorGripsGroup = svgFactory_.createSVGElement({
|
||||
element: 'g',
|
||||
attr: {display: 'none'}
|
||||
attr: { display: 'none' }
|
||||
});
|
||||
this.selectorParentGroup.append(this.selectorGripsGroup);
|
||||
svgFactory_.svgRoot().append(this.selectorParentGroup);
|
||||
|
@ -416,7 +418,7 @@ export class SelectorManager {
|
|||
* @param {module:utilities.BBoxObject} [bbox] - Optional bbox to use for reset (prevents duplicate getBBox call).
|
||||
* @returns {Selector} The selector based on the given element
|
||||
*/
|
||||
requestSelector (elem, bbox) {
|
||||
requestSelector(elem, bbox) {
|
||||
if (isNullish(elem)) { return null; }
|
||||
|
||||
const N = this.selectors.length;
|
||||
|
@ -446,13 +448,13 @@ export class SelectorManager {
|
|||
* @param {Element} elem - DOM element to remove the selector for
|
||||
* @returns {void}
|
||||
*/
|
||||
releaseSelector (elem) {
|
||||
releaseSelector(elem) {
|
||||
if (isNullish(elem)) { return; }
|
||||
const N = this.selectors.length,
|
||||
sel = this.selectorMap[elem.id];
|
||||
if (sel && !sel.locked) {
|
||||
// TODO(codedread): Ensure this exists in this module.
|
||||
console.log('WARNING! selector was released but was already unlocked');
|
||||
console.log('WARNING! selector was released but was already unlocked');
|
||||
}
|
||||
for (let i = 0; i < N; ++i) {
|
||||
if (this.selectors[i] && this.selectors[i] === sel) {
|
||||
|
@ -464,7 +466,7 @@ export class SelectorManager {
|
|||
// remove from DOM and store reference in JS but only if it exists in the DOM
|
||||
try {
|
||||
sel.selectorGroup.setAttribute('display', 'none');
|
||||
} catch (e) {/* empty fn */}
|
||||
} catch (e) {/* empty fn */ }
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -475,7 +477,7 @@ export class SelectorManager {
|
|||
* @returns {SVGRectElement} The rubberBandBox DOM element. This is the rectangle drawn by
|
||||
* the user for selecting/zooming
|
||||
*/
|
||||
getRubberBandBox () {
|
||||
getRubberBandBox() {
|
||||
if (!this.rubberBandBox) {
|
||||
this.rubberBandBox =
|
||||
svgFactory_.createSVGElement({
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* @copyright 2010 Alexis Deveria, 2010 Jeff Schiller
|
||||
*/
|
||||
import jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute
|
||||
import {NS} from '../common/namespaces.js';
|
||||
import { NS } from '../common/namespaces.js';
|
||||
import * as hstry from './history.js';
|
||||
import * as pathModule from './path.js';
|
||||
import {
|
||||
|
@ -26,7 +26,7 @@ import {
|
|||
import {
|
||||
isGecko
|
||||
} from '../common/browser.js'; // , supportsEditableText
|
||||
import {getParents} from '../editor/components/jgraduate/Util.js';
|
||||
import { getParents } from '../editor/components/jgraduate/Util.js';
|
||||
|
||||
const {
|
||||
MoveElementCommand, BatchCommand, InsertElementCommand, RemoveElementCommand, ChangeElementCommand
|
||||
|
@ -80,7 +80,7 @@ export const moveToBottomSelectedElem = function () {
|
|||
let t = selected;
|
||||
const oldParent = t.parentNode;
|
||||
const oldNextSibling = t.nextSibling;
|
||||
let {firstChild} = t.parentNode;
|
||||
let { firstChild } = t.parentNode;
|
||||
if (firstChild.tagName === 'title') {
|
||||
firstChild = firstChild.nextSibling;
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ export const moveUpDownSelected = function (dir) {
|
|||
const list = elementContext_.getIntersectionList(getStrokedBBoxDefaultVisible([selected]));
|
||||
if (dir === 'Down') { list.reverse(); }
|
||||
|
||||
Array.prototype.forEach.call(list, function(el, i){
|
||||
Array.prototype.forEach.call(list, function (el, i) {
|
||||
if (!foundCur) {
|
||||
if (el === selected) {
|
||||
foundCur = true;
|
||||
|
@ -134,7 +134,7 @@ export const moveUpDownSelected = function (dir) {
|
|||
const t = selected;
|
||||
const oldParent = t.parentNode;
|
||||
const oldNextSibling = t.nextSibling;
|
||||
if(dir === 'Down') {
|
||||
if (dir === 'Down') {
|
||||
closest.insertAdjacentElement('beforebegin', t);
|
||||
} else {
|
||||
closest.insertAdjacentElement('afterend', t);
|
||||
|
@ -252,7 +252,7 @@ export const cloneSelectedElements = function (x, y) {
|
|||
* @param {Element} b
|
||||
* @returns {Integer}
|
||||
*/
|
||||
function sortfunction (a, b) {
|
||||
function sortfunction(a, b) {
|
||||
return (index(b) - index(a));
|
||||
}
|
||||
selectedElements.sort(sortfunction);
|
||||
|
@ -302,40 +302,40 @@ export const alignSelectedElements = function (type, relativeTo) {
|
|||
|
||||
// now bbox is axis-aligned and handles rotation
|
||||
switch (relativeTo) {
|
||||
case 'smallest':
|
||||
if (((type === 'l' || type === 'c' || type === 'r' || type === 'left' || type === 'center' || type === 'right') &&
|
||||
(curwidth === Number.MIN_VALUE || curwidth > bboxes[i].width)) ||
|
||||
((type === 't' || type === 'm' || type === 'b' || type === 'top' || type === 'middle' || type === 'bottom') &&
|
||||
(curheight === Number.MIN_VALUE || curheight > bboxes[i].height))
|
||||
) {
|
||||
minx = bboxes[i].x;
|
||||
miny = bboxes[i].y;
|
||||
maxx = bboxes[i].x + bboxes[i].width;
|
||||
maxy = bboxes[i].y + bboxes[i].height;
|
||||
curwidth = bboxes[i].width;
|
||||
curheight = bboxes[i].height;
|
||||
}
|
||||
break;
|
||||
case 'largest':
|
||||
if (((type === 'l' || type === 'c' || type === 'r' || type === 'left' || type === 'center' || type === 'right') &&
|
||||
(curwidth === Number.MIN_VALUE || curwidth < bboxes[i].width)) ||
|
||||
((type === 't' || type === 'm' || type === 'b' || type === 'top' || type === 'middle' || type === 'bottom') &&
|
||||
(curheight === Number.MIN_VALUE || curheight < bboxes[i].height))
|
||||
) {
|
||||
minx = bboxes[i].x;
|
||||
miny = bboxes[i].y;
|
||||
maxx = bboxes[i].x + bboxes[i].width;
|
||||
maxy = bboxes[i].y + bboxes[i].height;
|
||||
curwidth = bboxes[i].width;
|
||||
curheight = bboxes[i].height;
|
||||
}
|
||||
break;
|
||||
default: // 'selected'
|
||||
if (bboxes[i].x < minx) { minx = bboxes[i].x; }
|
||||
if (bboxes[i].y < miny) { miny = bboxes[i].y; }
|
||||
if (bboxes[i].x + bboxes[i].width > maxx) { maxx = bboxes[i].x + bboxes[i].width; }
|
||||
if (bboxes[i].y + bboxes[i].height > maxy) { maxy = bboxes[i].y + bboxes[i].height; }
|
||||
break;
|
||||
case 'smallest':
|
||||
if (((type === 'l' || type === 'c' || type === 'r' || type === 'left' || type === 'center' || type === 'right') &&
|
||||
(curwidth === Number.MIN_VALUE || curwidth > bboxes[i].width)) ||
|
||||
((type === 't' || type === 'm' || type === 'b' || type === 'top' || type === 'middle' || type === 'bottom') &&
|
||||
(curheight === Number.MIN_VALUE || curheight > bboxes[i].height))
|
||||
) {
|
||||
minx = bboxes[i].x;
|
||||
miny = bboxes[i].y;
|
||||
maxx = bboxes[i].x + bboxes[i].width;
|
||||
maxy = bboxes[i].y + bboxes[i].height;
|
||||
curwidth = bboxes[i].width;
|
||||
curheight = bboxes[i].height;
|
||||
}
|
||||
break;
|
||||
case 'largest':
|
||||
if (((type === 'l' || type === 'c' || type === 'r' || type === 'left' || type === 'center' || type === 'right') &&
|
||||
(curwidth === Number.MIN_VALUE || curwidth < bboxes[i].width)) ||
|
||||
((type === 't' || type === 'm' || type === 'b' || type === 'top' || type === 'middle' || type === 'bottom') &&
|
||||
(curheight === Number.MIN_VALUE || curheight < bboxes[i].height))
|
||||
) {
|
||||
minx = bboxes[i].x;
|
||||
miny = bboxes[i].y;
|
||||
maxx = bboxes[i].x + bboxes[i].width;
|
||||
maxy = bboxes[i].y + bboxes[i].height;
|
||||
curwidth = bboxes[i].width;
|
||||
curheight = bboxes[i].height;
|
||||
}
|
||||
break;
|
||||
default: // 'selected'
|
||||
if (bboxes[i].x < minx) { minx = bboxes[i].x; }
|
||||
if (bboxes[i].y < miny) { miny = bboxes[i].y; }
|
||||
if (bboxes[i].x + bboxes[i].width > maxx) { maxx = bboxes[i].x + bboxes[i].width; }
|
||||
if (bboxes[i].y + bboxes[i].height > maxy) { maxy = bboxes[i].y + bboxes[i].height; }
|
||||
break;
|
||||
}
|
||||
} // loop for each element to find the bbox and adjust min/max
|
||||
|
||||
|
@ -355,30 +355,30 @@ export const alignSelectedElements = function (type, relativeTo) {
|
|||
dx[i] = 0;
|
||||
dy[i] = 0;
|
||||
switch (type) {
|
||||
case 'l': // left (horizontal)
|
||||
case 'left': // left (horizontal)
|
||||
dx[i] = minx - bbox.x;
|
||||
break;
|
||||
case 'c': // center (horizontal)
|
||||
case 'center': // center (horizontal)
|
||||
dx[i] = (minx + maxx) / 2 - (bbox.x + bbox.width / 2);
|
||||
break;
|
||||
case 'r': // right (horizontal)
|
||||
case 'right': // right (horizontal)
|
||||
dx[i] = maxx - (bbox.x + bbox.width);
|
||||
break;
|
||||
case 't': // top (vertical)
|
||||
case 'top': // top (vertical)
|
||||
dy[i] = miny - bbox.y;
|
||||
break;
|
||||
case 'm': // middle (vertical)
|
||||
case 'middle': // middle (vertical)
|
||||
dy[i] = (miny + maxy) / 2 - (bbox.y + bbox.height / 2);
|
||||
break;
|
||||
case 'b': // bottom (vertical)
|
||||
case 'bottom': // bottom (vertical)
|
||||
dy[i] = maxy - (bbox.y + bbox.height);
|
||||
break;
|
||||
case 'l': // left (horizontal)
|
||||
case 'left': // left (horizontal)
|
||||
dx[i] = minx - bbox.x;
|
||||
break;
|
||||
case 'c': // center (horizontal)
|
||||
case 'center': // center (horizontal)
|
||||
dx[i] = (minx + maxx) / 2 - (bbox.x + bbox.width / 2);
|
||||
break;
|
||||
case 'r': // right (horizontal)
|
||||
case 'right': // right (horizontal)
|
||||
dx[i] = maxx - (bbox.x + bbox.width);
|
||||
break;
|
||||
case 't': // top (vertical)
|
||||
case 'top': // top (vertical)
|
||||
dy[i] = miny - bbox.y;
|
||||
break;
|
||||
case 'm': // middle (vertical)
|
||||
case 'middle': // middle (vertical)
|
||||
dy[i] = (miny + maxy) / 2 - (bbox.y + bbox.height / 2);
|
||||
break;
|
||||
case 'b': // bottom (vertical)
|
||||
case 'bottom': // bottom (vertical)
|
||||
dy[i] = maxy - (bbox.y + bbox.height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
moveSelectedElements(dx, dy);
|
||||
|
@ -416,7 +416,7 @@ export const deleteSelectedElements = function () {
|
|||
parent = parent.parentNode;
|
||||
}
|
||||
|
||||
const {nextSibling} = t;
|
||||
const { nextSibling } = t;
|
||||
t.remove();
|
||||
const elem = t;
|
||||
selectedCopy.push(selected); // for the copy
|
||||
|
@ -437,7 +437,7 @@ export const deleteSelectedElements = function () {
|
|||
export const copySelectedElements = function () {
|
||||
const selectedElements = elementContext_.getSelectedElements();
|
||||
const data =
|
||||
JSON.stringify(selectedElements.map((x) => elementContext_.getJsonFromSvgElement(x)));
|
||||
JSON.stringify(selectedElements.map((x) => elementContext_.getJsonFromSvgElement(x)));
|
||||
// Use sessionStorage for the clipboard data.
|
||||
sessionStorage.setItem(elementContext_.getClipboardID(), data);
|
||||
elementContext_.flashStorage();
|
||||
|
@ -461,15 +461,15 @@ export const groupSelectedElements = function (type, urlArg) {
|
|||
let url;
|
||||
|
||||
switch (type) {
|
||||
case 'a': {
|
||||
cmdStr = 'Make hyperlink';
|
||||
url = urlArg || '';
|
||||
break;
|
||||
} default: {
|
||||
type = 'g';
|
||||
cmdStr = 'Group Elements';
|
||||
break;
|
||||
}
|
||||
case 'a': {
|
||||
cmdStr = 'Make hyperlink';
|
||||
url = urlArg || '';
|
||||
break;
|
||||
} default: {
|
||||
type = 'g';
|
||||
cmdStr = 'Group Elements';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const batchCmd = new BatchCommand(cmdStr);
|
||||
|
@ -713,6 +713,7 @@ export const convertToGroup = function (elem) {
|
|||
const $elem = elem;
|
||||
const batchCmd = new BatchCommand();
|
||||
let ts;
|
||||
const dataStorage = elementContext_.getDataStorage();
|
||||
if (dataStorage.has($elem, 'gsvg')) {
|
||||
// Use the gsvg as the new group
|
||||
const svg = elem.firstChild;
|
||||
|
@ -799,7 +800,7 @@ export const convertToGroup = function (elem) {
|
|||
if (parent) {
|
||||
if (!hasMore) {
|
||||
// remove symbol/svg element
|
||||
const {nextSibling} = elem;
|
||||
const { nextSibling } = elem;
|
||||
elem.remove();
|
||||
batchCmd.addSubCommand(new RemoveElementCommand(elem, nextSibling, parent));
|
||||
}
|
||||
|
@ -820,13 +821,13 @@ export const convertToGroup = function (elem) {
|
|||
try {
|
||||
recalculateDimensions(n);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
// Give ID for any visible element missing one
|
||||
const visElems = g.querySelectorAll(elementContext_.getVisElems());
|
||||
Array.prototype.forEach.call(visElems, function(el, i){
|
||||
Array.prototype.forEach.call(visElems, function (el, i) {
|
||||
if (!el.id) { el.id = elementContext_.getNextId(); }
|
||||
});
|
||||
|
||||
|
@ -839,7 +840,7 @@ export const convertToGroup = function (elem) {
|
|||
|
||||
elementContext_.addCommandToHistory(batchCmd);
|
||||
} else {
|
||||
console.log('Unexpected element to ungroup:', elem);
|
||||
console.log('Unexpected element to ungroup:', elem);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -851,6 +852,7 @@ export const convertToGroup = function (elem) {
|
|||
*/
|
||||
export const ungroupSelectedElement = function () {
|
||||
const selectedElements = elementContext_.getSelectedElements();
|
||||
const dataStorage = elementContext_.getDataStorage();
|
||||
let g = selectedElements[0];
|
||||
if (!g) {
|
||||
return;
|
||||
|
@ -891,7 +893,7 @@ export const ungroupSelectedElement = function () {
|
|||
|
||||
// Remove child title elements
|
||||
if (elem.tagName === 'title') {
|
||||
const {nextSibling} = elem;
|
||||
const { nextSibling } = elem;
|
||||
batchCmd.addSubCommand(new RemoveElementCommand(elem, nextSibling, oldParent));
|
||||
elem.remove();
|
||||
continue;
|
||||
|
@ -979,9 +981,9 @@ export const updateCanvas = function (w, h) {
|
|||
/**
|
||||
* @type {module:svgcanvas.SvgCanvas#event:ext_canvasUpdated}
|
||||
*/
|
||||
{new_x: x, new_y: y, old_x: oldX, old_y: oldY, d_x: x - oldX, d_y: y - oldY}
|
||||
{ new_x: x, new_y: y, old_x: oldX, old_y: oldY, d_x: x - oldX, d_y: y - oldY }
|
||||
);
|
||||
return {x, y, old_x: oldX, old_y: oldY, d_x: x - oldX, d_y: y - oldY};
|
||||
return { x, y, old_x: oldX, old_y: oldY, d_x: x - oldX, d_y: y - oldY };
|
||||
};
|
||||
/**
|
||||
* Select the next/previous element within the current layer.
|
||||
|
|
|
@ -6,19 +6,19 @@
|
|||
* @copyright 2011 Jeff Schiller
|
||||
*/
|
||||
|
||||
import {NS} from '../common/namespaces.js';
|
||||
import { NS } from '../common/namespaces.js';
|
||||
import {
|
||||
isNullish, getBBox as utilsGetBBox, getStrokedBBoxDefaultVisible
|
||||
} from './utilities.js';
|
||||
import {transformPoint, transformListToTransform, rectsIntersect} from './math.js';
|
||||
import { transformPoint, transformListToTransform, rectsIntersect } from './math.js';
|
||||
import jQueryPluginSVG from './jQuery.attr.js';
|
||||
import {
|
||||
getTransformList
|
||||
} from './svgtransformlist.js';
|
||||
import * as hstry from './history.js';
|
||||
import {getClosest} from '../editor/components/jgraduate/Util.js';
|
||||
import { getClosest } from '../editor/components/jgraduate/Util.js';
|
||||
|
||||
const {BatchCommand} = hstry;
|
||||
const { BatchCommand } = hstry;
|
||||
const $ = jQueryPluginSVG(jQuery);
|
||||
let selectionContext_ = null;
|
||||
|
||||
|
@ -140,7 +140,7 @@ export const getMouseTargetMethod = function (evt) {
|
|||
// for foreign content, go up until we find the foreignObject
|
||||
// WebKit browsers set the mouse target to the svgcanvas div
|
||||
if ([NS.MATH, NS.HTML].includes(mouseTarget.namespaceURI) &&
|
||||
mouseTarget.id !== 'svgcanvas'
|
||||
mouseTarget.id !== 'svgcanvas'
|
||||
) {
|
||||
while (mouseTarget.nodeName !== 'foreignObject') {
|
||||
mouseTarget = mouseTarget.parentNode;
|
||||
|
@ -243,9 +243,9 @@ export const getVisibleElementsAndBBoxes = function (parent) {
|
|||
}
|
||||
const contentElems = [];
|
||||
const elements = parent.children;
|
||||
Array.prototype.forEach.call(elements, function(elem, i){
|
||||
Array.prototype.forEach.call(elements, function (elem, i) {
|
||||
if (elem.getBBox) {
|
||||
contentElems.push({elem, bbox: getStrokedBBoxDefaultVisible([elem])});
|
||||
contentElems.push({ elem, bbox: getStrokedBBoxDefaultVisible([elem]) });
|
||||
}
|
||||
});
|
||||
return contentElems.reverse();
|
||||
|
@ -324,6 +324,7 @@ export const getIntersectionListMethod = function (rect) {
|
|||
* @returns {void}
|
||||
*/
|
||||
export const groupSvgElem = function (elem) {
|
||||
const dataStorage = selectionContext_.getDataStorage();
|
||||
const g = document.createElementNS(NS.SVG, 'g');
|
||||
elem.replaceWith(g);
|
||||
g.appendChild(elem);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* @copyright 2011 Jeff Schiller
|
||||
*/
|
||||
|
||||
import {jsPDF} from 'jspdf/dist/jspdf.es.min.js';
|
||||
import { jsPDF } from 'jspdf/dist/jspdf.es.min.js';
|
||||
import 'svg2pdf.js/dist/svg2pdf.es.js';
|
||||
import jQueryPluginSVG from './jQuery.attr.js';
|
||||
import * as hstry from './history.js';
|
||||
|
@ -18,18 +18,18 @@ import {
|
|||
import {
|
||||
transformPoint, transformListToTransform
|
||||
} from './math.js';
|
||||
import {resetListMap} from './svgtransformlist.js';
|
||||
import { resetListMap } from './svgtransformlist.js';
|
||||
import {
|
||||
convertUnit, shortFloat, convertToNum
|
||||
} from '../common/units.js';
|
||||
import {isGecko, isChrome, isWebkit} from '../common/browser.js';
|
||||
import { isGecko, isChrome, isWebkit } from '../common/browser.js';
|
||||
import * as pathModule from './path.js';
|
||||
import {NS} from '../common/namespaces.js';
|
||||
import { NS } from '../common/namespaces.js';
|
||||
import * as draw from './draw.js';
|
||||
import {
|
||||
recalculateDimensions
|
||||
} from './recalculate.js';
|
||||
import {getParents, getClosest} from '../editor/components/jgraduate/Util.js';
|
||||
import { getParents, getClosest } from '../editor/components/jgraduate/Util.js';
|
||||
|
||||
const {
|
||||
InsertElementCommand, RemoveElementCommand,
|
||||
|
@ -59,13 +59,13 @@ export const init = function (svgContext) {
|
|||
*/
|
||||
export const svgCanvasToString = function () {
|
||||
// keep calling it until there are none to remove
|
||||
while (svgContext_.getCanvas().removeUnusedDefElems() > 0) {} // eslint-disable-line no-empty
|
||||
while (svgContext_.getCanvas().removeUnusedDefElems() > 0) { } // eslint-disable-line no-empty
|
||||
|
||||
svgContext_.getCanvas().pathActions.clear(true);
|
||||
|
||||
// Keep SVG-Edit comment on top
|
||||
const childNodesElems = svgContext_.getSVGContent().childNodes;
|
||||
childNodesElems.forEach(function(node, i){
|
||||
childNodesElems.forEach(function (node, i) {
|
||||
if (i && node.nodeType === 8 && node.data.includes('Created with')) {
|
||||
svgContext_.getSVGContent().firstChild.before(node);
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ export const svgCanvasToString = function () {
|
|||
|
||||
// Unwrap gsvg if it has no special attributes (only id and style)
|
||||
const gsvgElems = svgContext_.getSVGContent().querySelectorAll('g[data-gsvg]');
|
||||
Array.prototype.forEach.call(gsvgElems, function(element, i){
|
||||
Array.prototype.forEach.call(gsvgElems, function (element, i) {
|
||||
const attrs = element.attributes;
|
||||
let len = attrs.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
|
@ -100,7 +100,7 @@ export const svgCanvasToString = function () {
|
|||
|
||||
// Rewrap gsvg
|
||||
if (nakedSvgs.length) {
|
||||
Array.prototype.forEach.call(nakedSvgs, function(el, i){
|
||||
Array.prototype.forEach.call(nakedSvgs, function (el, i) {
|
||||
svgContext_.getCanvas().groupSvgElem(el);
|
||||
});
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ export const svgToString = function (elem, indent) {
|
|||
const csElements = elem.querySelectorAll('*');
|
||||
const cElements = Array.prototype.slice.call(csElements);
|
||||
cElements.push(elem);
|
||||
Array.prototype.forEach.call(cElements, function(el, i){
|
||||
Array.prototype.forEach.call(cElements, function (el, i) {
|
||||
// const el = this;
|
||||
// for some elements have no attribute
|
||||
const uri = el.namespaceURI;
|
||||
|
@ -170,7 +170,7 @@ export const svgToString = function (elem, indent) {
|
|||
nsuris[uri] = true;
|
||||
out.push(' xmlns:' + nsMap[uri] + '="' + uri + '"');
|
||||
}
|
||||
if(el.attributes.length > 0) {
|
||||
if (el.attributes.length > 0) {
|
||||
for (const [i, attr] of Object.entries(el.attributes)) {
|
||||
const u = attr.namespaceURI;
|
||||
if (u && !nsuris[u] && nsMap[u] !== 'xmlns' && nsMap[u] !== 'xml') {
|
||||
|
@ -224,10 +224,10 @@ export const svgToString = function (elem, indent) {
|
|||
|
||||
// Embed images when saving
|
||||
if (svgContext_.getSvgOptionApply() &&
|
||||
elem.nodeName === 'image' &&
|
||||
attr.localName === 'href' &&
|
||||
svgContext_.getSvgOptionImages() &&
|
||||
svgContext_.getSvgOptionImages() === 'embed'
|
||||
elem.nodeName === 'image' &&
|
||||
attr.localName === 'href' &&
|
||||
svgContext_.getSvgOptionImages() &&
|
||||
svgContext_.getSvgOptionImages() === 'embed'
|
||||
) {
|
||||
const img = svgContext_.getEncodableImages(attrVal);
|
||||
if (img) { attrVal = img; }
|
||||
|
@ -251,31 +251,31 @@ export const svgToString = function (elem, indent) {
|
|||
for (let i = 0; i < childs.length; i++) {
|
||||
const child = childs.item(i);
|
||||
switch (child.nodeType) {
|
||||
case 1: // element node
|
||||
out.push('\n');
|
||||
out.push(this.svgToString(child, indent));
|
||||
break;
|
||||
case 3: { // text node
|
||||
const str = child.nodeValue.replace(/^\s+|\s+$/g, '');
|
||||
if (str !== '') {
|
||||
bOneLine = true;
|
||||
out.push(String(toXml(str)));
|
||||
}
|
||||
break;
|
||||
} case 4: // cdata node
|
||||
out.push('\n');
|
||||
out.push(new Array(indent + 1).join(' '));
|
||||
out.push('<![CDATA[');
|
||||
out.push(child.nodeValue);
|
||||
out.push(']]>');
|
||||
break;
|
||||
case 8: // comment
|
||||
out.push('\n');
|
||||
out.push(new Array(indent + 1).join(' '));
|
||||
out.push('<!--');
|
||||
out.push(child.data);
|
||||
out.push('-->');
|
||||
break;
|
||||
case 1: // element node
|
||||
out.push('\n');
|
||||
out.push(this.svgToString(child, indent));
|
||||
break;
|
||||
case 3: { // text node
|
||||
const str = child.nodeValue.replace(/^\s+|\s+$/g, '');
|
||||
if (str !== '') {
|
||||
bOneLine = true;
|
||||
out.push(String(toXml(str)));
|
||||
}
|
||||
break;
|
||||
} case 4: // cdata node
|
||||
out.push('\n');
|
||||
out.push(new Array(indent + 1).join(' '));
|
||||
out.push('<![CDATA[');
|
||||
out.push(child.nodeValue);
|
||||
out.push(']]>');
|
||||
break;
|
||||
case 8: // comment
|
||||
out.push('\n');
|
||||
out.push(new Array(indent + 1).join(' '));
|
||||
out.push('<!--');
|
||||
out.push(child.data);
|
||||
out.push('-->');
|
||||
break;
|
||||
} // switch on node type
|
||||
}
|
||||
indent--;
|
||||
|
@ -306,11 +306,12 @@ export const svgToString = function (elem, indent) {
|
|||
*/
|
||||
export const setSvgString = function (xmlString, preventUndo) {
|
||||
const curConfig = svgContext_.getCurConfig();
|
||||
const dataStorage = svgContext_.getDataStorage();
|
||||
try {
|
||||
// convert string into XML document
|
||||
const newDoc = text2xml(xmlString);
|
||||
if (newDoc.firstElementChild &&
|
||||
newDoc.firstElementChild.namespaceURI !== NS.SVG) {
|
||||
newDoc.firstElementChild.namespaceURI !== NS.SVG) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -319,7 +320,7 @@ export const setSvgString = function (xmlString, preventUndo) {
|
|||
const batchCmd = new BatchCommand('Change Source');
|
||||
|
||||
// remove old svg document
|
||||
const {nextSibling} = svgContext_.getSVGContent();
|
||||
const { nextSibling } = svgContext_.getSVGContent();
|
||||
|
||||
svgContext_.getSVGContent().remove();
|
||||
const oldzoom = svgContext_.getSVGContent();
|
||||
|
@ -348,7 +349,7 @@ export const setSvgString = function (xmlString, preventUndo) {
|
|||
|
||||
// change image href vals if possible
|
||||
const elements = content.querySelectorAll('image');
|
||||
Array.prototype.forEach.call(elements, function(image, i){
|
||||
Array.prototype.forEach.call(elements, function (image, i) {
|
||||
preventClickDefault(image);
|
||||
const val = svgContext_.getCanvas().getHref(this);
|
||||
if (val) {
|
||||
|
@ -373,7 +374,7 @@ export const setSvgString = function (xmlString, preventUndo) {
|
|||
|
||||
// Wrap child SVGs in group elements
|
||||
const svgElements = content.querySelectorAll('svg');
|
||||
Array.prototype.forEach.call(svgElements, function(element, i){
|
||||
Array.prototype.forEach.call(svgElements, function (element, i) {
|
||||
// Skip if it's in a <defs>
|
||||
if (getClosest(element.parentNode, 'defs')) { return; }
|
||||
|
||||
|
@ -393,7 +394,7 @@ export const setSvgString = function (xmlString, preventUndo) {
|
|||
if (isGecko()) {
|
||||
const svgDefs = findDefs();
|
||||
const findElems = content.querySelectorAll('linearGradient, radialGradient, pattern');
|
||||
Array.prototype.forEach.call(findElems, function(ele, i){
|
||||
Array.prototype.forEach.call(findElems, function (ele, i) {
|
||||
svgDefs.appendChild(ele);
|
||||
});
|
||||
}
|
||||
|
@ -420,7 +421,7 @@ export const setSvgString = function (xmlString, preventUndo) {
|
|||
attrs.height = vb[3];
|
||||
// handle content that doesn't have a viewBox
|
||||
} else {
|
||||
['width', 'height'].forEach(function(dim, i){
|
||||
['width', 'height'].forEach(function (dim, i) {
|
||||
// Set to 100 if not given
|
||||
const val = content.getAttribute(dim) || '100%';
|
||||
if (String(val).substr(-1) === '%') {
|
||||
|
@ -437,9 +438,9 @@ export const setSvgString = function (xmlString, preventUndo) {
|
|||
|
||||
// Give ID for any visible layer children missing one
|
||||
const chiElems = content.children;
|
||||
Array.prototype.forEach.call(chiElems, function(chiElem, i){
|
||||
Array.prototype.forEach.call(chiElems, function (chiElem, i) {
|
||||
const visElems = chiElem.querySelectorAll(svgContext_.getVisElems());
|
||||
Array.prototype.forEach.call(visElems, function(elem, i){
|
||||
Array.prototype.forEach.call(visElems, function (elem, i) {
|
||||
if (!elem.id) { elem.id = svgContext_.getCanvas().getNextId(); }
|
||||
});
|
||||
});
|
||||
|
@ -466,7 +467,7 @@ export const setSvgString = function (xmlString, preventUndo) {
|
|||
// update root to the correct size
|
||||
const width = content.getAttribute('width');
|
||||
const height = content.getAttribute('height');
|
||||
const changes = {width: width, height: height};
|
||||
const changes = { width: width, height: height };
|
||||
batchCmd.addSubCommand(new ChangeElementCommand(svgContext_.getSVGRoot(), changes));
|
||||
|
||||
// reset zoom
|
||||
|
@ -481,7 +482,7 @@ export const setSvgString = function (xmlString, preventUndo) {
|
|||
if (!preventUndo) svgContext_.addCommandToHistory(batchCmd);
|
||||
svgContext_.call('changed', [svgContext_.getSVGContent()]);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -503,7 +504,7 @@ export const setSvgString = function (xmlString, preventUndo) {
|
|||
* was obtained
|
||||
*/
|
||||
export const importSvgString = function (xmlString) {
|
||||
console.log('importSvgString --> ', xmlString);
|
||||
const dataStorage = svgContext_.getDataStorage();
|
||||
let j, ts, useEl;
|
||||
try {
|
||||
// Get unique ID
|
||||
|
@ -513,7 +514,7 @@ export const importSvgString = function (xmlString) {
|
|||
// Look for symbol and make sure symbol exists in image
|
||||
if (svgContext_.getImportIds(uid) && svgContext_.getImportIds(uid).symbol) {
|
||||
const parents = getParents(svgContext_.getImportIds(uid).symbol, '#svgroot');
|
||||
if(parents.length){
|
||||
if (parents.length) {
|
||||
useExisting = true;
|
||||
}
|
||||
}
|
||||
|
@ -521,7 +522,7 @@ export const importSvgString = function (xmlString) {
|
|||
const batchCmd = new BatchCommand('Import Image');
|
||||
let symbol;
|
||||
if (useExisting) {
|
||||
({symbol} = svgContext_.getImportIds());
|
||||
({ symbol } = svgContext_.getImportIds());
|
||||
ts = svgContext_.getImportIds(uid).xform;
|
||||
} else {
|
||||
// convert string into XML document
|
||||
|
@ -564,7 +565,7 @@ export const importSvgString = function (xmlString) {
|
|||
// https://bugzilla.mozilla.org/show_bug.cgi?id=353575
|
||||
// TODO: Make this properly undo-able.
|
||||
const elements = svg.querySelectorAll('linearGradient, radialGradient, pattern');
|
||||
Array.prototype.forEach.call(elements, function(el, i){
|
||||
Array.prototype.forEach.call(elements, function (el, i) {
|
||||
defs.appendChild(el);
|
||||
});
|
||||
}
|
||||
|
@ -610,7 +611,7 @@ export const importSvgString = function (xmlString) {
|
|||
svgContext_.addCommandToHistory(batchCmd);
|
||||
svgContext_.call('changed', [svgContext_.getSVGContent()]);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -689,7 +690,7 @@ export const save = function (opts) {
|
|||
* Codes only is useful for locale-independent detection.
|
||||
* @returns {module:svgcanvas.IssuesAndCodes}
|
||||
*/
|
||||
function getIssues () {
|
||||
function getIssues() {
|
||||
const uiStrings = svgContext_.getUIStrings();
|
||||
// remove the selected outline before serializing
|
||||
svgContext_.getCanvas().clearSelection();
|
||||
|
@ -717,7 +718,7 @@ function getIssues () {
|
|||
issues.push(descr);
|
||||
}
|
||||
}
|
||||
return {issues, issueCodes};
|
||||
return { issues, issueCodes };
|
||||
}
|
||||
/**
|
||||
* @typedef {PlainObject} module:svgcanvas.ImageExportedResults
|
||||
|
@ -749,7 +750,7 @@ function getIssues () {
|
|||
export const rasterExport = async function (imgType, quality, exportWindowName, opts = {}) {
|
||||
const type = imgType === 'ICO' ? 'BMP' : (imgType || 'PNG');
|
||||
const mimeType = 'image/' + type.toLowerCase();
|
||||
const {issues, issueCodes} = getIssues();
|
||||
const { issues, issueCodes } = getIssues();
|
||||
const svg = this.svgCanvasToString();
|
||||
|
||||
if (!$id('export_canvas')) {
|
||||
|
@ -777,7 +778,7 @@ export const rasterExport = async function (imgType, quality, exportWindowName,
|
|||
* Called when `bloburl` is available for export.
|
||||
* @returns {void}
|
||||
*/
|
||||
function done () {
|
||||
function done() {
|
||||
const obj = {
|
||||
datauri, bloburl, svg, issues, issueCodes, type: imgType,
|
||||
mimeType, quality, exportWindowName
|
||||
|
@ -854,17 +855,17 @@ export const exportPDF = async (
|
|||
keywords: '',
|
||||
creator: '' */
|
||||
});
|
||||
const {issues, issueCodes} = getIssues();
|
||||
const { issues, issueCodes } = getIssues();
|
||||
// const svg = this.svgCanvasToString();
|
||||
// await doc.addSvgAsImage(svg)
|
||||
await doc.svg(svgContext_.getSVGContent(), {x: 0, y: 0, width: res.w, height: res.h});
|
||||
await doc.svg(svgContext_.getSVGContent(), { x: 0, y: 0, width: res.w, height: res.h });
|
||||
|
||||
// doc.output('save'); // Works to open in a new
|
||||
// window; todo: configure this and other export
|
||||
// options to optionally work in this manner as
|
||||
// opposed to opening a new tab
|
||||
outputType = outputType || 'dataurlstring';
|
||||
const obj = {issues, issueCodes, exportWindowName, outputType};
|
||||
const obj = { issues, issueCodes, exportWindowName, outputType };
|
||||
obj.output = doc.output(outputType, outputType === 'save' ? (exportWindowName || 'svg.pdf') : undefined);
|
||||
svgContext_.call('exportedPDF', obj);
|
||||
return obj;
|
||||
|
@ -895,7 +896,7 @@ export const uniquifyElemsMethod = function (g) {
|
|||
// and we haven't tracked this ID yet
|
||||
if (!(n.id in ids)) {
|
||||
// add this id to our map
|
||||
ids[n.id] = {elem: null, attrs: [], hrefs: []};
|
||||
ids[n.id] = { elem: null, attrs: [], hrefs: [] };
|
||||
}
|
||||
ids[n.id].elem = n;
|
||||
}
|
||||
|
@ -911,7 +912,7 @@ export const uniquifyElemsMethod = function (g) {
|
|||
if (refid) {
|
||||
if (!(refid in ids)) {
|
||||
// add this id to our map
|
||||
ids[refid] = {elem: null, attrs: [], hrefs: []};
|
||||
ids[refid] = { elem: null, attrs: [], hrefs: [] };
|
||||
}
|
||||
ids[refid].attrs.push(attrnode);
|
||||
}
|
||||
|
@ -926,7 +927,7 @@ export const uniquifyElemsMethod = function (g) {
|
|||
if (refid) {
|
||||
if (!(refid in ids)) {
|
||||
// add this id to our map
|
||||
ids[refid] = {elem: null, attrs: [], hrefs: []};
|
||||
ids[refid] = { elem: null, attrs: [], hrefs: [] };
|
||||
}
|
||||
ids[refid].hrefs.push(n);
|
||||
}
|
||||
|
@ -937,7 +938,7 @@ export const uniquifyElemsMethod = function (g) {
|
|||
// in ids, we now have a map of ids, elements and attributes, let's re-identify
|
||||
for (const oldid in ids) {
|
||||
if (!oldid) { continue; }
|
||||
const {elem} = ids[oldid];
|
||||
const { elem } = ids[oldid];
|
||||
if (elem) {
|
||||
const newid = svgContext_.getCanvas().getNextId();
|
||||
|
||||
|
@ -945,7 +946,7 @@ export const uniquifyElemsMethod = function (g) {
|
|||
elem.id = newid;
|
||||
|
||||
// remap all url() attributes
|
||||
const {attrs} = ids[oldid];
|
||||
const { attrs } = ids[oldid];
|
||||
let j = attrs.length;
|
||||
while (j--) {
|
||||
const attr = attrs[j];
|
||||
|
@ -977,7 +978,8 @@ export const setUseDataMethod = function (parent) {
|
|||
elems = elems.querySelectorAll('use');
|
||||
}
|
||||
|
||||
Array.prototype.forEach.call(elems, function(el, _){
|
||||
Array.prototype.forEach.call(elems, function (el, _) {
|
||||
const dataStorage = svgContext_.getDataStorage();
|
||||
const id = svgContext_.getCanvas().getHref(el).substr(1);
|
||||
const refElem = svgContext_.getCanvas().getElem(id);
|
||||
if (!refElem) { return; }
|
||||
|
@ -1026,12 +1028,12 @@ export const removeUnusedDefElemsMethod = function () {
|
|||
}
|
||||
}
|
||||
|
||||
Array.prototype.forEach.call(defs, function(def, i){
|
||||
Array.prototype.forEach.call(defs, function (def, i) {
|
||||
const defelems = def.querySelectorAll('linearGradient, radialGradient, filter, marker, svg, symbol');
|
||||
i = defelems.length;
|
||||
while (i--) {
|
||||
const defelem = defelems[i];
|
||||
const {id} = defelem;
|
||||
const { id } = defelem;
|
||||
if (!defelemUses.includes(id)) {
|
||||
// Not found, so remove (but remember)
|
||||
svgContext_.setRemovedElements(id, defelem);
|
||||
|
@ -1058,7 +1060,7 @@ export const convertGradientsMethod = function (elem) {
|
|||
});
|
||||
}
|
||||
|
||||
Array.prototype.forEach.call(elems, function(grad, i){
|
||||
Array.prototype.forEach.call(elems, function (grad, i) {
|
||||
if (grad.getAttribute('gradientUnits') === 'userSpaceOnUse') {
|
||||
const svgcontent = svgContext_.getSVGContent();
|
||||
// TODO: Support more than one element with this ref by duplicating parent grad
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import {Canvg as canvg} from 'canvg';
|
||||
import { Canvg as canvg } from 'canvg';
|
||||
import 'pathseg';
|
||||
|
||||
import jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`
|
||||
|
@ -28,7 +28,7 @@ import {
|
|||
setLayerVisibility, moveSelectedToLayer, mergeLayer, mergeAllLayers,
|
||||
leaveContext, setContext
|
||||
} from './draw.js';
|
||||
import {svgRootElement} from './svgroot.js';
|
||||
import { svgRootElement } from './svgroot.js';
|
||||
import {
|
||||
init as undoInit, getUndoManager, changeSelectedAttributeNoUndoMethod,
|
||||
changeSelectedAttributeMethod, ffClone
|
||||
|
@ -45,7 +45,7 @@ import {
|
|||
init as eventInit, mouseMoveEvent, mouseUpEvent,
|
||||
dblClickEvent, mouseDownEvent, DOMMouseScrollEvent
|
||||
} from './event.js';
|
||||
import {init as jsonInit, getJsonFromSvgElements, addSVGElementsFromJson} from './json.js';
|
||||
import { init as jsonInit, getJsonFromSvgElements, addSVGElementsFromJson } from './json.js';
|
||||
import {
|
||||
init as elemInit, getResolutionMethod, getTitleMethod, setGroupTitleMethod,
|
||||
setDocumentTitleMethod, setResolutionMethod, getEditorNSMethod, setBBoxZoomMethod,
|
||||
|
@ -65,8 +65,8 @@ import {
|
|||
import {
|
||||
init as blurInit, setBlurNoUndo, setBlurOffsets, setBlur
|
||||
} from './blur-event.js';
|
||||
import {sanitizeSvg} from './sanitize.js';
|
||||
import {getReverseNS, NS} from '../common/namespaces.js';
|
||||
import { sanitizeSvg } from './sanitize.js';
|
||||
import { getReverseNS, NS } from '../common/namespaces.js';
|
||||
import {
|
||||
text2xml, assignAttributes, cleanupElement, getElem, getUrlFromAttr,
|
||||
findDefs, getHref, setHref, getRefElem, getRotationAngle, getPathBBox,
|
||||
|
@ -168,8 +168,8 @@ class SvgCanvas {
|
|||
* @param {HTMLElement} container - The container HTML element that should hold the SVG root element
|
||||
* @param {module:SVGeditor.configObj.curConfig} config - An object that contains configuration data
|
||||
*/
|
||||
constructor (container, config) {
|
||||
// Alias Namespace constants
|
||||
constructor(container, config) {
|
||||
// Alias Namespace constants
|
||||
|
||||
// Default configuration options
|
||||
const curConfig = {
|
||||
|
@ -184,7 +184,7 @@ class SvgCanvas {
|
|||
}
|
||||
|
||||
// Array with width/height of canvas
|
||||
const {dimensions} = curConfig;
|
||||
const { dimensions } = curConfig;
|
||||
|
||||
const canvas = this;
|
||||
|
||||
|
@ -193,6 +193,33 @@ class SvgCanvas {
|
|||
this.$qa = $qa;
|
||||
this.getClosest = getClosest;
|
||||
this.getParents = getParents;
|
||||
/** A storage solution aimed at replacing jQuerys data function.
|
||||
* Implementation Note: Elements are stored in a (WeakMap)[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap].
|
||||
* This makes sure the data is garbage collected when the node is removed.
|
||||
*/
|
||||
this.dataStorage = {
|
||||
_storage: new WeakMap(),
|
||||
put: function (element, key, obj) {
|
||||
if (!this._storage.has(element)) {
|
||||
this._storage.set(element, new Map());
|
||||
}
|
||||
this._storage.get(element).set(key, obj);
|
||||
},
|
||||
get: function (element, key) {
|
||||
return this._storage.get(element).get(key);
|
||||
},
|
||||
has: function (element, key) {
|
||||
return this._storage.has(element) && this._storage.get(element).has(key);
|
||||
},
|
||||
remove: function (element, key) {
|
||||
var ret = this._storage.get(element).delete(key);
|
||||
if (!this._storage.get(element).size === 0) {
|
||||
this._storage.delete(element);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
const getDataStorage = this.getDataStorage = function () { return canvas.dataStorage; };
|
||||
|
||||
this.isLayer = draw.Layer.isLayer;
|
||||
|
||||
|
@ -229,10 +256,10 @@ class SvgCanvas {
|
|||
*/
|
||||
{
|
||||
getSVGContent,
|
||||
getDOMDocument () { return svgdoc; },
|
||||
getDOMContainer () { return container; },
|
||||
getDOMDocument() { return svgdoc; },
|
||||
getDOMContainer() { return container; },
|
||||
getSVGRoot,
|
||||
getCurConfig () { return curConfig; }
|
||||
getCurConfig() { return curConfig; }
|
||||
}
|
||||
);
|
||||
/**
|
||||
|
@ -318,10 +345,10 @@ class SvgCanvas {
|
|||
* @implements {module:json.jsonContext}
|
||||
*/
|
||||
{
|
||||
getDOMDocument () { return svgdoc; },
|
||||
getDrawing () { return getCurrentDrawing(); },
|
||||
getCurShape () { return curShape; },
|
||||
getCurrentGroup () { return currentGroup; }
|
||||
getDOMDocument() { return svgdoc; },
|
||||
getDrawing() { return getCurrentDrawing(); },
|
||||
getCurShape() { return curShape; },
|
||||
getCurrentGroup() { return currentGroup; }
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -367,9 +394,9 @@ class SvgCanvas {
|
|||
{
|
||||
getBaseUnit,
|
||||
getElement: getElem,
|
||||
getHeight () { return svgcontent.getAttribute('height') / currentZoom; },
|
||||
getWidth () { return svgcontent.getAttribute('width') / currentZoom; },
|
||||
getRoundDigits () { return saveOptions.round_digits; }
|
||||
getHeight() { return svgcontent.getAttribute('height') / currentZoom; },
|
||||
getWidth() { return svgcontent.getAttribute('width') / currentZoom; },
|
||||
getRoundDigits() { return saveOptions.round_digits; }
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -391,7 +418,7 @@ class SvgCanvas {
|
|||
selectedElements = [];
|
||||
};
|
||||
|
||||
const {pathActions} = pathModule;
|
||||
const { pathActions } = pathModule;
|
||||
|
||||
/**
|
||||
* This should actually be an intersection as all interfaces should be met.
|
||||
|
@ -407,12 +434,13 @@ class SvgCanvas {
|
|||
getSVGContent,
|
||||
addSVGElementFromJson,
|
||||
getSelectedElements,
|
||||
getDOMDocument () { return svgdoc; },
|
||||
getDOMContainer () { return container; },
|
||||
getDOMDocument() { return svgdoc; },
|
||||
getDOMContainer() { return container; },
|
||||
getSVGRoot,
|
||||
// TODO: replace this mostly with a way to get the current drawing.
|
||||
getBaseUnit,
|
||||
getSnappingStep () { return curConfig.snappingStep; }
|
||||
getSnappingStep() { return curConfig.snappingStep; },
|
||||
getDataStorage
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -439,7 +467,8 @@ class SvgCanvas {
|
|||
* @implements {module:coords.EditorContext}
|
||||
*/
|
||||
{
|
||||
getDrawing () { return getCurrentDrawing(); },
|
||||
getDrawing() { return getCurrentDrawing(); },
|
||||
getDataStorage,
|
||||
getSVGRoot,
|
||||
getGridSnapping
|
||||
}
|
||||
|
@ -452,8 +481,9 @@ class SvgCanvas {
|
|||
*/
|
||||
{
|
||||
getSVGRoot,
|
||||
getStartTransform () { return startTransform; },
|
||||
setStartTransform (transform) { startTransform = transform; }
|
||||
getStartTransform() { return startTransform; },
|
||||
setStartTransform(transform) { startTransform = transform; },
|
||||
getDataStorage
|
||||
}
|
||||
);
|
||||
this.recalculateDimensions = recalculateDimensions;
|
||||
|
@ -485,9 +515,10 @@ class SvgCanvas {
|
|||
* @implements {module:select.SVGFactory}
|
||||
*/
|
||||
{
|
||||
createSVGElement (jsonMap) { return canvas.addSVGElementFromJson(jsonMap); },
|
||||
svgRoot () { return svgroot; },
|
||||
svgContent () { return svgcontent; },
|
||||
createSVGElement(jsonMap) { return canvas.addSVGElementFromJson(jsonMap); },
|
||||
svgRoot() { return svgroot; },
|
||||
svgContent() { return svgcontent; },
|
||||
getDataStorage,
|
||||
getCurrentZoom
|
||||
}
|
||||
);
|
||||
|
@ -529,7 +560,7 @@ class SvgCanvas {
|
|||
const restoreRefElems = function (elem) {
|
||||
// Look for missing reference elements, restore any found
|
||||
let attrs = {};
|
||||
refAttrs.forEach(function(item, _){
|
||||
refAttrs.forEach(function (item, _) {
|
||||
attrs[item] = elem.getAttribute(item);
|
||||
});
|
||||
Object.values(attrs).forEach((val) => {
|
||||
|
@ -560,8 +591,8 @@ class SvgCanvas {
|
|||
call,
|
||||
restoreRefElems,
|
||||
getSVGContent,
|
||||
getCanvas () { return canvas; },
|
||||
getCurrentMode () { return currentMode; },
|
||||
getCanvas() { return canvas; },
|
||||
getCurrentMode() { return currentMode; },
|
||||
getCurrentZoom,
|
||||
getSVGRoot,
|
||||
getSelectedElements
|
||||
|
@ -588,21 +619,22 @@ class SvgCanvas {
|
|||
* @implements {module:selection.selectionContext}
|
||||
*/
|
||||
{
|
||||
getCanvas () { return canvas; },
|
||||
getCurrentGroup () { return currentGroup; },
|
||||
getCanvas() { return canvas; },
|
||||
getDataStorage,
|
||||
getCurrentGroup() { return currentGroup; },
|
||||
getSelectedElements,
|
||||
getSVGRoot,
|
||||
getSVGContent,
|
||||
getDOMContainer () { return container; },
|
||||
getExtensions () { return extensions; },
|
||||
setExtensions (key, value) { extensions[key] = value; },
|
||||
getDOMContainer() { return container; },
|
||||
getExtensions() { return extensions; },
|
||||
setExtensions(key, value) { extensions[key] = value; },
|
||||
getCurrentZoom,
|
||||
getRubberBox () { return rubberBox; },
|
||||
setCurBBoxes (value) { curBBoxes = value; },
|
||||
getCurBBoxes (value) { return curBBoxes; },
|
||||
getCurrentResizeMode () { return currentResizeMode; },
|
||||
getRubberBox() { return rubberBox; },
|
||||
setCurBBoxes(value) { curBBoxes = value; },
|
||||
getCurBBoxes(value) { return curBBoxes; },
|
||||
getCurrentResizeMode() { return currentResizeMode; },
|
||||
addCommandToHistory,
|
||||
getSelector () { return Selector; }
|
||||
getSelector() { return Selector; }
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -645,7 +677,7 @@ class SvgCanvas {
|
|||
/**
|
||||
* @type {module:path.EditorContext#resetD}
|
||||
*/
|
||||
function resetD (p) {
|
||||
function resetD(p) {
|
||||
if (typeof pathActions.convertPath === 'function') {
|
||||
p.setAttribute('d', pathActions.convertPath(p));
|
||||
} else if (typeof pathActions.convertPaths === 'function') {
|
||||
|
@ -670,16 +702,16 @@ class SvgCanvas {
|
|||
getGridSnapping,
|
||||
getOpacity,
|
||||
getSelectedElements,
|
||||
getContainer () {
|
||||
getContainer() {
|
||||
return container;
|
||||
},
|
||||
setStarted (s) {
|
||||
setStarted(s) {
|
||||
started = s;
|
||||
},
|
||||
getRubberBox () {
|
||||
getRubberBox() {
|
||||
return rubberBox;
|
||||
},
|
||||
setRubberBox (rb) {
|
||||
setRubberBox(rb) {
|
||||
rubberBox = rb;
|
||||
return rubberBox;
|
||||
},
|
||||
|
@ -691,11 +723,11 @@ class SvgCanvas {
|
|||
* @fires module:svgcanvas.SvgCanvas#event:selected
|
||||
* @returns {void}
|
||||
*/
|
||||
addPtsToSelection ({closedSubpath, grips}) {
|
||||
addPtsToSelection({ closedSubpath, grips }) {
|
||||
// TODO: Correct this:
|
||||
pathActions.canDeleteNodes = true;
|
||||
pathActions.closed_subpath = closedSubpath;
|
||||
call('pointsAdded', {closedSubpath, grips});
|
||||
call('pointsAdded', { closedSubpath, grips });
|
||||
call('selected', grips);
|
||||
},
|
||||
/**
|
||||
|
@ -705,7 +737,7 @@ class SvgCanvas {
|
|||
* @fires module:svgcanvas.SvgCanvas#event:changed
|
||||
* @returns {void}
|
||||
*/
|
||||
endChanges ({cmd, elem}) {
|
||||
endChanges({ cmd, elem }) {
|
||||
addCommandToHistory(cmd);
|
||||
call('changed', [elem]);
|
||||
},
|
||||
|
@ -713,17 +745,17 @@ class SvgCanvas {
|
|||
getId,
|
||||
getNextId,
|
||||
getMouseTarget,
|
||||
getCurrentMode () {
|
||||
getCurrentMode() {
|
||||
return currentMode;
|
||||
},
|
||||
setCurrentMode (cm) {
|
||||
setCurrentMode(cm) {
|
||||
currentMode = cm;
|
||||
return currentMode;
|
||||
},
|
||||
getDrawnPath () {
|
||||
getDrawnPath() {
|
||||
return drawnPath;
|
||||
},
|
||||
setDrawnPath (dp) {
|
||||
setDrawnPath(dp) {
|
||||
drawnPath = dp;
|
||||
return drawnPath;
|
||||
},
|
||||
|
@ -765,7 +797,7 @@ class SvgCanvas {
|
|||
/**
|
||||
* @type {module:svgcanvas.SaveOptions}
|
||||
*/
|
||||
saveOptions = {round_digits: 5},
|
||||
saveOptions = { round_digits: 5 },
|
||||
|
||||
// Object with IDs for imported files, to see if one was already added
|
||||
importIds = {},
|
||||
|
@ -839,7 +871,7 @@ class SvgCanvas {
|
|||
* if extension of supplied name already exists
|
||||
* @returns {Promise<void>} Resolves to `undefined`
|
||||
*/
|
||||
this.addExtension = async function (name, extInitFunc, {$: jq, importLocale}) {
|
||||
this.addExtension = async function (name, extInitFunc, { $: jq, importLocale }) {
|
||||
if (typeof extInitFunc !== 'function') {
|
||||
throw new TypeError('Function argument expected for `svgcanvas.addExtension`');
|
||||
}
|
||||
|
@ -1076,7 +1108,7 @@ class SvgCanvas {
|
|||
* @returns {void}
|
||||
*/
|
||||
const logMatrix = function (m) {
|
||||
console.log([m.a, m.b, m.c, m.d, m.e, m.f]);
|
||||
console.log([m.a, m.b, m.c, m.d, m.e, m.f]);
|
||||
};
|
||||
|
||||
// Root Current Transformation Matrix in user units
|
||||
|
@ -1140,7 +1172,7 @@ class SvgCanvas {
|
|||
const currentLayer = getCurrentDrawing().getCurrentLayer();
|
||||
if (currentLayer) {
|
||||
currentMode = 'select';
|
||||
if(currentGroup){
|
||||
if (currentGroup) {
|
||||
selectOnly(currentGroup.children);
|
||||
} else {
|
||||
selectOnly(currentLayer.children);
|
||||
|
@ -1167,12 +1199,12 @@ class SvgCanvas {
|
|||
let rStartY = null;
|
||||
let initBbox = {};
|
||||
let sumDistance = 0;
|
||||
const controllPoint2 = {x: 0, y: 0};
|
||||
const controllPoint1 = {x: 0, y: 0};
|
||||
let start = {x: 0, y: 0};
|
||||
const end = {x: 0, y: 0};
|
||||
let bSpline = {x: 0, y: 0};
|
||||
let nextPos = {x: 0, y: 0};
|
||||
const controllPoint2 = { x: 0, y: 0 };
|
||||
const controllPoint1 = { x: 0, y: 0 };
|
||||
let start = { x: 0, y: 0 };
|
||||
const end = { x: 0, y: 0 };
|
||||
let bSpline = { x: 0, y: 0 };
|
||||
let nextPos = { x: 0, y: 0 };
|
||||
let parameter;
|
||||
let nextParameter;
|
||||
|
||||
|
@ -1181,73 +1213,74 @@ class SvgCanvas {
|
|||
* @returns {void}
|
||||
*/
|
||||
eventInit(
|
||||
/**
|
||||
* @implements {module:event.eventContext_}
|
||||
*/
|
||||
/**
|
||||
* @implements {module:event.eventContext_}
|
||||
*/
|
||||
{
|
||||
getStarted () { return started; },
|
||||
getCanvas () { return canvas; },
|
||||
getCurConfig () { return curConfig; },
|
||||
getCurrentMode () { return currentMode; },
|
||||
getrootSctm () { return rootSctm; },
|
||||
getStartX () { return startX; },
|
||||
setStartX (value) { startX = value; },
|
||||
getStartY () { return startY; },
|
||||
setStartY (value) { startY = value; },
|
||||
getRStartX () { return rStartX; },
|
||||
getRStartY () { return rStartY; },
|
||||
getRubberBox () { return rubberBox; },
|
||||
getInitBbox () { return initBbox; },
|
||||
getCurrentResizeMode () { return currentResizeMode; },
|
||||
getCurrentGroup () { return currentGroup; },
|
||||
getDrawnPath () { return drawnPath; },
|
||||
getJustSelected () { return justSelected; },
|
||||
getOpacAni () { return opacAni; },
|
||||
getParameter () { return parameter; },
|
||||
getNextParameter () { return nextParameter; },
|
||||
getStepCount () { return STEP_COUNT; },
|
||||
getThreSholdDist () { return THRESHOLD_DIST; },
|
||||
getSumDistance () { return sumDistance; },
|
||||
getStart (key) { return start[key]; },
|
||||
getEnd (key) { return end[key]; },
|
||||
getbSpline (key) { return bSpline[key]; },
|
||||
getNextPos (key) { return nextPos[key]; },
|
||||
getControllPoint1 (key) { return controllPoint1[key]; },
|
||||
getControllPoint2 (key) { return controllPoint2[key]; },
|
||||
getFreehand (key) { return freehand[key]; },
|
||||
getDrawing () { return getCurrentDrawing(); },
|
||||
getCurShape () { return curShape; },
|
||||
getDAttr () { return dAttr; },
|
||||
getLastGoodImgUrl () { return lastGoodImgUrl; },
|
||||
getCurText (key) { return curText[key]; },
|
||||
setDAttr (value) { dAttr = value; },
|
||||
setEnd (key, value) { end[key] = value; },
|
||||
setControllPoint1 (key, value) { controllPoint1[key] = value; },
|
||||
setControllPoint2 (key, value) { controllPoint2[key] = value; },
|
||||
setJustSelected (value) { justSelected = value; },
|
||||
setParameter (value) { parameter = value; },
|
||||
setStart (value) { start = value; },
|
||||
setRStartX (value) { rStartX = value; },
|
||||
setRStartY (value) { rStartY = value; },
|
||||
setSumDistance (value) { sumDistance = value; },
|
||||
setbSpline (value) { bSpline = value; },
|
||||
setNextPos (value) { nextPos = value; },
|
||||
setNextParameter (value) { nextParameter = value; },
|
||||
setCurProperties (key, value) { curProperties[key] = value; },
|
||||
setCurText (key, value) { curText[key] = value; },
|
||||
setStarted (s) { started = s; },
|
||||
setStartTransform (transform) { startTransform = transform; },
|
||||
setCurrentMode (cm) {
|
||||
getStarted() { return started; },
|
||||
getCanvas() { return canvas; },
|
||||
getDataStorage,
|
||||
getCurConfig() { return curConfig; },
|
||||
getCurrentMode() { return currentMode; },
|
||||
getrootSctm() { return rootSctm; },
|
||||
getStartX() { return startX; },
|
||||
setStartX(value) { startX = value; },
|
||||
getStartY() { return startY; },
|
||||
setStartY(value) { startY = value; },
|
||||
getRStartX() { return rStartX; },
|
||||
getRStartY() { return rStartY; },
|
||||
getRubberBox() { return rubberBox; },
|
||||
getInitBbox() { return initBbox; },
|
||||
getCurrentResizeMode() { return currentResizeMode; },
|
||||
getCurrentGroup() { return currentGroup; },
|
||||
getDrawnPath() { return drawnPath; },
|
||||
getJustSelected() { return justSelected; },
|
||||
getOpacAni() { return opacAni; },
|
||||
getParameter() { return parameter; },
|
||||
getNextParameter() { return nextParameter; },
|
||||
getStepCount() { return STEP_COUNT; },
|
||||
getThreSholdDist() { return THRESHOLD_DIST; },
|
||||
getSumDistance() { return sumDistance; },
|
||||
getStart(key) { return start[key]; },
|
||||
getEnd(key) { return end[key]; },
|
||||
getbSpline(key) { return bSpline[key]; },
|
||||
getNextPos(key) { return nextPos[key]; },
|
||||
getControllPoint1(key) { return controllPoint1[key]; },
|
||||
getControllPoint2(key) { return controllPoint2[key]; },
|
||||
getFreehand(key) { return freehand[key]; },
|
||||
getDrawing() { return getCurrentDrawing(); },
|
||||
getCurShape() { return curShape; },
|
||||
getDAttr() { return dAttr; },
|
||||
getLastGoodImgUrl() { return lastGoodImgUrl; },
|
||||
getCurText(key) { return curText[key]; },
|
||||
setDAttr(value) { dAttr = value; },
|
||||
setEnd(key, value) { end[key] = value; },
|
||||
setControllPoint1(key, value) { controllPoint1[key] = value; },
|
||||
setControllPoint2(key, value) { controllPoint2[key] = value; },
|
||||
setJustSelected(value) { justSelected = value; },
|
||||
setParameter(value) { parameter = value; },
|
||||
setStart(value) { start = value; },
|
||||
setRStartX(value) { rStartX = value; },
|
||||
setRStartY(value) { rStartY = value; },
|
||||
setSumDistance(value) { sumDistance = value; },
|
||||
setbSpline(value) { bSpline = value; },
|
||||
setNextPos(value) { nextPos = value; },
|
||||
setNextParameter(value) { nextParameter = value; },
|
||||
setCurProperties(key, value) { curProperties[key] = value; },
|
||||
setCurText(key, value) { curText[key] = value; },
|
||||
setStarted(s) { started = s; },
|
||||
setStartTransform(transform) { startTransform = transform; },
|
||||
setCurrentMode(cm) {
|
||||
currentMode = cm;
|
||||
return currentMode;
|
||||
},
|
||||
setFreehand (key, value) { freehand[key] = value; },
|
||||
setCurBBoxes (value) { curBBoxes = value; },
|
||||
setRubberBox (value) { rubberBox = value; },
|
||||
setInitBbox (value) { initBbox = value; },
|
||||
setRootSctm (value) { rootSctm = value; },
|
||||
setCurrentResizeMode (value) { currentResizeMode = value; },
|
||||
setLastClickPoint (value) { lastClickPoint = value; },
|
||||
setFreehand(key, value) { freehand[key] = value; },
|
||||
setCurBBoxes(value) { curBBoxes = value; },
|
||||
setRubberBox(value) { rubberBox = value; },
|
||||
setInitBbox(value) { initBbox = value; },
|
||||
setRootSctm(value) { rootSctm = value; },
|
||||
setCurrentResizeMode(value) { currentResizeMode = value; },
|
||||
setLastClickPoint(value) { lastClickPoint = value; },
|
||||
getSelectedElements,
|
||||
getCurrentZoom,
|
||||
getId,
|
||||
|
@ -1324,14 +1357,14 @@ class SvgCanvas {
|
|||
* @implements {module:text-actions.textActionsContext}
|
||||
*/
|
||||
{
|
||||
getCanvas () { return canvas; },
|
||||
getrootSctm () { return rootSctm; },
|
||||
getCanvas() { return canvas; },
|
||||
getrootSctm() { return rootSctm; },
|
||||
getSelectedElements,
|
||||
getCurrentZoom,
|
||||
getCurrentMode () {
|
||||
getCurrentMode() {
|
||||
return currentMode;
|
||||
},
|
||||
setCurrentMode (cm) {
|
||||
setCurrentMode(cm) {
|
||||
currentMode = cm;
|
||||
return currentMode;
|
||||
},
|
||||
|
@ -1347,34 +1380,35 @@ class SvgCanvas {
|
|||
*/
|
||||
|
||||
svgInit(
|
||||
/**
|
||||
* @implements {module:elem-get-set.elemInit}
|
||||
*/
|
||||
/**
|
||||
* @implements {module:elem-get-set.elemInit}
|
||||
*/
|
||||
{
|
||||
getCanvas () { return canvas; },
|
||||
getCanvas() { return canvas; },
|
||||
getDataStorage,
|
||||
getSVGContent,
|
||||
getSVGRoot,
|
||||
getUIStrings () { return uiStrings; },
|
||||
getCurrentGroup () { return currentGroup; },
|
||||
getCurConfig () { return curConfig; },
|
||||
getNsMap () { return nsMap; },
|
||||
getSvgOption () { return saveOptions; },
|
||||
setSvgOption (key, value) { saveOptions[key] = value; },
|
||||
getSvgOptionApply () { return saveOptions.apply; },
|
||||
getSvgOptionImages () { return saveOptions.images; },
|
||||
getEncodableImages (key) { return encodableImages[key]; },
|
||||
setEncodableImages (key, value) { encodableImages[key] = value; },
|
||||
getUIStrings() { return uiStrings; },
|
||||
getCurrentGroup() { return currentGroup; },
|
||||
getCurConfig() { return curConfig; },
|
||||
getNsMap() { return nsMap; },
|
||||
getSvgOption() { return saveOptions; },
|
||||
setSvgOption(key, value) { saveOptions[key] = value; },
|
||||
getSvgOptionApply() { return saveOptions.apply; },
|
||||
getSvgOptionImages() { return saveOptions.images; },
|
||||
getEncodableImages(key) { return encodableImages[key]; },
|
||||
setEncodableImages(key, value) { encodableImages[key] = value; },
|
||||
call,
|
||||
getDOMDocument () { return svgdoc; },
|
||||
getVisElems () { return visElems; },
|
||||
getIdPrefix () { return idprefix; },
|
||||
setCurrentZoom (value) { currentZoom = value; },
|
||||
getImportIds (key) { return importIds[key]; },
|
||||
setImportIds (key, value) { importIds[key] = value; },
|
||||
setRemovedElements (key, value) { removedElements[key] = value; },
|
||||
setSVGContent (value) { svgcontent = value; },
|
||||
getrefAttrs () { return refAttrs; },
|
||||
getcanvg () { return canvg; },
|
||||
getDOMDocument() { return svgdoc; },
|
||||
getVisElems() { return visElems; },
|
||||
getIdPrefix() { return idprefix; },
|
||||
setCurrentZoom(value) { currentZoom = value; },
|
||||
getImportIds(key) { return importIds[key]; },
|
||||
setImportIds(key, value) { importIds[key] = value; },
|
||||
setRemovedElements(key, value) { removedElements[key] = value; },
|
||||
setSVGContent(value) { svgcontent = value; },
|
||||
getrefAttrs() { return refAttrs; },
|
||||
getcanvg() { return canvg; },
|
||||
addCommandToHistory
|
||||
}
|
||||
);
|
||||
|
@ -1619,10 +1653,11 @@ class SvgCanvas {
|
|||
*/
|
||||
{
|
||||
pathActions,
|
||||
getCurrentGroup () {
|
||||
getDataStorage,
|
||||
getCurrentGroup() {
|
||||
return currentGroup;
|
||||
},
|
||||
setCurrentGroup (cg) {
|
||||
setCurrentGroup(cg) {
|
||||
currentGroup = cg;
|
||||
},
|
||||
getSelectedElements,
|
||||
|
@ -1636,7 +1671,7 @@ class SvgCanvas {
|
|||
* @fires module:svgcanvas.SvgCanvas#event:changed
|
||||
* @returns {void}
|
||||
*/
|
||||
changeSVGContent () {
|
||||
changeSVGContent() {
|
||||
call('changed', [svgcontent]);
|
||||
}
|
||||
}
|
||||
|
@ -1704,15 +1739,16 @@ class SvgCanvas {
|
|||
getSelectedElements,
|
||||
call,
|
||||
changeSelectedAttributeNoUndoMethod,
|
||||
getDOMDocument () { return svgdoc; },
|
||||
getCanvas () { return canvas; },
|
||||
setCanvas (key, value) { canvas[key] = value; },
|
||||
setCurrentZoom (value) { currentZoom = value; },
|
||||
setCurProperties (key, value) { curProperties[key] = value; },
|
||||
getCurProperties (key) { return curProperties[key]; },
|
||||
setCurShape (key, value) { curShape[key] = value; },
|
||||
getCurText (key) { return curText[key]; },
|
||||
setCurText (key, value) { curText[key] = value; }
|
||||
getDOMDocument() { return svgdoc; },
|
||||
getCanvas() { return canvas; },
|
||||
getDataStorage,
|
||||
setCanvas(key, value) { canvas[key] = value; },
|
||||
setCurrentZoom(value) { currentZoom = value; },
|
||||
setCurProperties(key, value) { curProperties[key] = value; },
|
||||
getCurProperties(key) { return curProperties[key]; },
|
||||
setCurShape(key, value) { curShape[key] = value; },
|
||||
getCurText(key) { return curText[key]; },
|
||||
setCurText(key, value) { curText[key] = value; }
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1830,7 +1866,7 @@ class SvgCanvas {
|
|||
* position in the editor's canvas.
|
||||
*/
|
||||
this.getOffset = function () {
|
||||
return {x: svgcontent.getAttribute('x'), y: svgcontent.getAttribute('y')};
|
||||
return { x: svgcontent.getAttribute('x'), y: svgcontent.getAttribute('y') };
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2153,13 +2189,13 @@ class SvgCanvas {
|
|||
* @implements {module:elem-get-set.elemInit}
|
||||
*/
|
||||
{
|
||||
getCanvas () { return canvas; },
|
||||
getCurCommand () { return curCommand; },
|
||||
setCurCommand (value) { curCommand = value; },
|
||||
getFilter () { return filter; },
|
||||
setFilter (value) { filter = value; },
|
||||
getFilterHidden () { return filterHidden; },
|
||||
setFilterHidden (value) { filterHidden = value; },
|
||||
getCanvas() { return canvas; },
|
||||
getCurCommand() { return curCommand; },
|
||||
setCurCommand(value) { curCommand = value; },
|
||||
getFilter() { return filter; },
|
||||
setFilter(value) { filter = value; },
|
||||
getFilterHidden() { return filterHidden; },
|
||||
setFilterHidden(value) { filterHidden = value; },
|
||||
changeSelectedAttributeNoUndoMethod,
|
||||
changeSelectedAttributeMethod,
|
||||
isWebkit,
|
||||
|
@ -2424,17 +2460,17 @@ class SvgCanvas {
|
|||
flashStorage,
|
||||
call,
|
||||
getIntersectionList,
|
||||
setCurBBoxes (value) { curBBoxes = value; },
|
||||
setCurBBoxes(value) { curBBoxes = value; },
|
||||
getSVGRoot,
|
||||
gettingSelectorManager () { return selectorManager; },
|
||||
gettingSelectorManager() { return selectorManager; },
|
||||
getCurrentZoom,
|
||||
getDrawing () { return getCurrentDrawing(); },
|
||||
getCurrentGroup () { return currentGroup; },
|
||||
getDrawing() { return getCurrentDrawing(); },
|
||||
getCurrentGroup() { return currentGroup; },
|
||||
addToSelection,
|
||||
getContentW () { return canvas.contentW; },
|
||||
getContentH () { return canvas.contentH; },
|
||||
getClipboardID () { return CLIPBOARD_ID; },
|
||||
getDOMDocument () { return svgdoc; },
|
||||
getContentW() { return canvas.contentW; },
|
||||
getContentH() { return canvas.contentH; },
|
||||
getClipboardID() { return CLIPBOARD_ID; },
|
||||
getDOMDocument() { return svgdoc; },
|
||||
clearSelection,
|
||||
getNextId,
|
||||
selectOnly,
|
||||
|
@ -2442,8 +2478,9 @@ class SvgCanvas {
|
|||
setUseData,
|
||||
convertGradients,
|
||||
getSVGContent,
|
||||
getCanvas () { return canvas; },
|
||||
getVisElems () { return visElems; }
|
||||
getCanvas() { return canvas; },
|
||||
getDataStorage,
|
||||
getVisElems() { return visElems; }
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -2473,7 +2510,7 @@ class SvgCanvas {
|
|||
* Flash the clipboard data momentarily on localStorage so all tabs can see.
|
||||
* @returns {void}
|
||||
*/
|
||||
function flashStorage () {
|
||||
function flashStorage() {
|
||||
const data = sessionStorage.getItem(CLIPBOARD_ID);
|
||||
localStorage.setItem(CLIPBOARD_ID, data);
|
||||
setTimeout(function () {
|
||||
|
@ -2486,7 +2523,7 @@ class SvgCanvas {
|
|||
* @param {!Event} ev Storage event.
|
||||
* @returns {void}
|
||||
*/
|
||||
function storageChange (ev) {
|
||||
function storageChange(ev) {
|
||||
if (!ev.newValue) return; // This is a call from removeItem.
|
||||
if (ev.key === CLIPBOARD_ID + '_startup') {
|
||||
// Another tab asked for our sessionStorage.
|
||||
|
@ -2515,13 +2552,13 @@ class SvgCanvas {
|
|||
* paste element functionality
|
||||
*/
|
||||
pasteInit(
|
||||
/**
|
||||
* @implements {module:event.eventContext_}
|
||||
*/
|
||||
/**
|
||||
* @implements {module:event.eventContext_}
|
||||
*/
|
||||
{
|
||||
getCanvas () { return canvas; },
|
||||
getClipBoardID () { return CLIPBOARD_ID; },
|
||||
getLastClickPoint (key) { return lastClickPoint[key]; },
|
||||
getCanvas() { return canvas; },
|
||||
getClipBoardID() { return CLIPBOARD_ID; },
|
||||
getLastClickPoint(key) { return lastClickPoint[key]; },
|
||||
addCommandToHistory,
|
||||
restoreRefElems
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
*/
|
||||
|
||||
import jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`
|
||||
import {NS} from '../common/namespaces.js';
|
||||
import {getTransformList} from './svgtransformlist.js';
|
||||
import {setUnitAttr, getTypeMap} from '../common/units.js';
|
||||
import { NS } from '../common/namespaces.js';
|
||||
import { getTransformList } from './svgtransformlist.js';
|
||||
import { setUnitAttr, getTypeMap } from '../common/units.js';
|
||||
import {
|
||||
hasMatrixTransform, transformListToTransform, transformBox
|
||||
} from './math.js';
|
||||
|
@ -18,7 +18,7 @@ import {
|
|||
isWebkit, supportsHVLineContainerBBox, supportsPathBBox, supportsXpath,
|
||||
supportsSelectors
|
||||
} from '../common/browser.js';
|
||||
import {getClosest} from '../editor/components/jgraduate/Util.js';
|
||||
import { getClosest } from '../editor/components/jgraduate/Util.js';
|
||||
|
||||
// Constants
|
||||
const $ = jQueryPluginSVG(jQuery);
|
||||
|
@ -138,7 +138,7 @@ export const toXml = function (str) {
|
|||
* @param {string} str - The string to be converted
|
||||
* @returns {string} The converted string
|
||||
*/
|
||||
export function fromXml (str) {
|
||||
export function fromXml(str) {
|
||||
const p = document.createElement('p');
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
p.innerHTML = str;
|
||||
|
@ -158,7 +158,7 @@ export function fromXml (str) {
|
|||
* @param {string} input
|
||||
* @returns {string} Base64 output
|
||||
*/
|
||||
export function encode64 (input) {
|
||||
export function encode64(input) {
|
||||
// base64 strings are 4/3 larger than the original string
|
||||
input = encodeUTF8(input); // convert non-ASCII characters
|
||||
// input = convertToXMLReferences(input);
|
||||
|
@ -204,7 +204,7 @@ export function encode64 (input) {
|
|||
* @param {string} input Base64-encoded input
|
||||
* @returns {string} Decoded output
|
||||
*/
|
||||
export function decode64 (input) {
|
||||
export function decode64(input) {
|
||||
if (window.atob) {
|
||||
return decodeUTF8(window.atob(input));
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ export function decode64 (input) {
|
|||
* @param {string} argString
|
||||
* @returns {string}
|
||||
*/
|
||||
export function decodeUTF8 (argString) {
|
||||
export function decodeUTF8(argString) {
|
||||
return decodeURIComponent(escape(argString));
|
||||
}
|
||||
|
||||
|
@ -281,7 +281,7 @@ export const dataURLToObjectURL = function (dataurl) {
|
|||
while (n--) {
|
||||
u8arr[n] = bstr.charCodeAt(n);
|
||||
}
|
||||
const blob = new Blob([u8arr], {type: mime});
|
||||
const blob = new Blob([u8arr], { type: mime });
|
||||
return URL.createObjectURL(blob);
|
||||
};
|
||||
|
||||
|
@ -305,7 +305,7 @@ export const blankPageObjectURL = (function () {
|
|||
if (typeof Blob === 'undefined') {
|
||||
return '';
|
||||
}
|
||||
const blob = new Blob(['<html><head><title>SVG-edit</title></head><body> </body></html>'], {type: 'text/html'});
|
||||
const blob = new Blob(['<html><head><title>SVG-edit</title></head><body> </body></html>'], { type: 'text/html' });
|
||||
return createObjectURL(blob);
|
||||
})();
|
||||
|
||||
|
@ -368,8 +368,8 @@ export const text2xml = function (sXML) {
|
|||
* @param {SVGRect} bbox - a SVGRect
|
||||
* @returns {module:utilities.BBoxObject} An object with properties names x, y, width, height.
|
||||
*/
|
||||
export const bboxToObj = function ({x, y, width, height}) {
|
||||
return {x, y, width, height};
|
||||
export const bboxToObj = function ({ x, y, width, height }) {
|
||||
return { x, y, width, height };
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -571,24 +571,24 @@ export const getPathBBox = function (path) {
|
|||
* @param {Element} selected - Container or `<use>` DOM element
|
||||
* @returns {DOMRect} Bounding box object
|
||||
*/
|
||||
function groupBBFix (selected) {
|
||||
function groupBBFix(selected) {
|
||||
if (supportsHVLineContainerBBox()) {
|
||||
try { return selected.getBBox(); } catch (e) {/* empty */}
|
||||
try { return selected.getBBox(); } catch (e) {/* empty */ }
|
||||
}
|
||||
const ref = dataStorage.get(selected, 'ref');
|
||||
const ref = editorContext_.getDataStorage().get(selected, 'ref');
|
||||
let matched = null;
|
||||
let ret, copy;
|
||||
|
||||
if (ref) {
|
||||
let elements = [];
|
||||
Array.prototype.forEach.call(ref.children, function(el, i){
|
||||
const elem = el.cloneNode(true);
|
||||
elem.setAttribute('visibility', 'hidden');
|
||||
svgroot_.appendChild(elem);
|
||||
copy.push(elem);
|
||||
if(['line', 'path'].indexOf(elem.tagName) !== -1){
|
||||
elements.push(elem);
|
||||
}
|
||||
Array.prototype.forEach.call(ref.children, function (el, i) {
|
||||
const elem = el.cloneNode(true);
|
||||
elem.setAttribute('visibility', 'hidden');
|
||||
svgroot_.appendChild(elem);
|
||||
copy.push(elem);
|
||||
if (['line', 'path'].indexOf(elem.tagName) !== -1) {
|
||||
elements.push(elem);
|
||||
}
|
||||
});
|
||||
matched = (elements.length) ? elements : null;
|
||||
} else {
|
||||
|
@ -597,7 +597,7 @@ function groupBBFix (selected) {
|
|||
|
||||
let issue = false;
|
||||
if (matched.length) {
|
||||
Array.prototype.forEach.call(matched, function(match, i){
|
||||
Array.prototype.forEach.call(matched, function (match, i) {
|
||||
const bb = match.getBBox();
|
||||
if (!bb.width || !bb.height) {
|
||||
issue = true;
|
||||
|
@ -632,70 +632,70 @@ export const getBBox = function (elem) {
|
|||
|
||||
let ret = null;
|
||||
switch (elname) {
|
||||
case 'text':
|
||||
if (selected.textContent === '') {
|
||||
selected.textContent = 'a'; // Some character needed for the selector to use.
|
||||
ret = selected.getBBox();
|
||||
selected.textContent = '';
|
||||
} else if (selected.getBBox) {
|
||||
ret = selected.getBBox();
|
||||
}
|
||||
break;
|
||||
case 'path':
|
||||
if (!supportsPathBBox()) {
|
||||
ret = getPathBBox(selected);
|
||||
} else if (selected.getBBox) {
|
||||
ret = selected.getBBox();
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
case 'a':
|
||||
ret = groupBBFix(selected);
|
||||
break;
|
||||
default:
|
||||
case 'text':
|
||||
if (selected.textContent === '') {
|
||||
selected.textContent = 'a'; // Some character needed for the selector to use.
|
||||
ret = selected.getBBox();
|
||||
selected.textContent = '';
|
||||
} else if (selected.getBBox) {
|
||||
ret = selected.getBBox();
|
||||
}
|
||||
break;
|
||||
case 'path':
|
||||
if (!supportsPathBBox()) {
|
||||
ret = getPathBBox(selected);
|
||||
} else if (selected.getBBox) {
|
||||
ret = selected.getBBox();
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
case 'a':
|
||||
ret = groupBBFix(selected);
|
||||
break;
|
||||
default:
|
||||
|
||||
if (elname === 'use') {
|
||||
ret = groupBBFix(selected); // , true);
|
||||
}
|
||||
if (elname === 'use' || (elname === 'foreignObject' && isWebkit())) {
|
||||
if (!ret) { ret = selected.getBBox(); }
|
||||
// This is resolved in later versions of webkit, perhaps we should
|
||||
// have a featured detection for correct 'use' behavior?
|
||||
// ——————————
|
||||
if (!isWebkit()) {
|
||||
const {x, y, width, height} = ret;
|
||||
const bb = {
|
||||
width,
|
||||
height,
|
||||
x: x + Number.parseFloat(selected.getAttribute('x') || 0),
|
||||
y: y + Number.parseFloat(selected.getAttribute('y') || 0)
|
||||
};
|
||||
ret = bb;
|
||||
if (elname === 'use') {
|
||||
ret = groupBBFix(selected); // , true);
|
||||
}
|
||||
} else if (visElemsArr.includes(elname)) {
|
||||
if (selected) {
|
||||
try {
|
||||
ret = selected.getBBox();
|
||||
} catch (err) {
|
||||
// tspan (and textPath apparently) have no `getBBox` in Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=937268
|
||||
// Re: Chrome returning bbox for containing text element, see: https://bugs.chromium.org/p/chromium/issues/detail?id=349835
|
||||
const extent = selected.getExtentOfChar(0); // pos+dimensions of the first glyph
|
||||
const width = selected.getComputedTextLength(); // width of the tspan
|
||||
ret = {
|
||||
x: extent.x,
|
||||
y: extent.y,
|
||||
if (elname === 'use' || (elname === 'foreignObject' && isWebkit())) {
|
||||
if (!ret) { ret = selected.getBBox(); }
|
||||
// This is resolved in later versions of webkit, perhaps we should
|
||||
// have a featured detection for correct 'use' behavior?
|
||||
// ——————————
|
||||
if (!isWebkit()) {
|
||||
const { x, y, width, height } = ret;
|
||||
const bb = {
|
||||
width,
|
||||
height: extent.height
|
||||
height,
|
||||
x: x + Number.parseFloat(selected.getAttribute('x') || 0),
|
||||
y: y + Number.parseFloat(selected.getAttribute('y') || 0)
|
||||
};
|
||||
ret = bb;
|
||||
}
|
||||
} else {
|
||||
// Check if element is child of a foreignObject
|
||||
const fo = getClosest(selected.parentNode, 'foreignObject');
|
||||
if (fo.length && fo[0].getBBox) {
|
||||
ret = fo[0].getBBox();
|
||||
} else if (visElemsArr.includes(elname)) {
|
||||
if (selected) {
|
||||
try {
|
||||
ret = selected.getBBox();
|
||||
} catch (err) {
|
||||
// tspan (and textPath apparently) have no `getBBox` in Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=937268
|
||||
// Re: Chrome returning bbox for containing text element, see: https://bugs.chromium.org/p/chromium/issues/detail?id=349835
|
||||
const extent = selected.getExtentOfChar(0); // pos+dimensions of the first glyph
|
||||
const width = selected.getComputedTextLength(); // width of the tspan
|
||||
ret = {
|
||||
x: extent.x,
|
||||
y: extent.y,
|
||||
width,
|
||||
height: extent.height
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// Check if element is child of a foreignObject
|
||||
const fo = getClosest(selected.parentNode, 'foreignObject');
|
||||
if (fo.length && fo[0].getBBox) {
|
||||
ret = fo[0].getBBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret) {
|
||||
ret = bboxToObj(ret);
|
||||
|
@ -743,76 +743,75 @@ export const getPathDFromElement = function (elem) {
|
|||
let num = 1.81;
|
||||
let d, a, rx, ry;
|
||||
switch (elem.tagName) {
|
||||
case 'ellipse':
|
||||
case 'circle': {
|
||||
const rx = elem.getAttribute('rx');
|
||||
const ry = elem.getAttribute('ry');
|
||||
const cx = elem.getAttribute('cx');
|
||||
const cy = elem.getAttribute('cy');
|
||||
if (elem.tagName === 'circle') {
|
||||
ry = elem.getAttribute('r');
|
||||
rx = ry;
|
||||
}
|
||||
|
||||
d = getPathDFromSegments([
|
||||
['M', [(cx - rx), (cy)]],
|
||||
['C', [(cx - rx), (cy - ry / num), (cx - rx / num), (cy - ry), (cx), (cy - ry)]],
|
||||
['C', [(cx + rx / num), (cy - ry), (cx + rx), (cy - ry / num), (cx + rx), (cy)]],
|
||||
['C', [(cx + rx), (cy + ry / num), (cx + rx / num), (cy + ry), (cx), (cy + ry)]],
|
||||
['C', [(cx - rx / num), (cy + ry), (cx - rx), (cy + ry / num), (cx - rx), (cy)]],
|
||||
['Z', []]
|
||||
]);
|
||||
break;
|
||||
} case 'path':
|
||||
d = elem.getAttribute('d');
|
||||
break;
|
||||
case 'line':
|
||||
const x1 = elem.getAttribute('x1');
|
||||
const y1 = elem.getAttribute('y1');
|
||||
const x2 = elem.getAttribute('x2');
|
||||
const y2 = elem.getAttribute('y2');
|
||||
d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
|
||||
break;
|
||||
case 'polyline':
|
||||
d = 'M' + elem.getAttribute('points');
|
||||
break;
|
||||
case 'polygon':
|
||||
d = 'M' + elem.getAttribute('points') + ' Z';
|
||||
break;
|
||||
case 'rect': {
|
||||
const rx = elem.getAttribute('rx');
|
||||
const ry = elem.getAttribute('ry');
|
||||
const b = elem.getBBox();
|
||||
const {x, y} = b,
|
||||
w = b.width,
|
||||
h = b.height;
|
||||
num = 4 - num; // Why? Because!
|
||||
|
||||
d = (!rx && !ry)
|
||||
// Regular rect
|
||||
? getPathDFromSegments([
|
||||
['M', [x, y]],
|
||||
['L', [x + w, y]],
|
||||
['L', [x + w, y + h]],
|
||||
['L', [x, y + h]],
|
||||
['L', [x, y]],
|
||||
['Z', []]
|
||||
])
|
||||
: getPathDFromSegments([
|
||||
['M', [x, y + ry]],
|
||||
['C', [x, y + ry / num, x + rx / num, y, x + rx, y]],
|
||||
['L', [x + w - rx, y]],
|
||||
['C', [x + w - rx / num, y, x + w, y + ry / num, x + w, y + ry]],
|
||||
['L', [x + w, y + h - ry]],
|
||||
['C', [x + w, y + h - ry / num, x + w - rx / num, y + h, x + w - rx, y + h]],
|
||||
['L', [x + rx, y + h]],
|
||||
['C', [x + rx / num, y + h, x, y + h - ry / num, x, y + h - ry]],
|
||||
['L', [x, y + ry]],
|
||||
case 'ellipse':
|
||||
case 'circle': {
|
||||
rx = elem.getAttribute('rx');
|
||||
ry = elem.getAttribute('ry');
|
||||
const cx = elem.getAttribute('cx');
|
||||
const cy = elem.getAttribute('cy');
|
||||
if (elem.tagName === 'circle' && elem.hasAttribute('r')) {
|
||||
ry = elem.getAttribute('r');
|
||||
rx = ry;
|
||||
}
|
||||
d = getPathDFromSegments([
|
||||
['M', [(cx - rx), (cy)]],
|
||||
['C', [(cx - rx), (cy - ry / num), (cx - rx / num), (cy - ry), (cx), (cy - ry)]],
|
||||
['C', [(cx + rx / num), (cy - ry), (cx + rx), (cy - ry / num), (cx + rx), (cy)]],
|
||||
['C', [(cx + rx), (cy + ry / num), (cx + rx / num), (cy + ry), (cx), (cy + ry)]],
|
||||
['C', [(cx - rx / num), (cy + ry), (cx - rx), (cy + ry / num), (cx - rx), (cy)]],
|
||||
['Z', []]
|
||||
]);
|
||||
break;
|
||||
} default:
|
||||
break;
|
||||
break;
|
||||
} case 'path':
|
||||
d = elem.getAttribute('d');
|
||||
break;
|
||||
case 'line':
|
||||
const x1 = elem.getAttribute('x1');
|
||||
const y1 = elem.getAttribute('y1');
|
||||
const x2 = elem.getAttribute('x2');
|
||||
const y2 = elem.getAttribute('y2');
|
||||
d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
|
||||
break;
|
||||
case 'polyline':
|
||||
d = 'M' + elem.getAttribute('points');
|
||||
break;
|
||||
case 'polygon':
|
||||
d = 'M' + elem.getAttribute('points') + ' Z';
|
||||
break;
|
||||
case 'rect': {
|
||||
rx = elem.getAttribute('rx');
|
||||
ry = elem.getAttribute('ry');
|
||||
const b = elem.getBBox();
|
||||
const { x, y } = b,
|
||||
w = b.width,
|
||||
h = b.height;
|
||||
num = 4 - num; // Why? Because!
|
||||
|
||||
d = (!rx && !ry)
|
||||
// Regular rect
|
||||
? getPathDFromSegments([
|
||||
['M', [x, y]],
|
||||
['L', [x + w, y]],
|
||||
['L', [x + w, y + h]],
|
||||
['L', [x, y + h]],
|
||||
['L', [x, y]],
|
||||
['Z', []]
|
||||
])
|
||||
: getPathDFromSegments([
|
||||
['M', [x, y + ry]],
|
||||
['C', [x, y + ry / num, x + rx / num, y, x + rx, y]],
|
||||
['L', [x + w - rx, y]],
|
||||
['C', [x + w - rx / num, y, x + w, y + ry / num, x + w, y + ry]],
|
||||
['L', [x + w, y + h - ry]],
|
||||
['C', [x + w, y + h - ry / num, x + w - rx / num, y + h, x + w - rx, y + h]],
|
||||
['L', [x + rx, y + h]],
|
||||
['C', [x + rx / num, y + h, x, y + h - ry / num, x, y + h - ry]],
|
||||
['L', [x, y + ry]],
|
||||
['Z', []]
|
||||
]);
|
||||
break;
|
||||
} default:
|
||||
break;
|
||||
}
|
||||
|
||||
return d;
|
||||
|
@ -856,7 +855,7 @@ export const getBBoxOfElementAsPath = function (elem, addSVGElementFromJson, pat
|
|||
path.setAttribute('transform', eltrans);
|
||||
}
|
||||
|
||||
const {parentNode} = elem;
|
||||
const { parentNode } = elem;
|
||||
if (elem.nextSibling) {
|
||||
elem.before(path);
|
||||
} else {
|
||||
|
@ -914,8 +913,8 @@ export const convertToPath = function (
|
|||
path.setAttribute('transform', eltrans);
|
||||
}
|
||||
|
||||
const {id} = elem;
|
||||
const {parentNode} = elem;
|
||||
const { id } = elem;
|
||||
const { parentNode } = elem;
|
||||
if (elem.nextSibling) {
|
||||
elem.before(path);
|
||||
} else {
|
||||
|
@ -936,7 +935,7 @@ export const convertToPath = function (
|
|||
}
|
||||
}
|
||||
|
||||
const {nextSibling} = elem;
|
||||
const { nextSibling } = elem;
|
||||
batchCmd.addSubCommand(new hstry.RemoveElementCommand(elem, nextSibling, parent));
|
||||
batchCmd.addSubCommand(new hstry.InsertElementCommand(path));
|
||||
|
||||
|
@ -975,7 +974,7 @@ export const convertToPath = function (
|
|||
* @param {boolean} hasAMatrixTransform - True if there is a matrix transform
|
||||
* @returns {boolean} True if the bbox can be optimized.
|
||||
*/
|
||||
function bBoxCanBeOptimizedOverNativeGetBBox (angle, hasAMatrixTransform) {
|
||||
function bBoxCanBeOptimizedOverNativeGetBBox(angle, hasAMatrixTransform) {
|
||||
const angleModulo90 = angle % 90;
|
||||
const closeTo90 = angleModulo90 < -89.99 || angleModulo90 > 89.99;
|
||||
const closeTo0 = angleModulo90 > -0.001 && angleModulo90 < 0.001;
|
||||
|
@ -1026,7 +1025,7 @@ export const getBBoxWithTransform = function (elem, addSVGElementFromJson, pathA
|
|||
}
|
||||
|
||||
if (!goodBb) {
|
||||
const {matrix} = transformListToTransform(tlist);
|
||||
const { matrix } = transformListToTransform(tlist);
|
||||
bb = transformBox(bb.x, bb.y, bb.width, bb.height, matrix).aabox;
|
||||
|
||||
// Old technique that was exceedingly slow with large documents.
|
||||
|
@ -1053,7 +1052,7 @@ export const getBBoxWithTransform = function (elem, addSVGElementFromJson, pathA
|
|||
* @todo This is problematic with large stroke-width and, for example, a single
|
||||
* horizontal line. The calculated BBox extends way beyond left and right sides.
|
||||
*/
|
||||
function getStrokeOffsetForBBox (elem) {
|
||||
function getStrokeOffsetForBBox(elem) {
|
||||
const sw = elem.getAttribute('stroke-width');
|
||||
return (!isNaN(sw) && elem.getAttribute('stroke') !== 'none') ? sw / 2 : 0;
|
||||
}
|
||||
|
@ -1141,7 +1140,7 @@ export const getVisibleElements = function (parentElement) {
|
|||
|
||||
const contentElems = [];
|
||||
const childrens = parentElement.children
|
||||
Array.prototype.forEach.call(childrens, function(elem, i){
|
||||
Array.prototype.forEach.call(childrens, function (elem, i) {
|
||||
if (elem.getBBox) {
|
||||
contentElems.push(elem);
|
||||
}
|
||||
|
@ -1324,8 +1323,8 @@ export const snapToGrid = function (value) {
|
|||
*/
|
||||
export const preventClickDefault = function (img) {
|
||||
const elements = document.querySelectorAll("img");
|
||||
Array.from(elements).forEach(function(element) {
|
||||
element.addEventListener('click', function(e) {
|
||||
Array.from(elements).forEach(function (element) {
|
||||
element.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue