add flip buttons
also update svgedit.css
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
{"total": {"lines":{"total":1903,"covered":1123,"skipped":0,"pct":59.01},"statements":{"total":2952,"covered":1625,"skipped":0,"pct":55.04},"functions":{"total":219,"covered":123,"skipped":0,"pct":56.16},"branches":{"total":853,"covered":417,"skipped":0,"pct":48.88},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/packages/svgcanvas/common/util.js": {"lines":{"total":138,"covered":99,"skipped":0,"pct":71.73},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":194,"covered":136,"skipped":0,"pct":70.1},"branches":{"total":98,"covered":59,"skipped":0,"pct":60.2}}
|
||||
{"total": {"lines":{"total":1903,"covered":1152,"skipped":0,"pct":60.53},"statements":{"total":2952,"covered":1665,"skipped":0,"pct":56.4},"functions":{"total":219,"covered":127,"skipped":0,"pct":57.99},"branches":{"total":853,"covered":434,"skipped":0,"pct":50.87},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/packages/svgcanvas/common/util.js": {"lines":{"total":138,"covered":99,"skipped":0,"pct":71.73},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":194,"covered":138,"skipped":0,"pct":71.13},"branches":{"total":98,"covered":60,"skipped":0,"pct":61.22}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/packages/svgcanvas/core/clear.js": {"lines":{"total":22,"covered":22,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":38,"covered":38,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/packages/svgcanvas/core/coords.js": {"lines":{"total":251,"covered":102,"skipped":0,"pct":40.63},"functions":{"total":12,"covered":8,"skipped":0,"pct":66.66},"statements":{"total":378,"covered":159,"skipped":0,"pct":42.06},"branches":{"total":87,"covered":24,"skipped":0,"pct":27.58}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/packages/svgcanvas/core/dataStorage.js": {"lines":{"total":16,"covered":16,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":20,"covered":20,"skipped":0,"pct":100},"branches":{"total":6,"covered":6,"skipped":0,"pct":100}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/packages/svgcanvas/core/paint.js": {"lines":{"total":51,"covered":44,"skipped":0,"pct":86.27},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":75,"covered":65,"skipped":0,"pct":86.66},"branches":{"total":24,"covered":21,"skipped":0,"pct":87.5}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/packages/svgcanvas/core/path.js": {"lines":{"total":312,"covered":130,"skipped":0,"pct":41.66},"functions":{"total":21,"covered":11,"skipped":0,"pct":52.38},"statements":{"total":511,"covered":193,"skipped":0,"pct":37.76},"branches":{"total":111,"covered":33,"skipped":0,"pct":29.72}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/packages/svgcanvas/core/recalculate.js": {"lines":{"total":241,"covered":86,"skipped":0,"pct":35.68},"functions":{"total":5,"covered":4,"skipped":0,"pct":80},"statements":{"total":338,"covered":114,"skipped":0,"pct":33.72},"branches":{"total":140,"covered":50,"skipped":0,"pct":35.71}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/packages/svgcanvas/core/recalculate.js": {"lines":{"total":241,"covered":102,"skipped":0,"pct":42.32},"functions":{"total":5,"covered":4,"skipped":0,"pct":80},"statements":{"total":338,"covered":133,"skipped":0,"pct":39.34},"branches":{"total":140,"covered":62,"skipped":0,"pct":44.28}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/packages/svgcanvas/core/touch.js": {"lines":{"total":22,"covered":22,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":40,"covered":36,"skipped":0,"pct":90},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/packages/svgcanvas/core/utilities.js": {"lines":{"total":669,"covered":438,"skipped":0,"pct":65.47},"functions":{"total":78,"covered":54,"skipped":0,"pct":69.23},"statements":{"total":991,"covered":630,"skipped":0,"pct":63.57},"branches":{"total":312,"covered":163,"skipped":0,"pct":52.24}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/packages/svgcanvas/core/utilities.js": {"lines":{"total":669,"covered":451,"skipped":0,"pct":67.41},"functions":{"total":78,"covered":58,"skipped":0,"pct":74.35},"statements":{"total":991,"covered":649,"skipped":0,"pct":65.48},"branches":{"total":312,"covered":167,"skipped":0,"pct":53.52}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/src/editor/MainMenu.js": {"lines":{"total":138,"covered":123,"skipped":0,"pct":89.13},"functions":{"total":15,"covered":13,"skipped":0,"pct":86.66},"statements":{"total":186,"covered":166,"skipped":0,"pct":89.24},"branches":{"total":44,"covered":33,"skipped":0,"pct":75}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/src/editor/contextmenu.js": {"lines":{"total":25,"covered":24,"skipped":0,"pct":96},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":38,"covered":36,"skipped":0,"pct":94.73},"branches":{"total":13,"covered":12,"skipped":0,"pct":92.3}}
|
||||
,"/Users/jfh/Documents/GitHub/svgedit/src/editor/locale.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":60,"covered":5,"skipped":0,"pct":8.33},"statements":{"total":143,"covered":32,"skipped":0,"pct":22.37},"branches":{"total":10,"covered":9,"skipped":0,"pct":90}}
|
||||
|
||||
@@ -63,6 +63,7 @@ export const init = canvas => {
|
||||
svgCanvas.updateCanvas = updateCanvas // Updates the editor canvas width/height/position after a zoom has occurred.
|
||||
svgCanvas.cycleElement = cycleElement // Select the next/previous element within the current layer.
|
||||
svgCanvas.deleteSelectedElements = deleteSelectedElements // Removes all selected elements from the DOM and adds the change to the history
|
||||
svgCanvas.flipSelectedElements = flipSelectedElements // Flips selected elements horizontally or vertically
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -621,6 +622,80 @@ const deleteSelectedElements = () => {
|
||||
svgCanvas.clearSelection()
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips selected elements horizontally or vertically by transforming actual coordinates.
|
||||
* @function module:selected-elem.SvgCanvas#flipSelectedElements
|
||||
* @param {number} scaleX - Scale factor for X axis (-1 for horizontal flip, 1 for no flip)
|
||||
* @param {number} scaleY - Scale factor for Y axis (1 for no flip, -1 for vertical flip)
|
||||
* @fires module:selected-elem.SvgCanvas#event:changed
|
||||
* @returns {void}
|
||||
*/
|
||||
const flipSelectedElements = (scaleX, scaleY) => {
|
||||
const selectedElements = svgCanvas.getSelectedElements()
|
||||
const batchCmd = new BatchCommand('Flip Elements')
|
||||
const svgRoot = svgCanvas.getSvgRoot()
|
||||
|
||||
selectedElements.forEach(selected => {
|
||||
if (!selected) return
|
||||
|
||||
const bbox = getStrokedBBoxDefaultVisible([selected])
|
||||
if (!bbox) return
|
||||
|
||||
const cx = bbox.x + bbox.width / 2
|
||||
const cy = bbox.y + bbox.height / 2
|
||||
const existingTransform = selected.getAttribute('transform') || ''
|
||||
|
||||
const flipMatrix = svgRoot
|
||||
.createSVGMatrix()
|
||||
.translate(cx, cy)
|
||||
.scaleNonUniform(scaleX, scaleY)
|
||||
.translate(-cx, -cy)
|
||||
|
||||
const tlist = getTransformList(selected)
|
||||
const combinedMatrix = matrixMultiply(
|
||||
transformListToTransform(tlist).matrix,
|
||||
flipMatrix
|
||||
)
|
||||
|
||||
const flipTransform = svgRoot.createSVGTransform()
|
||||
flipTransform.setMatrix(combinedMatrix)
|
||||
|
||||
tlist.clear()
|
||||
tlist.appendItem(flipTransform)
|
||||
|
||||
const prevStartTransform = svgCanvas.getStartTransform
|
||||
? svgCanvas.getStartTransform()
|
||||
: null
|
||||
if (svgCanvas.setStartTransform) {
|
||||
svgCanvas.setStartTransform(existingTransform)
|
||||
}
|
||||
|
||||
const cmd = recalculateDimensions(selected)
|
||||
|
||||
if (svgCanvas.setStartTransform) {
|
||||
svgCanvas.setStartTransform(prevStartTransform)
|
||||
}
|
||||
|
||||
if (cmd) {
|
||||
batchCmd.addSubCommand(cmd)
|
||||
} else if ((selected.getAttribute('transform') || '') !== existingTransform) {
|
||||
batchCmd.addSubCommand(
|
||||
new ChangeElementCommand(selected, { transform: existingTransform })
|
||||
)
|
||||
}
|
||||
|
||||
svgCanvas
|
||||
.gettingSelectorManager()
|
||||
.requestSelector(selected)
|
||||
.resize()
|
||||
})
|
||||
|
||||
if (!batchCmd.isEmpty()) {
|
||||
svgCanvas.addCommandToHistory(batchCmd)
|
||||
svgCanvas.call('changed', selectedElements.filter(Boolean))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remembers the current selected elements on the clipboard.
|
||||
* @function module:selected-elem.SvgCanvas#copySelectedElements
|
||||
|
||||
48
src/editor/images/flip_horizontal.svg
Normal file
48
src/editor/images/flip_horizontal.svg
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 100 100"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="flip_horizontal.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="8.27"
|
||||
inkscape:cx="43.168077"
|
||||
inkscape:cy="50.120919"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1008"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
stroke-width="4"
|
||||
stroke="#f9bc01"
|
||||
fill="none"
|
||||
d="M 49.940133,0.25937021 V 100.25936 Z m -10,30.00000079 v 40.000006 l -3.27677,-5.76184 -16.723226,-34.238166 z"
|
||||
id="path2"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<path
|
||||
stroke-width="4"
|
||||
stroke="#f9bc01"
|
||||
fill="none"
|
||||
d="M 61.490429,31.147345 V 71.147347 L 67.079935,61.143717 81.49043,31.147345 Z"
|
||||
id="path2-3"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
style="stroke:#f9dab8;stroke-opacity:1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
48
src/editor/images/flip_vertical.svg
Normal file
48
src/editor/images/flip_vertical.svg
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 100 100"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="flip_vertical.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="8.27"
|
||||
inkscape:cx="43.168077"
|
||||
inkscape:cy="50.120919"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1008"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
stroke-width="4"
|
||||
stroke="#f9bc01"
|
||||
fill="none"
|
||||
d="M 0.10978222,43.451827 H 100.10978 Z m 29.99999978,10 H 70.10978 L 64.347943,56.7286 30.109782,73.451827 Z"
|
||||
id="path2"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<path
|
||||
stroke-width="4"
|
||||
stroke="#f9bc01"
|
||||
fill="none"
|
||||
d="m 30.216722,33.403103 h 40 L 60.213097,27.813597 30.216722,13.403103 Z"
|
||||
id="path2-3"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
style="stroke:#f9dab8;stroke-opacity:1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -168,6 +168,8 @@ export default {
|
||||
set_link_url: 'Set link URL (leave empty to remove)',
|
||||
to_path: 'Convert to Path',
|
||||
reorient_path: 'Reorient path',
|
||||
flip_horizontal: 'Flip Horizontally',
|
||||
flip_vertical: 'Flip Vertically',
|
||||
ungroup: 'Ungroup Elements',
|
||||
docprops: 'Document Properties',
|
||||
editor_homepage: 'SVG-Edit Home Page',
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
<se-button id="tool_topath" title="tools.to_path" src="to_path.svg"></se-button>
|
||||
<se-button id="tool_reorient" title="tools.reorient_path" src="reorient.svg"></se-button>
|
||||
<se-button id="tool_make_link" title="tools.make_link" src="globe_link.svg"></se-button>
|
||||
<div class="tool_sep"></div>
|
||||
<se-button id="tool_flip_h" title="tools.flip_horizontal" src="flip_horizontal.svg"></se-button>
|
||||
<se-button id="tool_flip_v" title="tools.flip_vertical" src="flip_vertical.svg"></se-button>
|
||||
</div>
|
||||
<div class="selected_panel">
|
||||
<div class="tool_sep"></div>
|
||||
@@ -219,4 +222,4 @@
|
||||
<se-button id="tool_add_subpath" title="tools.add_subpath" src="tool_add_subpath.svg"></se-button>
|
||||
</div> <!-- path_node_panel -->
|
||||
<div id="cur_context_panel"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -667,6 +667,26 @@ class TopPanel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip selected element(s) horizontally.
|
||||
* @returns {void}
|
||||
*/
|
||||
clickFlipHorizontal () {
|
||||
if (this.editor.selectedElement || this.multiselected) {
|
||||
this.editor.svgCanvas.flipSelectedElements(-1, 1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip selected element(s) vertically.
|
||||
* @returns {void}
|
||||
*/
|
||||
clickFlipVertical () {
|
||||
if (this.editor.selectedElement || this.multiselected) {
|
||||
this.editor.svgCanvas.flipSelectedElements(1, -1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void} Resolves to `undefined`
|
||||
@@ -962,6 +982,8 @@ class TopPanel {
|
||||
$click($id('tool_make_link'), this.makeHyperlink.bind(this))
|
||||
$click($id('tool_make_link_multi'), this.makeHyperlink.bind(this))
|
||||
$click($id('tool_reorient'), this.reorientPath.bind(this))
|
||||
$click($id('tool_flip_h'), this.clickFlipHorizontal.bind(this))
|
||||
$click($id('tool_flip_v'), this.clickFlipVertical.bind(this))
|
||||
$click($id('tool_group_elements'), this.clickGroup.bind(this))
|
||||
$id('tool_position').addEventListener('change', evt =>
|
||||
this.clickAlignEle.bind(this)(evt)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
--input-color: #B2B2B2;
|
||||
--orange-color: #f9bc01;
|
||||
--global-se-spin-input-width: 82px;
|
||||
--top-toolbar-min-height: 80px;
|
||||
}
|
||||
|
||||
.svg_editor * {
|
||||
@@ -18,7 +19,7 @@
|
||||
|
||||
.svg_editor {
|
||||
display: grid;
|
||||
grid-template-rows: auto 15px 1fr 40px;
|
||||
grid-template-rows: minmax(var(--top-toolbar-min-height), auto) 15px 1fr 40px;
|
||||
grid-template-columns: 40px 15px 50px 1fr 15px;
|
||||
grid-template-areas:
|
||||
"main main main top top"
|
||||
@@ -41,13 +42,6 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* on smaller screen, allow 2 lines for the toolbar */
|
||||
@media screen and (max-width:1250px) {
|
||||
.svg_editor {
|
||||
grid-template-rows: minmax(80px, auto) 15px 1fr 40px;
|
||||
}
|
||||
}
|
||||
|
||||
/* class to open the right panel */
|
||||
.svg_editor.open {
|
||||
grid-template-columns: 34px 15px 50px 1fr 220px;
|
||||
@@ -311,7 +305,9 @@ hr {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
align-content: flex-start;
|
||||
background-color: var(--main-bg-color);
|
||||
min-height: var(--top-toolbar-min-height);
|
||||
}
|
||||
|
||||
#tools_top>* {
|
||||
@@ -628,4 +624,4 @@ ul li.current {
|
||||
|
||||
.dropdown li.tool_button {
|
||||
width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
102
tests/unit/flip-selected.test.js
Normal file
102
tests/unit/flip-selected.test.js
Normal file
@@ -0,0 +1,102 @@
|
||||
import SvgCanvas from '../../packages/svgcanvas/svgcanvas.js'
|
||||
|
||||
describe('flipSelectedElements', () => {
|
||||
let svgCanvas
|
||||
|
||||
const createSvgCanvas = () => {
|
||||
document.body.textContent = ''
|
||||
const svgEditor = document.createElement('div')
|
||||
svgEditor.id = 'svg_editor'
|
||||
const svgcanvas = document.createElement('div')
|
||||
svgcanvas.style.visibility = 'hidden'
|
||||
svgcanvas.id = 'svgcanvas'
|
||||
const workarea = document.createElement('div')
|
||||
workarea.id = 'workarea'
|
||||
workarea.append(svgcanvas)
|
||||
const toolsLeft = document.createElement('div')
|
||||
toolsLeft.id = 'tools_left'
|
||||
svgEditor.append(workarea, toolsLeft)
|
||||
document.body.append(svgEditor)
|
||||
|
||||
svgCanvas = new SvgCanvas(document.getElementById('svgcanvas'), {
|
||||
canvas_expansion: 3,
|
||||
dimensions: [640, 480],
|
||||
initFill: {
|
||||
color: 'FF0000',
|
||||
opacity: 1
|
||||
},
|
||||
initStroke: {
|
||||
width: 5,
|
||||
color: '000000',
|
||||
opacity: 1
|
||||
},
|
||||
initOpacity: 1,
|
||||
imgPath: '../editor/images',
|
||||
langPath: 'locale/',
|
||||
extPath: 'extensions/',
|
||||
extensions: [],
|
||||
initTool: 'select',
|
||||
wireframe: false
|
||||
})
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
createSvgCanvas()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
document.body.textContent = ''
|
||||
})
|
||||
|
||||
it('flips a simple line horizontally and records history', () => {
|
||||
const line = svgCanvas.addSVGElementsFromJson({
|
||||
element: 'line',
|
||||
attr: {
|
||||
id: 'line-basic',
|
||||
x1: 10,
|
||||
y1: 20,
|
||||
x2: 30,
|
||||
y2: 20,
|
||||
stroke: '#000'
|
||||
}
|
||||
})
|
||||
|
||||
svgCanvas.selectOnly([line], true)
|
||||
const undoSize = svgCanvas.undoMgr.getUndoStackSize()
|
||||
|
||||
svgCanvas.flipSelectedElements(-1, 1)
|
||||
|
||||
expect(Number(line.getAttribute('x1'))).toBe(30)
|
||||
expect(Number(line.getAttribute('x2'))).toBe(10)
|
||||
expect(line.hasAttribute('transform')).toBe(false)
|
||||
expect(svgCanvas.undoMgr.getUndoStackSize()).toBe(undoSize + 1)
|
||||
})
|
||||
|
||||
it('flips around the visual center when a transform exists and can be undone', () => {
|
||||
const line = svgCanvas.addSVGElementsFromJson({
|
||||
element: 'line',
|
||||
attr: {
|
||||
id: 'line-transformed',
|
||||
x1: 10,
|
||||
y1: 0,
|
||||
x2: 30,
|
||||
y2: 0,
|
||||
stroke: '#000',
|
||||
transform: 'translate(100,0)'
|
||||
}
|
||||
})
|
||||
|
||||
svgCanvas.selectOnly([line], true)
|
||||
svgCanvas.flipSelectedElements(-1, 1)
|
||||
|
||||
expect(Number(line.getAttribute('x1'))).toBe(130)
|
||||
expect(Number(line.getAttribute('x2'))).toBe(110)
|
||||
expect(line.hasAttribute('transform')).toBe(false)
|
||||
|
||||
svgCanvas.undoMgr.undo()
|
||||
|
||||
expect(Number(line.getAttribute('x1'))).toBe(10)
|
||||
expect(Number(line.getAttribute('x2'))).toBe(30)
|
||||
expect(line.getAttribute('transform')).toMatch(/translate\(100[ ,]0\)/)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user