mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-10-10 09:39:38 +02:00
187 lines
5.1 KiB
JavaScript
187 lines
5.1 KiB
JavaScript
/** Created by AshishJ on 11-09-2019. */
|
|
import { select, scaleOrdinal, pie as d3pie, arc } from 'd3';
|
|
import pieData from './pieDb';
|
|
import pieParser from './parser/pie';
|
|
import { log } from '../../logger';
|
|
import { configureSvgSize } from '../../utils';
|
|
import * as configApi from '../../config';
|
|
import addSVGAccessibilityFields from '../../accessibility';
|
|
|
|
let conf = configApi.getConfig();
|
|
|
|
/**
|
|
* Draws a Pie Chart with the data given in text.
|
|
*
|
|
* @param text
|
|
* @param id
|
|
*/
|
|
let width;
|
|
const height = 450;
|
|
export const draw = (txt, id) => {
|
|
try {
|
|
conf = configApi.getConfig();
|
|
const parser = pieParser.parser;
|
|
parser.yy = pieData;
|
|
log.debug('Rendering info diagram\n' + txt);
|
|
|
|
const securityLevel = configApi.getConfig().securityLevel;
|
|
// Handle root and ocument for when rendering in sanbox mode
|
|
let sandboxElement;
|
|
if (securityLevel === 'sandbox') {
|
|
sandboxElement = select('#i' + id);
|
|
}
|
|
const root =
|
|
securityLevel === 'sandbox'
|
|
? select(sandboxElement.nodes()[0].contentDocument.body)
|
|
: select('body');
|
|
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
|
|
|
// Parse the Pie Chart definition
|
|
parser.yy.clear();
|
|
parser.parse(txt);
|
|
log.debug('Parsed info diagram');
|
|
const elem = doc.getElementById(id);
|
|
width = elem.parentElement.offsetWidth;
|
|
|
|
if (typeof width === 'undefined') {
|
|
width = 1200;
|
|
}
|
|
|
|
if (typeof conf.useWidth !== 'undefined') {
|
|
width = conf.useWidth;
|
|
}
|
|
if (typeof conf.pie.useWidth !== 'undefined') {
|
|
width = conf.pie.useWidth;
|
|
}
|
|
|
|
const diagram = root.select('#' + id);
|
|
configureSvgSize(diagram, height, width, conf.pie.useMaxWidth);
|
|
|
|
addSVGAccessibilityFields(parser.yy, diagram, id);
|
|
// Set viewBox
|
|
elem.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
|
|
|
|
// Fetch the default direction, use TD if none was found
|
|
var margin = 40;
|
|
var legendRectSize = 18;
|
|
var legendSpacing = 4;
|
|
|
|
var radius = Math.min(width, height) / 2 - margin;
|
|
|
|
var svg = diagram
|
|
.append('g')
|
|
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
|
|
|
|
var data = pieData.getSections();
|
|
var sum = 0;
|
|
Object.keys(data).forEach(function (key) {
|
|
sum += data[key];
|
|
});
|
|
|
|
const themeVariables = conf.themeVariables;
|
|
var myGeneratedColors = [
|
|
themeVariables.pie1,
|
|
themeVariables.pie2,
|
|
themeVariables.pie3,
|
|
themeVariables.pie4,
|
|
themeVariables.pie5,
|
|
themeVariables.pie6,
|
|
themeVariables.pie7,
|
|
themeVariables.pie8,
|
|
themeVariables.pie9,
|
|
themeVariables.pie10,
|
|
themeVariables.pie11,
|
|
themeVariables.pie12,
|
|
];
|
|
|
|
// Set the color scale
|
|
var color = scaleOrdinal().range(myGeneratedColors);
|
|
|
|
// Compute the position of each group on the pie:
|
|
var pie = d3pie().value(function (d) {
|
|
return d[1];
|
|
});
|
|
var dataReady = pie(Object.entries(data));
|
|
|
|
// Shape helper to build arcs:
|
|
var arcGenerator = arc().innerRadius(0).outerRadius(radius);
|
|
|
|
// Build the pie chart: each part of the pie is a path that we build using the arc function.
|
|
svg
|
|
.selectAll('mySlices')
|
|
.data(dataReady)
|
|
.enter()
|
|
.append('path')
|
|
.attr('d', arcGenerator)
|
|
.attr('fill', function (d) {
|
|
return color(d.data[0]);
|
|
})
|
|
.attr('class', 'pieCircle');
|
|
|
|
// Now add the percentage.
|
|
// Use the centroid method to get the best coordinates.
|
|
svg
|
|
.selectAll('mySlices')
|
|
.data(dataReady)
|
|
.enter()
|
|
.append('text')
|
|
.text(function (d) {
|
|
return ((d.data[1] / sum) * 100).toFixed(0) + '%';
|
|
})
|
|
.attr('transform', function (d) {
|
|
return 'translate(' + arcGenerator.centroid(d) + ')';
|
|
})
|
|
.style('text-anchor', 'middle')
|
|
.attr('class', 'slice');
|
|
|
|
svg
|
|
.append('text')
|
|
.text(parser.yy.getTitle())
|
|
.attr('x', 0)
|
|
.attr('y', -(height - 50) / 2)
|
|
.attr('class', 'pieTitleText');
|
|
|
|
// Add the legends/annotations for each section
|
|
var legend = svg
|
|
.selectAll('.legend')
|
|
.data(color.domain())
|
|
.enter()
|
|
.append('g')
|
|
.attr('class', 'legend')
|
|
.attr('transform', function (d, i) {
|
|
var height = legendRectSize + legendSpacing;
|
|
var offset = (height * color.domain().length) / 2;
|
|
var horz = 12 * legendRectSize;
|
|
var vert = i * height - offset;
|
|
return 'translate(' + horz + ',' + vert + ')';
|
|
});
|
|
|
|
legend
|
|
.append('rect')
|
|
.attr('width', legendRectSize)
|
|
.attr('height', legendRectSize)
|
|
.style('fill', color)
|
|
.style('stroke', color);
|
|
|
|
legend
|
|
.data(dataReady)
|
|
.append('text')
|
|
.attr('x', legendRectSize + legendSpacing)
|
|
.attr('y', legendRectSize - legendSpacing)
|
|
.text(function (d) {
|
|
if (parser.yy.getShowData() || conf.showData || conf.pie.showData) {
|
|
return d.data[0] + ' [' + d.data[1] + ']';
|
|
} else {
|
|
return d.data[0];
|
|
}
|
|
});
|
|
} catch (e) {
|
|
log.error('Error while rendering info diagram');
|
|
log.error(e);
|
|
}
|
|
};
|
|
|
|
export default {
|
|
draw,
|
|
};
|