Browse Source

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

tags/1.2.0
Prateeksha Singh 7 years ago
parent
commit
a22c3eba33
17 changed files with 201 additions and 191 deletions
  1. +109
    -97
      dist/frappe-charts.esm.js
  2. +1
    -1
      dist/frappe-charts.min.cjs.js
  3. +1
    -1
      dist/frappe-charts.min.css
  4. +1
    -1
      dist/frappe-charts.min.esm.js
  5. +1
    -1
      dist/frappe-charts.min.iife.js
  6. +1
    -1
      dist/frappe-charts.min.iife.js.map
  7. +1
    -1
      docs/assets/js/frappe-charts.min.js
  8. +1
    -1
      docs/assets/js/frappe-charts.min.js.map
  9. +9
    -3
      docs/assets/js/index.min.js
  10. +1
    -1
      docs/assets/js/index.min.js.map
  11. +4
    -0
      src/js/charts/AggregationChart.js
  12. +40
    -34
      src/js/charts/PercentageChart.js
  13. +0
    -2
      src/js/charts/PieChart.js
  14. +10
    -17
      src/js/objects/ChartComponents.js
  15. +8
    -6
      src/js/utils/constants.js
  16. +13
    -0
      src/js/utils/draw.js
  17. +0
    -24
      src/scss/charts.scss

+ 109
- 97
dist/frappe-charts.esm.js 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();
}



+ 1
- 1
dist/frappe-charts.min.cjs.js
File diff suppressed because it is too large
View File


+ 1
- 1
dist/frappe-charts.min.css 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}

+ 1
- 1
dist/frappe-charts.min.esm.js
File diff suppressed because it is too large
View File


+ 1
- 1
dist/frappe-charts.min.iife.js
File diff suppressed because it is too large
View File


+ 1
- 1
dist/frappe-charts.min.iife.js.map
File diff suppressed because it is too large
View File


+ 1
- 1
docs/assets/js/frappe-charts.min.js
File diff suppressed because it is too large
View File


+ 1
- 1
docs/assets/js/frappe-charts.min.js.map
File diff suppressed because it is too large
View File


+ 9
- 3
docs/assets/js/index.min.js View File

@@ -28,12 +28,18 @@ function __$styleInject(css, ref) {
}
}

// Universal constants
// Fixed 5-color theme,
// More colors are difficult to parse visually



// Fixed 5-color theme,
// More colors are difficult to parse visually






// Universal constants

/**
* Returns whether or not two given arrays are equal.


+ 1
- 1
docs/assets/js/index.min.js.map
File diff suppressed because it is too large
View File


+ 4
- 0
src/js/charts/AggregationChart.js 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>`;
// }
// });

//
}
}

+ 40
- 34
src/js/charts/PercentageChart.js 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;
});
}



+ 0
- 2
src/js/charts/PieChart.js 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();
}



+ 10
- 17
src/js/objects/ChartComponents.js 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: {


+ 8
- 6
src/js/utils/constants.js 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;

+ 13
- 0
src/js/utils/draw.js 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,


+ 0
- 24
src/scss/charts.scss 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;


Loading…
Cancel
Save