Skip to content

Commit

Permalink
Merge pull request #4288 from iwestlin/fix/pie-chart-viewbox
Browse files Browse the repository at this point in the history
fix: Adjust piechart viewbox for mobile devices with small width
  • Loading branch information
sidharthv96 authored Nov 28, 2023
2 parents 72d2d04 + 005c998 commit 1564358
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 31 deletions.
4 changes: 2 additions & 2 deletions cypress/integration/rendering/pie.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,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.eq(984);
expect(maxWidthValue).to.be.within(590, 600); // depends on installed fonts: 596.2 on my PC, 597.5 on CI
});
});

Expand All @@ -59,7 +59,7 @@ describe('pie chart', () => {
);
cy.get('svg').should((svg) => {
const width = parseFloat(svg.attr('width'));
expect(width).to.eq(984);
expect(width).to.be.within(590, 600); // depends on installed fonts: 596.2 on my PC, 597.5 on CI
expect(svg).to.not.have.attr('style');
});
});
Expand Down
35 changes: 19 additions & 16 deletions packages/mermaid/src/diagrams/pie/pieRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type d3 from 'd3';
import { scaleOrdinal, pie as d3pie, arc } from 'd3';

import { log } from '../../logger.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
Expand Down Expand Up @@ -38,33 +37,25 @@ const createPieArcs = (sections: Sections): d3.PieArcDatum<D3Sections>[] => {
*/
export const draw: DrawDefinition = (text, id, _version, diagObj) => {
log.debug('rendering pie chart\n' + text);

const db = diagObj.db as PieDB;
const globalConfig: MermaidConfig = getConfig();
const pieConfig: Required<PieDiagramConfig> = cleanAndMerge(db.getConfig(), globalConfig.pie);

const height = 450;
// TODO: remove document width
const width: number =
document.getElementById(id)?.parentElement?.offsetWidth ?? pieConfig.useWidth;
const svg: SVG = selectSvgElement(id);
// Set viewBox
svg.attr('viewBox', `0 0 ${width} ${height}`);
configureSvgSize(svg, height, width, pieConfig.useMaxWidth);

const MARGIN = 40;
const LEGEND_RECT_SIZE = 18;
const LEGEND_SPACING = 4;

const height = 450;
const pieWidth: number = height;
const svg: SVG = selectSvgElement(id);
const group: Group = svg.append('g');
group.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
const sections: Sections = db.getSections();
group.attr('transform', 'translate(' + pieWidth / 2 + ',' + height / 2 + ')');

const { themeVariables } = globalConfig;
let [outerStrokeWidth] = parseFontSize(themeVariables.pieOuterStrokeWidth);
outerStrokeWidth ??= 2;

const textPosition: number = pieConfig.textPosition;
const radius: number = Math.min(width, height) / 2 - MARGIN;
const radius: number = Math.min(pieWidth, height) / 2 - MARGIN;
// Shape helper to build arcs:
const arcGenerator: d3.Arc<unknown, d3.PieArcDatum<D3Sections>> = arc<
d3.PieArcDatum<D3Sections>
Expand All @@ -84,7 +75,6 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
.attr('r', radius + outerStrokeWidth / 2)
.attr('class', 'pieOuterCircle');

const sections: Sections = db.getSections();
const arcs: d3.PieArcDatum<D3Sections>[] = createPieArcs(sections);

const myGeneratedColors = [
Expand Down Expand Up @@ -177,6 +167,19 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
}
return label;
});

const longestTextWidth = Math.max(
...legend
.selectAll('text')
.nodes()
.map((node) => (node as Element)?.getBoundingClientRect().width ?? 0)
);

const totalWidth = pieWidth + MARGIN + LEGEND_RECT_SIZE + LEGEND_SPACING + longestTextWidth;

// Set viewBox
svg.attr('viewBox', `0 0 ${totalWidth} ${height}`);
configureSvgSize(svg, height, totalWidth, pieConfig.useMaxWidth);
};

export const renderer = { draw };
14 changes: 1 addition & 13 deletions packages/mermaid/src/setupGraphViewbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const configureSvgSize = function (svgElem, height, width, useMaxWidth) {
const attrs = calculateSvgSizeAttrs(height, width, useMaxWidth);
d3Attrs(svgElem, attrs);
};

export const setupGraphViewbox = function (graph, svgElem, padding, useMaxWidth) {
const svgBounds = svgElem.node().getBBox();
const sWidth = svgBounds.width;
Expand All @@ -55,26 +56,13 @@ export const setupGraphViewbox = function (graph, svgElem, padding, useMaxWidth)
let height = 0;
log.info(`Graph bounds: ${width}x${height}`, graph);

// let tx = 0;
// let ty = 0;
// if (sWidth > width) {
// tx = (sWidth - width) / 2 + padding;
width = sWidth + padding * 2;
// } else {
// if (Math.abs(sWidth - width) >= 2 * padding + 1) {
// width = width - padding;
// }
// }
// if (sHeight > height) {
// ty = (sHeight - height) / 2 + padding;
height = sHeight + padding * 2;
// }

log.info(`Calculated bounds: ${width}x${height}`);
configureSvgSize(svgElem, height, width, useMaxWidth);

// Ensure the viewBox includes the whole svgBounds area with extra space for padding
// const vBox = `0 0 ${width} ${height}`;
const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${
svgBounds.width + 2 * padding
} ${svgBounds.height + 2 * padding}`;
Expand Down

0 comments on commit 1564358

Please sign in to comment.