Fix copy group shapes as svg (#112)

* fixes copy group shapes as svg

* Update tlstate.ts

* Fix failing tests
pull/114/head
Steve Ruiz 2021-09-23 10:48:08 +01:00 zatwierdzone przez GitHub
rodzic 6ba76c0e78
commit 48f784c322
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
3 zmienionych plików z 87 dodań i 17 usunięć

Wyświetl plik

@ -125,4 +125,14 @@ Array [
]
`;
exports[`TLDrawState Selection When selecting all selects all: selected all 1`] = `
Array [
"rect1",
"rect2",
"rect3",
]
`;
exports[`TLDrawState When copying to SVG Copies grouped shapes.: copied svg with group 1`] = `"<svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"-16 -16 232 232\\" width=\\"200\\" height=\\"200\\"><g/></svg>"`;
exports[`TLDrawState When copying to SVG Copies shapes.: copied svg 1`] = `"<svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"-20.741879096242684 -20.741879096242684 236.74 236.74\\" width=\\"204.74\\" height=\\"204.74\\"/>"`;

Wyświetl plik

@ -113,7 +113,17 @@ describe('TLDrawState', () => {
it.todo('re-creates shapes on redo after creating')
it.todo('selects all')
describe('When selecting all', () => {
it('selects all', () => {
const tlstate = new TLDrawState().loadDocument(mockDocument).selectAll()
expect(tlstate.selectedIds).toMatchSnapshot('selected all')
})
it('does not select children of a group', () => {
const tlstate = new TLDrawState().loadDocument(mockDocument).selectAll().group()
expect(tlstate.selectedIds.length).toBe(1)
})
})
// Single click on a selected shape to select just that shape
@ -453,6 +463,17 @@ describe('TLDrawState', () => {
expect(result).toMatchSnapshot('copied svg')
})
it('Copies grouped shapes.', () => {
const tlstate = new TLDrawState()
const result = tlstate
.loadDocument(mockDocument)
.select('rect1', 'rect2')
.group()
.selectAll()
.copySvg()
expect(result).toMatchSnapshot('copied svg with group')
})
it.todo('Copies Text shapes as <text> elements.')
// it('Copies Text shapes as <text> elements.', () => {
// const tlstate2 = new TLDrawState()

Wyświetl plik

@ -979,26 +979,56 @@ export class TLDrawState extends StateManager<Data> {
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
ids.forEach((id) => {
const elm = document.getElementById(id + '_svg')
// const idsToCopy = ids.flatMap((id) => TLDR.getDocumentBranch(this.state, id, pageId))
const shapes = ids.map((id) => this.getShape(id, pageId))
function getSvgElementForShape(shape: TLDrawShape) {
const elm = document.getElementById(shape.id + '_svg')
if (!elm) return
// TODO: Create SVG elements for text
if (elm) {
const clone = elm?.cloneNode(true) as SVGElement
const shape = this.getShape(id, pageId)
const bounds = TLDR.getShapeUtils(shape).getBounds(shape)
clone.setAttribute(
'transform',
`translate(${shape.point[0]}px ${shape.point[1]}px) rotate(${
((shape.rotation || 0) * 180) / Math.PI
}, ${bounds.width / 2}, ${bounds.height / 2})`
)
svg.appendChild(clone)
const element = elm?.cloneNode(true) as SVGElement
const bounds = TLDR.getShapeUtils(shape).getBounds(shape)
element.setAttribute(
'transform',
`translate(${shape.point[0]}, ${shape.point[1]}) rotate(${
((shape.rotation || 0) * 180) / Math.PI
}, ${bounds.width / 2}, ${bounds.height / 2})`
)
return element
}
shapes.forEach((shape) => {
if (shape.children?.length) {
// Create a group <g> element for shape
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g')
// Get the shape's children as elements
shape.children
.map((childId) => this.getShape(childId, pageId))
.map(getSvgElementForShape)
.filter(Boolean)
.forEach((element) => g.appendChild(element!))
// Add the group element to the SVG
svg.appendChild(g)
return
}
const element = getSvgElementForShape(shape)
if (element) {
svg.appendChild(element)
}
})
const shapes = ids.map((id) => this.getShape(id, pageId))
const bounds = Utils.getCommonBounds(shapes.map(TLDR.getRotatedBounds))
const padding = 16
@ -1307,13 +1337,22 @@ export class TLDrawState extends StateManager<Data> {
/**
* Select all shapes on the page.
*/
selectAll = (): this => {
selectAll = (pageId = this.currentPageId): this => {
if (this.session) return this
this.setSelectedIds(Object.keys(this.page.shapes))
// Select only shapes that are the direct child of the page
this.setSelectedIds(
Object.values(this.document.pages[pageId].shapes)
.filter((shape) => shape.parentId === pageId)
.map((shape) => shape.id)
)
this.addToSelectHistory(this.selectedIds)
if (this.appState.activeTool !== 'select') {
this.selectTool('select')
}
return this
}