[svg] remove last remaining shred of HTML: Percentage bars

This commit is contained in:
Prateeksha Singh 2018-04-12 18:51:12 +05:30
parent 6e14dd45ee
commit a22c3eba33
17 changed files with 202 additions and 192 deletions

View File

@ -247,11 +247,7 @@ const MIN_BAR_PERCENT_HEIGHT = 0.01;
const LINE_CHART_DOT_SIZE = 4;
const DOT_OVERLAY_SIZE_INCR = 4;
const DEFAULT_CHAR_WIDTH = 7;
// Universal constants
const ANGLE_RATIO = Math.PI / 180;
const FULL_ANGLE = 360;
const PERCENTAGE_BAR_DEFAULT_HEIGHT = 20;
// Fixed 5-color theme,
// More colors are difficult to parse visually
@ -260,6 +256,8 @@ const HEATMAP_DISTRIBUTION_SIZE = 5;
const HEATMAP_SQUARE_SIZE = 10;
const HEATMAP_GUTTER_SIZE = 2;
const DEFAULT_CHAR_WIDTH = 7;
const HEATMAP_COLORS = ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'];
const DEFAULT_CHART_COLORS = ['light-blue', 'blue', 'violet', 'red', 'orange',
'yellow', 'green', 'light-green', 'purple', 'magenta', 'light-grey', 'dark-grey'];
@ -272,6 +270,10 @@ const DEFAULT_COLORS = {
heatmap: HEATMAP_COLORS
};
// Universal constants
const ANGLE_RATIO = Math.PI / 180;
const FULL_ANGLE = 360;
function floatTwo(d) {
return parseFloat(d.toFixed(2));
}
@ -472,6 +474,19 @@ function makeGradient(svgDefElem, color, lighter = false) {
return gradientId;
}
function percentageBar(x, y, width, height, fill='none') {
let args = {
className: 'percentage-bar',
x: x,
y: y,
width: width,
height: height,
fill: fill
};
return createSVG("rect", args);
}
function heatSquare(className, x, y, size, fill='none', data={}) {
let args = {
className: className,
@ -1555,6 +1570,8 @@ class AggregationChart extends BaseChart {
s.sliceTotals.push(d[0]);
s.labels.push(d[1]);
});
s.grandTotal = s.sliceTotals.reduce((a, b) => a + b, 0);
}
renderLegend() {
@ -1578,79 +1595,8 @@ class AggregationChart extends BaseChart {
// </span>`;
// }
// });
}
}
class PercentageChart extends AggregationChart {
constructor(parent, args) {
super(parent, args);
this.type = 'percentage';
this.setup();
}
makeChartArea() {
this.container.className += ' ' + 'graph-focus-margin';
this.container.style.marginTop = '45px';
// this.statsWrapper.className += ' ' + 'graph-focus-margin';
// this.statsWrapper.style.marginBottom = '30px';
// this.statsWrapper.style.paddingTop = '0px';
this.svg = $.create('div', {
className: 'div',
inside: this.container
});
this.chart = $.create('div', {
className: 'progress-chart',
inside: this.svg
});
this.percentageBar = $.create('div', {
className: 'progress',
inside: this.chart
});
}
render() {
let s = this.state;
this.grandTotal = s.sliceTotals.reduce((a, b) => a + b, 0);
s.slices = [];
s.sliceTotals.map((total, i) => {
let slice = $.create('div', {
className: `progress-bar`,
'data-index': i,
inside: this.percentageBar,
styles: {
background: this.colors[i],
width: total*100/this.grandTotal + "%"
}
});
s.slices.push(slice);
});
}
bindTooltip() {
let s = this.state;
this.container.addEventListener('mousemove', (e) => {
let slice = e.target;
if(slice.classList.contains('progress-bar')) {
let i = slice.getAttribute('data-index');
let gOff = getOffset(this.container), pOff = getOffset(slice);
let x = pOff.left - gOff.left + slice.offsetWidth/2;
let y = pOff.top - gOff.top - 6;
let title = (this.formattedLabels && this.formattedLabels.length>0
? this.formattedLabels[i] : this.state.labels[i]) + ': ';
let percent = (s.sliceTotals[i]*100/this.grandTotal).toFixed(1);
this.tip.setValues(x, y, {name: title, value: percent + "%"});
this.tip.showTip();
}
});
//
}
}
@ -1707,7 +1653,7 @@ class ChartComponent {
this.refresh();
let animateElements = [];
if(animate) {
animateElements = this.animateElements(this.data);
animateElements = this.animateElements(this.data) || [];
}
return animateElements;
}
@ -1733,18 +1679,15 @@ let componentConfigs = {
percentageBars: {
layerClass: 'percentage-bars',
makeElements(data) {
// return data.sliceStrings.map((s, i) =>{
// let slice = makePath(s, 'pie-path', 'none', data.colors[i]);
// slice.style.transition = 'transform .3s;';
// return slice;
// });
return data.xPositions.map((x, i) =>{
let y = 0;
let bar = percentageBar(x, y, data.widths[i],
this.constants.barHeight, data.colors[i]);
return bar;
});
},
animateElements(newData) {
// return this.store.map((slice, i) =>
// animatePathStr(slice, newData.sliceStrings[i])
// );
}
animateElements(newData) { }
},
yAxis: {
layerClass: 'y axis',
@ -1905,11 +1848,7 @@ let componentConfigs = {
return this.serializedSubDomains;
},
animateElements(newData) {
// return this.store.map((slice, i) =>
// animatePathStr(slice, newData.sliceStrings[i])
// );
}
animateElements(newData) { }
},
barGraph: {
@ -2064,6 +2003,83 @@ function getComponent(name, constants, getData) {
return new ChartComponent(config);
}
class PercentageChart extends AggregationChart {
constructor(parent, args) {
super(parent, args);
this.type = 'percentage';
this.barOptions = args.barOptions || {};
this.barOptions.height = this.barOptions.height
|| PERCENTAGE_BAR_DEFAULT_HEIGHT;
this.setup();
}
setupComponents() {
let s = this.state;
let componentConfigs = [
[
'percentageBars',
{
barHeight: this.barOptions.height
},
function() {
return {
xPositions: s.xPositions,
widths: s.widths,
colors: this.colors
};
}.bind(this)
]
];
this.components = new Map(componentConfigs
.map(args => {
let component = getComponent(...args);
return [args[0], component];
}));
}
calc() {
super.calc();
let s = this.state;
s.xPositions = [];
s.widths = [];
let xPos = 0;
s.sliceTotals.map((value, i) => {
let width = this.width * value / s.grandTotal;
s.widths.push(width);
s.xPositions.push(xPos);
xPos += width;
});
}
bindTooltip() {
let s = this.state;
this.container.addEventListener('mousemove', (e) => {
let slice = e.target;
if(slice.classList.contains('progress-bar')) {
let i = slice.getAttribute('data-index');
let gOff = getOffset(this.container), pOff = getOffset(slice);
let x = pOff.left - gOff.left + slice.offsetWidth/2;
let y = pOff.top - gOff.top - 6;
let title = (this.formattedLabels && this.formattedLabels.length>0
? this.formattedLabels[i] : this.state.labels[i]) + ': ';
let percent = (s.sliceTotals[i]*100/this.grandTotal).toFixed(1);
this.tip.setValues(x, y, {name: title, value: percent + "%"});
this.tip.showTip();
}
});
}
}
class PieChart extends AggregationChart {
constructor(parent, args) {
super(parent, args);
@ -2087,16 +2103,12 @@ class PieChart extends AggregationChart {
calc() {
super.calc();
let s = this.state;
this.center = {
x: this.width / 2,
y: this.height / 2
};
this.radius = (this.height > this.width ? this.center.x : this.center.y);
s.grandTotal = s.sliceTotals.reduce((a, b) => a + b, 0);
this.calcSlices();
}

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
.chart-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.chart-container .axis,.chart-container .chart-label{fill:#555b51}.chart-container .axis line,.chart-container .chart-label line{stroke:#dadada}.chart-container .dataset-units circle{stroke:#fff;stroke-width:2}.chart-container .dataset-units path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container .dataset-path{stroke-width:2px}.chart-container .path-group path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container line.dashed{stroke-dasharray:5,3}.chart-container .axis-line .specific-value{text-anchor:start}.chart-container .axis-line .y-line{text-anchor:end}.chart-container .axis-line .x-line{text-anchor:middle}.chart-container .progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.chart-container .progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#36414c;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.chart-container .graph-svg-tip{position:absolute;z-index:1;padding:10px;font-size:12px;color:#959da5;text-align:center;background:rgba(0,0,0,.8);border-radius:3px}.chart-container .graph-svg-tip ol,.chart-container .graph-svg-tip ul{padding-left:0;display:-webkit-box;display:-ms-flexbox;display:flex}.chart-container .graph-svg-tip ul.data-point-list li{min-width:90px;-webkit-box-flex:1;-ms-flex:1;flex:1;font-weight:600}.chart-container .graph-svg-tip strong{color:#dfe2e5;font-weight:600}.chart-container .graph-svg-tip .svg-pointer{position:absolute;height:5px;margin:0 0 0 -5px;content:" ";border:5px solid transparent;border-top-color:rgba(0,0,0,.8)}.chart-container .graph-svg-tip.comparison{padding:0;text-align:left;pointer-events:none}.chart-container .graph-svg-tip.comparison .title{display:block;padding:10px;margin:0;font-weight:600;line-height:1;pointer-events:none}.chart-container .graph-svg-tip.comparison ul{margin:0;white-space:nowrap;list-style:none}.chart-container .graph-svg-tip.comparison li{display:inline-block;padding:5px 10px}
.chart-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.chart-container .axis,.chart-container .chart-label{fill:#555b51}.chart-container .axis line,.chart-container .chart-label line{stroke:#dadada}.chart-container .dataset-units circle{stroke:#fff;stroke-width:2}.chart-container .dataset-units path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container .dataset-path{stroke-width:2px}.chart-container .path-group path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container line.dashed{stroke-dasharray:5,3}.chart-container .axis-line .specific-value{text-anchor:start}.chart-container .axis-line .y-line{text-anchor:end}.chart-container .axis-line .x-line{text-anchor:middle}.chart-container .graph-svg-tip{position:absolute;z-index:1;padding:10px;font-size:12px;color:#959da5;text-align:center;background:rgba(0,0,0,.8);border-radius:3px}.chart-container .graph-svg-tip ol,.chart-container .graph-svg-tip ul{padding-left:0;display:-webkit-box;display:-ms-flexbox;display:flex}.chart-container .graph-svg-tip ul.data-point-list li{min-width:90px;-webkit-box-flex:1;-ms-flex:1;flex:1;font-weight:600}.chart-container .graph-svg-tip strong{color:#dfe2e5;font-weight:600}.chart-container .graph-svg-tip .svg-pointer{position:absolute;height:5px;margin:0 0 0 -5px;content:" ";border:5px solid transparent;border-top-color:rgba(0,0,0,.8)}.chart-container .graph-svg-tip.comparison{padding:0;text-align:left;pointer-events:none}.chart-container .graph-svg-tip.comparison .title{display:block;padding:10px;margin:0;font-weight:600;line-height:1;pointer-events:none}.chart-container .graph-svg-tip.comparison ul{margin:0;white-space:nowrap;list-style:none}.chart-container .graph-svg-tip.comparison li{display:inline-block;padding:5px 10px}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -28,13 +28,19 @@ function __$styleInject(css, ref) {
}
}
// Universal constants
// Fixed 5-color theme,
// More colors are difficult to parse visually
// Universal constants
/**
* Returns whether or not two given arrays are equal.
* @param {Array} arr1 First array

File diff suppressed because one or more lines are too long

View File

@ -44,6 +44,8 @@ export default class AggregationChart extends BaseChart {
s.sliceTotals.push(d[0]);
s.labels.push(d[1]);
});
s.grandTotal = s.sliceTotals.reduce((a, b) => a + b, 0);
}
renderLegend() {
@ -67,5 +69,7 @@ export default class AggregationChart extends BaseChart {
// </span>`;
// }
// });
//
}
}

View File

@ -1,53 +1,59 @@
import AggregationChart from './AggregationChart';
import { $, getOffset } from '../utils/dom';
import { getComponent } from '../objects/ChartComponents';
import { PERCENTAGE_BAR_DEFAULT_HEIGHT } from '../utils/constants';
export default class PercentageChart extends AggregationChart {
constructor(parent, args) {
super(parent, args);
this.type = 'percentage';
this.barOptions = args.barOptions || {};
this.barOptions.height = this.barOptions.height
|| PERCENTAGE_BAR_DEFAULT_HEIGHT;
this.setup();
}
makeChartArea() {
this.container.className += ' ' + 'graph-focus-margin';
this.container.style.marginTop = '45px';
setupComponents() {
let s = this.state;
// this.statsWrapper.className += ' ' + 'graph-focus-margin';
// this.statsWrapper.style.marginBottom = '30px';
// this.statsWrapper.style.paddingTop = '0px';
let componentConfigs = [
[
'percentageBars',
{
barHeight: this.barOptions.height
},
function() {
return {
xPositions: s.xPositions,
widths: s.widths,
colors: this.colors
};
}.bind(this)
]
];
this.svg = $.create('div', {
className: 'div',
inside: this.container
});
this.chart = $.create('div', {
className: 'progress-chart',
inside: this.svg
});
this.percentageBar = $.create('div', {
className: 'progress',
inside: this.chart
});
this.components = new Map(componentConfigs
.map(args => {
let component = getComponent(...args);
return [args[0], component];
}));
}
render() {
calc() {
super.calc();
let s = this.state;
this.grandTotal = s.sliceTotals.reduce((a, b) => a + b, 0);
s.slices = [];
s.sliceTotals.map((total, i) => {
let slice = $.create('div', {
className: `progress-bar`,
'data-index': i,
inside: this.percentageBar,
styles: {
background: this.colors[i],
width: total*100/this.grandTotal + "%"
}
});
s.slices.push(slice);
s.xPositions = [];
s.widths = [];
let xPos = 0;
s.sliceTotals.map((value, i) => {
let width = this.width * value / s.grandTotal;
s.widths.push(width);
s.xPositions.push(xPos);
xPos += width;
});
}

View File

@ -38,8 +38,6 @@ export default class PieChart extends AggregationChart {
};
this.radius = (this.height > this.width ? this.center.x : this.center.y);
s.grandTotal = s.sliceTotals.reduce((a, b) => a + b, 0);
this.calcSlices();
}

View File

@ -1,5 +1,5 @@
import { makeSVGGroup } from '../utils/draw';
import { makePath, xLine, yLine, yMarker, yRegion, datasetBar, datasetDot, getPaths, heatSquare } from '../utils/draw';
import { makePath, xLine, yLine, yMarker, yRegion, datasetBar, datasetDot, percentageBar, getPaths, heatSquare } from '../utils/draw';
import { equilizeNoOfElements } from '../utils/draw-utils';
import { translateHoriLine, translateVertLine, animateRegion, animateBar,
animateDot, animatePath, animatePathStr } from '../utils/animate';
@ -57,7 +57,7 @@ class ChartComponent {
this.refresh();
let animateElements = [];
if(animate) {
animateElements = this.animateElements(this.data);
animateElements = this.animateElements(this.data) || [];
}
return animateElements;
}
@ -83,18 +83,15 @@ let componentConfigs = {
percentageBars: {
layerClass: 'percentage-bars',
makeElements(data) {
// return data.sliceStrings.map((s, i) =>{
// let slice = makePath(s, 'pie-path', 'none', data.colors[i]);
// slice.style.transition = 'transform .3s;';
// return slice;
// });
return data.xPositions.map((x, i) =>{
let y = 0;
let bar = percentageBar(x, y, data.widths[i],
this.constants.barHeight, data.colors[i]);
return bar;
});
},
animateElements(newData) {
// return this.store.map((slice, i) =>
// animatePathStr(slice, newData.sliceStrings[i])
// );
}
animateElements(newData) { }
},
yAxis: {
layerClass: 'y axis',
@ -255,11 +252,7 @@ let componentConfigs = {
return this.serializedSubDomains;
},
animateElements(newData) {
// return this.store.map((slice, i) =>
// animatePathStr(slice, newData.sliceStrings[i])
// );
}
animateElements(newData) { }
},
barGraph: {

View File

@ -37,11 +37,7 @@ export const MIN_BAR_PERCENT_HEIGHT = 0.01;
export const LINE_CHART_DOT_SIZE = 4;
export const DOT_OVERLAY_SIZE_INCR = 4;
export const DEFAULT_CHAR_WIDTH = 7;
// Universal constants
export const ANGLE_RATIO = Math.PI / 180;
export const FULL_ANGLE = 360;
export const PERCENTAGE_BAR_DEFAULT_HEIGHT = 20;
// Fixed 5-color theme,
// More colors are difficult to parse visually
@ -50,6 +46,8 @@ export const HEATMAP_DISTRIBUTION_SIZE = 5;
export const HEATMAP_SQUARE_SIZE = 10;
export const HEATMAP_GUTTER_SIZE = 2;
export const DEFAULT_CHAR_WIDTH = 7;
const HEATMAP_COLORS = ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'];
const DEFAULT_CHART_COLORS = ['light-blue', 'blue', 'violet', 'red', 'orange',
'yellow', 'green', 'light-green', 'purple', 'magenta', 'light-grey', 'dark-grey'];
@ -60,4 +58,8 @@ export const DEFAULT_COLORS = {
pie: DEFAULT_CHART_COLORS,
percentage: DEFAULT_CHART_COLORS,
heatmap: HEATMAP_COLORS
};
};
// Universal constants
export const ANGLE_RATIO = Math.PI / 180;
export const FULL_ANGLE = 360;

View File

@ -132,6 +132,19 @@ export function makeGradient(svgDefElem, color, lighter = false) {
return gradientId;
}
export function percentageBar(x, y, width, height, fill='none') {
let args = {
className: 'percentage-bar',
x: x,
y: y,
width: width,
height: height,
fill: fill
};
return createSVG("rect", args);
}
export function heatSquare(className, x, y, size, fill='none', data={}) {
let args = {
className: className,

View File

@ -51,30 +51,6 @@
text-anchor: middle;
}
}
.progress {
height: 20px;
margin-bottom: 20px;
overflow: hidden;
background-color: #f5f5f5;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
}
.progress-bar {
float: left;
width: 0;
height: 100%;
font-size: 12px;
line-height: 20px;
color: #fff;
text-align: center;
background-color: #36414c;
-webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);
-webkit-transition: width .6s ease;
-o-transition: width .6s ease;
transition: width .6s ease;
}
.graph-svg-tip {
position: absolute;