mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-02-04 07:13:25 +08:00
Merge pull request #4288 from iwestlin/fix/pie-chart-viewbox
fix: Adjust piechart viewbox for mobile devices with small width
This commit is contained in:
commit
1564358421
@ -44,7 +44,7 @@ describe('pie chart', () => {
|
|||||||
const style = svg.attr('style');
|
const style = svg.attr('style');
|
||||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
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
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ describe('pie chart', () => {
|
|||||||
);
|
);
|
||||||
cy.get('svg').should((svg) => {
|
cy.get('svg').should((svg) => {
|
||||||
const width = parseFloat(svg.attr('width'));
|
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');
|
expect(svg).to.not.have.attr('style');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import type d3 from 'd3';
|
import type d3 from 'd3';
|
||||||
import { scaleOrdinal, pie as d3pie, arc } from 'd3';
|
import { scaleOrdinal, pie as d3pie, arc } from 'd3';
|
||||||
|
|
||||||
import { log } from '../../logger.js';
|
import { log } from '../../logger.js';
|
||||||
import { configureSvgSize } from '../../setupGraphViewbox.js';
|
import { configureSvgSize } from '../../setupGraphViewbox.js';
|
||||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||||
@ -38,33 +37,25 @@ const createPieArcs = (sections: Sections): d3.PieArcDatum<D3Sections>[] => {
|
|||||||
*/
|
*/
|
||||||
export const draw: DrawDefinition = (text, id, _version, diagObj) => {
|
export const draw: DrawDefinition = (text, id, _version, diagObj) => {
|
||||||
log.debug('rendering pie chart\n' + text);
|
log.debug('rendering pie chart\n' + text);
|
||||||
|
|
||||||
const db = diagObj.db as PieDB;
|
const db = diagObj.db as PieDB;
|
||||||
const globalConfig: MermaidConfig = getConfig();
|
const globalConfig: MermaidConfig = getConfig();
|
||||||
const pieConfig: Required<PieDiagramConfig> = cleanAndMerge(db.getConfig(), globalConfig.pie);
|
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 MARGIN = 40;
|
||||||
const LEGEND_RECT_SIZE = 18;
|
const LEGEND_RECT_SIZE = 18;
|
||||||
const LEGEND_SPACING = 4;
|
const LEGEND_SPACING = 4;
|
||||||
|
const height = 450;
|
||||||
|
const pieWidth: number = height;
|
||||||
|
const svg: SVG = selectSvgElement(id);
|
||||||
const group: Group = svg.append('g');
|
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;
|
const { themeVariables } = globalConfig;
|
||||||
let [outerStrokeWidth] = parseFontSize(themeVariables.pieOuterStrokeWidth);
|
let [outerStrokeWidth] = parseFontSize(themeVariables.pieOuterStrokeWidth);
|
||||||
outerStrokeWidth ??= 2;
|
outerStrokeWidth ??= 2;
|
||||||
|
|
||||||
const textPosition: number = pieConfig.textPosition;
|
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:
|
// Shape helper to build arcs:
|
||||||
const arcGenerator: d3.Arc<unknown, d3.PieArcDatum<D3Sections>> = arc<
|
const arcGenerator: d3.Arc<unknown, d3.PieArcDatum<D3Sections>> = arc<
|
||||||
d3.PieArcDatum<D3Sections>
|
d3.PieArcDatum<D3Sections>
|
||||||
@ -84,7 +75,6 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
|
|||||||
.attr('r', radius + outerStrokeWidth / 2)
|
.attr('r', radius + outerStrokeWidth / 2)
|
||||||
.attr('class', 'pieOuterCircle');
|
.attr('class', 'pieOuterCircle');
|
||||||
|
|
||||||
const sections: Sections = db.getSections();
|
|
||||||
const arcs: d3.PieArcDatum<D3Sections>[] = createPieArcs(sections);
|
const arcs: d3.PieArcDatum<D3Sections>[] = createPieArcs(sections);
|
||||||
|
|
||||||
const myGeneratedColors = [
|
const myGeneratedColors = [
|
||||||
@ -177,6 +167,19 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
|
|||||||
}
|
}
|
||||||
return label;
|
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 };
|
export const renderer = { draw };
|
||||||
|
@ -44,6 +44,7 @@ export const configureSvgSize = function (svgElem, height, width, useMaxWidth) {
|
|||||||
const attrs = calculateSvgSizeAttrs(height, width, useMaxWidth);
|
const attrs = calculateSvgSizeAttrs(height, width, useMaxWidth);
|
||||||
d3Attrs(svgElem, attrs);
|
d3Attrs(svgElem, attrs);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setupGraphViewbox = function (graph, svgElem, padding, useMaxWidth) {
|
export const setupGraphViewbox = function (graph, svgElem, padding, useMaxWidth) {
|
||||||
const svgBounds = svgElem.node().getBBox();
|
const svgBounds = svgElem.node().getBBox();
|
||||||
const sWidth = svgBounds.width;
|
const sWidth = svgBounds.width;
|
||||||
@ -55,26 +56,13 @@ export const setupGraphViewbox = function (graph, svgElem, padding, useMaxWidth)
|
|||||||
let height = 0;
|
let height = 0;
|
||||||
log.info(`Graph bounds: ${width}x${height}`, graph);
|
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;
|
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;
|
height = sHeight + padding * 2;
|
||||||
// }
|
|
||||||
|
|
||||||
log.info(`Calculated bounds: ${width}x${height}`);
|
log.info(`Calculated bounds: ${width}x${height}`);
|
||||||
configureSvgSize(svgElem, height, width, useMaxWidth);
|
configureSvgSize(svgElem, height, width, useMaxWidth);
|
||||||
|
|
||||||
// Ensure the viewBox includes the whole svgBounds area with extra space for padding
|
// 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} ${
|
const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${
|
||||||
svgBounds.width + 2 * padding
|
svgBounds.width + 2 * padding
|
||||||
} ${svgBounds.height + 2 * padding}`;
|
} ${svgBounds.height + 2 * padding}`;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user