#22 Basic Pie Chart

This commit is contained in:
Ashish Jain
2019-09-11 21:20:28 +02:00
parent 78cae3dce7
commit 42fc23cff2
42 changed files with 2571 additions and 3602 deletions

View File

@@ -0,0 +1,57 @@
/** mermaid
* http://knsv.github.io/mermaid/
* (c) 2015 Knut Sveidqvist
* MIT license.
*/
%lex
%x string
%options case-insensitive
%{
// Pre-lexer code can go here
%}
%%
\%\%[^\n]* /* do nothing */
\s+ /* skip whitespace */
"pie" return 'pie' ;
[\s\n\r]+ return 'NL' ;
[\s]+ return 'space';
"title"\s[^#\n;]+ return 'title';
["] {/*console.log('begin str');*/this.begin("string");}
<string>["] {/*console.log('pop-state');*/this.popState();}
<string>[^"]* {/*console.log('ending string')*/return "STR";}
":"[\s]*[\d]+(?:\.[\d]+)? return "VALUE";
<<EOF>> return 'EOF' ;
/lex
%start start
%% /* language grammar */
start
// %{ : info document 'EOF' { return yy; } }
: pie document 'EOF'
;
document
: /* empty */
| document line
;
line
: statement { }
| 'NL'
;
statement
: STR VALUE {
console.log('str:'+$1+' value: '+$2)
yy.addSection($1,yy.cleanupValue($2)); }
| title {yy.setTitle($1.substr(6));$$=$1.substr(6);}
;
%%

View File

@@ -0,0 +1,37 @@
/* eslint-env jasmine */
import pieDb from '../pieDb'
import pie from './pie'
import { setConfig } from '../../../config'
setConfig({
securityLevel: 'strict'
})
describe('when parsing pie', function () {
beforeEach(function () {
pie.parser.yy = pieDb
pie.parser.yy.clear()
})
it('should handle simple pie', function () {
const res = pie.parser.parse('pie \n"ash" : 60\n"bat" : 40\n')
const sections = pieDb.getSections()
console.log('sections: ', sections)
const section1 = sections['ash']
expect(section1).toBe(60)
})
it('should handle simple pie with positive decimal', function () {
const res = pie.parser.parse('pie \n"ash" : 60.67\n"bat" : 40\n')
const sections = pieDb.getSections()
console.log('sections: ', sections)
const section1 = sections['ash']
expect(section1).toBe(60.67)
})
it('should handle simple pie with negative decimal', function () {
expect(()=>{
pie.parser.parse('pie \n"ash" : 60.67\n"bat" : 40..12\n');
}).toThrowError();
})
})

50
src/diagrams/pie/pieDb.js Normal file
View File

@@ -0,0 +1,50 @@
/**
*
*/
import { logger } from '../../logger'
let sections = {}
let title = ''
const addSection = function (id, value) {
if (typeof sections[id] === 'undefined') {
sections[id] = value
logger.debug('Added new section :', id)
// console.log('Added new section:', id, value)
}
}
const getSections = () => sections
const setTitle = function (txt) {
title = txt
}
const getTitle = function () {
return title
}
const cleanupValue = function (value) {
if (value.substring(0, 1) === ':') {
value = value.substring(1).trim()
return Number(value.trim())
} else {
return Number(value.trim())
}
}
const clear = function () {
sections = {}
title = ''
}
// export const parseError = (err, hash) => {
// global.mermaidAPI.parseError(err, hash)
// }
export default {
addSection,
getSections,
cleanupValue,
clear,
setTitle,
getTitle
// parseError
}

View File

@@ -0,0 +1,119 @@
/**
* Created by AshishJ on 11-09-2019.
*/
import * as d3 from 'd3'
import pieData from './pieDb'
import pieParser from './parser/pie'
import { logger } from '../../logger'
const conf = {
}
export const setConf = function (cnf) {
const keys = Object.keys(cnf)
keys.forEach(function (key) {
conf[key] = cnf[key]
})
}
/**
* Draws a Pie Chart with the data given in text.
* @param text
* @param id
*/
let w
export const draw = (txt, id, ver) => {
try {
const parser = pieParser.parser
parser.yy = pieData
logger.debug('Rendering info diagram\n' + txt)
// Parse the Pie Chart definition
parser.yy.clear()
parser.parse(txt)
logger.debug('Parsed info diagram')
const elem = document.getElementById(id)
w = elem.parentElement.offsetWidth
if (typeof w === 'undefined') {
w = 1200
}
if (typeof conf.useWidth !== 'undefined') {
w = conf.useWidth
}
const h = 450
elem.setAttribute('height', '100%')
// Set viewBox
elem.setAttribute('viewBox', '0 0 ' + w + ' ' + h)
// Fetch the default direction, use TD if none was found
var width = w// 450
var height = 450
var margin = 40
var radius = Math.min(width, height) / 2 - margin
var svg = d3.select('#' + id).append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')')
var data = pieData.getSections()
logger.info(data)
// set the color scale
var color = d3.scaleOrdinal()
.domain(data)
.range(d3.schemeSet2)
// Compute the position of each group on the pie:
var pie = d3.pie()
.value(function (d) { return d.value })
var dataReady = pie(d3.entries(data))
// Now I know that group A goes from 0 degrees to x degrees and so on.
// shape helper to build arcs:
var arcGenerator = d3.arc()
.innerRadius(0)
.outerRadius(radius)
// Build the pie chart: Basically, 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.key)) })
.attr('stroke', 'black')
.style('stroke-width', '2px')
.style('opacity', 0.7)
// Now add the annotation. Use the centroid method to get the best coordinates
svg
.selectAll('mySlices')
.data(dataReady)
.enter()
.append('text')
.text(function (d) { return d.data.key })
.attr('transform', function (d) { return 'translate(' + arcGenerator.centroid(d) + ')' })
.style('text-anchor', 'middle')
.style('font-size', 17)
svg.append('text')
.text(parser.yy.getTitle())
.attr('x', 0)
.attr('y', -(h - 50) / 2)
.attr('class', 'titleText')
} catch (e) {
logger.error('Error while rendering info diagram')
logger.error(e.message)
}
}
export default {
setConf,
draw
}