From: Ulrich-Matthias Schäfer Date: Thu, 27 Jun 2024 09:57:42 +0000 (+0200) Subject: fixing dmove for nested svgs (https://github.com/svgdotjs/svg.draggable.js/issues... X-Git-Tag: 3.2.4~2 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=37750c14d57eabe1d4692b5ec3db431f4cfc9fcb;p=svg.js.git fixing dmove for nested svgs (https://github.com/svgdotjs/svg.draggable.js/issues/127) --- diff --git a/spec/spec/modules/core/containerGeometry.js b/spec/spec/modules/core/containerGeometry.js index 011d9a8..2bb2fca 100644 --- a/spec/spec/modules/core/containerGeometry.js +++ b/spec/spec/modules/core/containerGeometry.js @@ -47,6 +47,60 @@ describe('containerGeometry.js', () => { expect(newBox.h).toBeCloseTo(oldBox.h, 4) }) + it('moves nested svgs in a group correctly when calling dmove', () => { + const canvas = SVG().addTo(container) + const g = canvas.group() + const s1 = g.nested().size(100, 100).move(100, 100) + s1.rect(100, 100).move(50, 50).rotate(10) + + const oldBox = g.bbox() + + g.dmove(10, 10) + + const newBox = g.bbox() + + expect(newBox.x).toBeCloseTo(oldBox.x + 10, 4) + expect(newBox.y).toBeCloseTo(oldBox.y + 10, 4) + expect(newBox.w).toBeCloseTo(oldBox.w, 4) + expect(newBox.h).toBeCloseTo(oldBox.h, 4) + }) + + it('moves nested svgs in a group correctly when calling dmove (2)', () => { + const canvas = SVG().addTo(container) + const g = canvas.group() + const s1 = g.nested().move(100, 100) + s1.rect(100, 100).move(50, 50).rotate(10) + + const oldBox = g.bbox() + + g.dmove(10, 10) + + const newBox = g.bbox() + + expect(newBox.x).toBeCloseTo(oldBox.x + 10, 4) + expect(newBox.y).toBeCloseTo(oldBox.y + 10, 4) + expect(newBox.w).toBeCloseTo(oldBox.w, 4) + expect(newBox.h).toBeCloseTo(oldBox.h, 4) + }) + + it('moves nested svgs in a group correctly when calling dmove (3)', () => { + const canvas = SVG().addTo(container) + const g = canvas.group() + const s1 = g.nested() + s1.rect(100, 100).move(50, 50).rotate(10) + + const oldBox = g.bbox() + + g.dmove(10, 10) + + const newBox = g.bbox() + + expect(newBox.x).toBeCloseTo(oldBox.x + 10, 4) + expect(newBox.y).toBeCloseTo(oldBox.y + 10, 4) + expect(newBox.w).toBeCloseTo(oldBox.w, 4) + expect(newBox.h).toBeCloseTo(oldBox.h, 4) + }) + it('it does not fail when hitting elements without bbox', () => { const canvas = SVG().addTo(container) const g = canvas.group() diff --git a/src/modules/core/containerGeometry.js b/src/modules/core/containerGeometry.js index 21139e8..32a3c8e 100644 --- a/src/modules/core/containerGeometry.js +++ b/src/modules/core/containerGeometry.js @@ -1,6 +1,8 @@ import Matrix from '../../types/Matrix.js' import Point from '../../types/Point.js' +import Box from '../../types/Box.js' import { proportionalSize } from '../../utils/utils.js' +import { getWindow } from '../../utils/window.js' export function dmove(dx, dy) { this.children().forEach((child) => { @@ -10,7 +12,12 @@ export function dmove(dx, dy) { // e.g. title and other descriptive elements try { // Get the childs bbox - bbox = child.bbox() + // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1905039 + // Because bbox for nested svgs returns the contents bbox in the coordinate space of the svg itself (weird!), we cant use bbox for svgs + // Therefore we have to use getBoundingClientRect. But THAT is broken (as explained in the bug). + // Funnily enough the broken behavior would work for us but that breaks it in chrome + // So we have to replicate the broken behavior of FF by just reading the attributes of the svg itself + bbox = child.node instanceof getWindow().SVGSVGElement ? new Box(child.attr(['x', 'y', 'width', 'height'])) : child.bbox() } catch (e) { return }