diff --git a/cypress/integration/rendering/pie.spec.ts b/cypress/integration/rendering/pie.spec.ts index 4a1d774c0a..4166989b81 100644 --- a/cypress/integration/rendering/pie.spec.ts +++ b/cypress/integration/rendering/pie.spec.ts @@ -20,6 +20,60 @@ describe('pie chart', () => { ); }); + it('should render a simple pie diagram with long title', () => { + renderGraph( + `pie title Sports in Sweden that are my favorite to watch + "Bandy": 40 + "Ice-Hockey": 80 + "Football": 90 + ` + ); + cy.get('svg').should((svg) => { + expect(svg).to.have.attr('width', '100%'); + const style = svg.attr('style'); + expect(style).to.match(/^max-width: [\d.]+px;$/); + const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); + expect(maxWidthValue).to.be.within(730, 750); // depends on installed fonts + }); + }); + + it('should render a simple pie diagram with long title and long labels', () => { + renderGraph( + `pie title Time usage on NETFLIX the last few movie nights + "Time spent looking for movie": 90 + "Time spent watching it": 10 + ` + ); + cy.get('svg').should((svg) => { + expect(svg).to.have.attr('width', '100%'); + const style = svg.attr('style'); + expect(style).to.match(/^max-width: [\d.]+px;$/); + const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); + expect(maxWidthValue).to.be.within(900, 920); // depends on installed fonts + }); + }); + + it('should render a simple pie diagram that is centered with long title', () => { + renderGraph( + `pie title Sports in Sweden that are my favorite to watch + "Bandy": 40 + "Ice-Hockey": 80 + "Football": 90 + ` + ); + cy.get('g') + .eq(1) + .should((g) => { + const transform = g.attr('transform'); + expect(transform).to.match(/translate\(\d+(\.\d+)?,\d+(\.\d+)?\)/); + + const translateValues = transform.match(/translate\((\d+(\.\d+)?),(\d+(\.\d+)?)\)/); + const translateX = parseFloat(translateValues[1]); + + expect(translateX).to.be.within(280, 300); + }); + }); + it('should render a simple pie diagram with capital letters for labels', () => { imgSnapshotTest( `pie title What Voldemort doesn't have? @@ -44,7 +98,7 @@ describe('pie chart', () => { const style = svg.attr('style'); expect(style).to.match(/^max-width: [\d.]+px;$/); const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); - expect(maxWidthValue).to.be.within(590, 600); // depends on installed fonts: 596.2 on my PC, 597.5 on CI + expect(maxWidthValue).to.be.within(590, 610); // depends on installed fonts: 596.2 on my PC, 597.5 on CI }); }); @@ -59,7 +113,7 @@ describe('pie chart', () => { ); cy.get('svg').should((svg) => { const width = parseFloat(svg.attr('width')); - expect(width).to.be.within(590, 600); // depends on installed fonts: 596.2 on my PC, 597.5 on CI + expect(width).to.be.within(590, 610); // depends on installed fonts: 596.2 on my PC, 597.5 on CI expect(svg).to.not.have.attr('style'); }); }); diff --git a/packages/mermaid/src/diagrams/pie/pieRenderer.ts b/packages/mermaid/src/diagrams/pie/pieRenderer.ts index 8f3b9cc5b3..8796b17870 100644 --- a/packages/mermaid/src/diagrams/pie/pieRenderer.ts +++ b/packages/mermaid/src/diagrams/pie/pieRenderer.ts @@ -167,14 +167,32 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => { return label; }); - const longestTextWidth = Math.max( + const titleTextElement = group.select('.pieTitleText'); + const titleTextLeft = (titleTextElement.node() as Element).getBoundingClientRect().left; + const titleTextWidth = (titleTextElement.node() as Element).getBoundingClientRect().width; + + // Adjust chart placement. + if (titleTextLeft < MARGIN && titleTextElement.text()) { + group.attr( + 'transform', + 'translate(' + (pieWidth / 2 - (titleTextLeft - MARGIN)) + ',' + height / 2 + ')' + ); + } + + const circleOffset = (group.select('circle').node() as Element).getBoundingClientRect().left; + + const furthestTextPos = Math.max( ...legend .selectAll('text') .nodes() - .map((node) => (node as Element)?.getBoundingClientRect().width ?? 0) + .map((node) => (node as Element)?.getBoundingClientRect().right ?? 0) ); - const totalWidth = pieWidth + MARGIN + LEGEND_RECT_SIZE + LEGEND_SPACING + longestTextWidth; + const totalWidth = Math.max( + pieWidth, + circleOffset + furthestTextPos, + MARGIN * 2 + titleTextWidth + ); // Set viewBox svg.attr('viewBox', `0 0 ${totalWidth} ${height}`);