diff --git a/src/Bar.js b/src/Bar.js index a755803..3f935d3 100644 --- a/src/Bar.js +++ b/src/Bar.js @@ -1,22 +1,20 @@ -import { addFontGaegu, addFontIndieFlower } from './utils/addFonts'; import { max } from 'd3-array'; import { axisBottom, axisLeft } from 'd3-axis'; -import { csv, tsv } from 'd3-fetch'; import { format } from 'd3-format'; import { scaleBand, scaleLinear } from 'd3-scale'; import { mouse, select, selectAll } from 'd3-selection'; import rough from 'roughjs/dist/rough.umd'; import get from 'lodash.get'; import { roughCeiling } from './utils/roughCeiling'; +import Chart from './Chart'; -class Bar { +class Bar extends Chart { constructor(opts) { + super(opts); + // load in arguments from config object - this.el = opts.element; this.data = opts.data; - this.element = opts.element; this.margin = opts.margin || { top: 50, right: 20, bottom: 70, left: 100 }; - this.title = opts.title; this.color = get(opts, 'color', 'skyblue'); this.highlight = get(opts, 'highlight', 'coral'); this.roughness = roughCeiling({ roughness: opts.roughness }); @@ -25,15 +23,8 @@ class Bar { this.axisStrokeWidth = get(opts, 'axisStrokeWidth', 0.5); this.axisRoughness = get(opts, 'axisRoughness', 0.5); this.innerStrokeWidth = get(opts, 'innerStrokeWidth', 1); - this.fillStyle = opts.fillStyle; - this.bowing = get(opts, 'bowing', 0); this.fillWeight = get(opts, 'fillWeight', 0.5); - this.simplification = get(opts, 'simplification', 0.2); - this.interactive = opts.interactive !== false; - this.titleFontSize = opts.titleFontSize; this.axisFontSize = opts.axisFontSize; - this.tooltipFontSize = get(opts, 'tooltipFontSize', '0.95rem'); - this.font = get(opts, 'font', 0); this.dataFormat = (typeof opts.data === 'object') ? 'object' : 'file'; this.labels = (this.dataFormat === 'object') ? 'labels' : opts.labels; this.values = (this.dataFormat === 'object') ? 'values' : opts.values; @@ -44,81 +35,13 @@ class Bar { this.yLabel = get(opts, 'yLabel', ''); this.labelFontSize = get(opts, 'labelFontSize', '1rem'); // new width - this.initChartValues(opts); + this.initChartValues(opts, 350, 450); // resolve font this.resolveFont(); // create the chart this.drawChart = this.resolveData(opts.data); this.drawChart(); - if (opts.title !== 'undefined') this.setTitle(opts.title); - } - - initChartValues(opts) { - let width = opts.width ? opts.width : 350; - let height = opts.height ? opts.height : 450; - this.width = width - this.margin.left - this.margin.right; - this.height = height - this.margin.top - this.margin.bottom; - this.roughId = this.el + '_svg'; - this.graphClass = this.el.substring(1, this.el.length); - this.interactionG = 'g.' + this.graphClass; - this.setSvg(); - } - - setSvg() { - this.svg = select(this.el) - .append('svg') - .attr('width', this.width + this.margin.left + this.margin.right) - .attr('height', this.height + this.margin.top + this.margin.bottom) - .append('g') - .attr('id', this.roughId) - .attr('transform', - 'translate(' + this.margin.left + ',' + this.margin.top + ')'); - } - - resolveFont() { - if ( - this.font === 0 || - this.font === undefined || - this.font.toString().toLowerCase() === 'gaegu' - ) { - addFontGaegu(this.svg); - this.fontFamily = 'gaeguregular'; - } else if ( - this.font === 1 || - this.font.toString().toLowerCase() === 'indie flower' - ) { - addFontIndieFlower(this.svg); - this.fontFamily = 'indie_flowerregular'; - } else { - this.fontFamily = this.font; - } - } - - // add this to abstract base - resolveData(data) { - if (typeof data === 'string') { - if (data.includes('.csv')) { - return () => { - csv(data).then(d => { - // console.log(d); - this.data = d; - this.drawFromFile(); - }); - }; - } else if (data.includes('.tsv')) { - return () => { - tsv(data).then(d => { - this.data = d; - this.drawFromFile(); - }); - }; - } - } else { - return () => { - this.data = data; - this.drawFromObject(); - }; - } + if (opts.title !== 'undefined') this.setTitle(opts.title, { fontSizeFactor: 5 }); } addScales() { @@ -238,20 +161,6 @@ class Bar { }); } - setTitle(title) { - this.svg.append('text') - .attr('x', (this.width / 2)) - .attr('y', 0 - (this.margin.top / 2)) - .attr('class', 'title') - .attr('text-anchor', 'middle') - .style('font-size', (this.titleFontSize === undefined) ? - `${Math.min(40, Math.min(this.width, this.height) / 5)}px` : - this.titleFontSize) - .style('font-family', this.fontFamily) - .style('opacity', 0.8) - .text(title); - } - addInteraction() { selectAll(this.interactionG) diff --git a/src/BarH.js b/src/BarH.js index ea68c64..47bf7b1 100644 --- a/src/BarH.js +++ b/src/BarH.js @@ -1,22 +1,20 @@ -import { addFontGaegu, addFontIndieFlower } from './utils/addFonts'; import { max } from 'd3-array'; import { axisBottom, axisLeft } from 'd3-axis'; -import { csv, tsv } from 'd3-fetch'; import { format } from 'd3-format'; import { scaleBand, scaleLinear } from 'd3-scale'; import { mouse, select, selectAll } from 'd3-selection'; import rough from 'roughjs/dist/rough.umd'; import get from 'lodash.get'; import { roughCeiling } from './utils/roughCeiling'; +import Chart from './Chart'; -class BarH { +class BarH extends Chart { constructor(opts) { + super(opts); + // load in arguments from config object - this.el = opts.element; // this.data = opts.data; - this.element = opts.element; this.margin = opts.margin || { top: 50, right: 20, bottom: 50, left: 100 }; - this.title = opts.title; this.color = get(opts, 'color', 'skyblue'); this.highlight = get(opts, 'highlight', 'coral'); this.roughness = roughCeiling({ roughness: opts.roughness }); @@ -25,15 +23,8 @@ class BarH { this.axisStrokeWidth = get(opts, 'axisStrokeWidth', 0.5); this.axisRoughness = get(opts, 'axisRoughness', 0.5); this.innerStrokeWidth = get(opts, 'innerStrokeWidth', 1); - this.fillStyle = opts.fillStyle; - this.bowing = get(opts, 'bowing', 0); this.fillWeight = get(opts, 'fillWeight', 0.5); - this.simplification = get(opts, 'simplification', 0.2); - this.interactive = opts.interactive !== false; - this.titleFontSize = opts.titleFontSize; this.axisFontSize = opts.axisFontSize; - this.tooltipFontSize = get(opts, 'tooltipFontSize', '0.95rem'); - this.font = get(opts, 'font', 0); this.dataFormat = (typeof opts.data === 'object') ? 'object' : 'file'; this.labels = (this.dataFormat === 'object') ? 'labels' : opts.labels; this.values = (this.dataFormat === 'object') ? 'values' : opts.values; @@ -44,81 +35,13 @@ class BarH { this.yLabel = get(opts, 'yLabel', ''); this.labelFontSize = get(opts, 'labelFontSize', '1rem'); // new width - this.initChartValues(opts); + this.initChartValues(opts, 350, 450); // resolve font this.resolveFont(); // create the chart this.drawChart = this.resolveData(opts.data); this.drawChart(); - if (opts.title !== 'undefined') this.setTitle(opts.title); - } - - initChartValues(opts) { - let width = opts.width ? opts.width : 350; - let height = opts.height ? opts.height : 450; - this.width = width - this.margin.left - this.margin.right; - this.height = height - this.margin.top - this.margin.bottom; - this.roughId = this.el + '_svg'; - this.graphClass = this.el.substring(1, this.el.length); - this.interactionG = 'g.' + this.graphClass; - this.setSvg(); - } - - setSvg() { - this.svg = select(this.el) - .append('svg') - .attr('width', this.width + this.margin.left + this.margin.right) - .attr('height', this.height + this.margin.top + this.margin.bottom) - .append('g') - .attr('id', this.roughId) - .attr('transform', - 'translate(' + this.margin.left + ',' + this.margin.top + ')'); - } - - resolveFont() { - if ( - this.font === 0 || - this.font === undefined || - this.font.toString().toLowerCase() === 'gaegu' - ) { - addFontGaegu(this.svg); - this.fontFamily = 'gaeguregular'; - } else if ( - this.font === 1 || - this.font.toString().toLowerCase() === 'indie flower' - ) { - addFontIndieFlower(this.svg); - this.fontFamily = 'indie_flowerregular'; - } else { - this.fontFamily = this.font; - } - } - - // add this to abstract base - resolveData(data) { - if (typeof data === 'string') { - if (data.includes('.csv')) { - return () => { - csv(data).then(d => { - console.log(d); - this.data = d; - this.drawFromFile(); - }); - }; - } else if (data.includes('.tsv')) { - return () => { - tsv(data).then(d => { - this.data = d; - this.drawFromFile(); - }); - }; - } - } else { - return () => { - this.data = data; - this.drawFromObject(); - }; - } + if (opts.title !== 'undefined') this.setTitle(opts.title, { fontSizeFactor: 5 }); } addScales() { @@ -240,20 +163,6 @@ class BarH { }); } - setTitle(title) { - this.svg.append('text') - .attr('x', (this.width / 2)) - .attr('y', 0 - (this.margin.top / 2)) - .attr('class', 'title') - .attr('text-anchor', 'middle') - .style('font-size', (this.titleFontSize === undefined) ? - `${Math.min(40, Math.min(this.width, this.height) / 5)}px` : - this.titleFontSize) - .style('font-family', this.fontFamily) - .style('opacity', 0.8) - .text(title); - } - addInteraction() { // add highlight helper dom nodes selectAll(this.interactionG) diff --git a/src/Chart.js b/src/Chart.js new file mode 100644 index 0000000..54f8591 --- /dev/null +++ b/src/Chart.js @@ -0,0 +1,135 @@ +import { csv, tsv, json } from 'd3-fetch'; +import { select } from 'd3-selection'; +import get from 'lodash.get'; +import { addFontGaegu, addFontIndieFlower } from './utils/addFonts'; + +class Chart { + constructor(opts) { + this.el = opts.element; + this.element = opts.element; + this.title = opts.title; + this.titleFontSize = opts.titleFontSize; + this.font = get(opts, 'font', 0); + this.fillStyle = opts.fillStyle; + this.tooltipFontSize = get(opts, 'tooltipFontSize', '0.95rem'); + this.bowing = get(opts, 'bowing', 0); + this.simplification = get(opts, 'simplification', 0.2); + this.interactive = opts.interactive !== false; + } + + initChartValues(opts, chartWidth, chartHeight, addRadius = false) { + const width = opts.width ? opts.width : chartWidth; + const height = opts.height ? opts.height : chartHeight; + + this.width = width - this.margin.left - this.margin.right; + this.height = height - this.margin.top - this.margin.bottom; + this.roughId = this.el + '_svg'; + this.graphClass = this.el.substring(1, this.el.length); + this.interactionG = 'g.' + this.graphClass; + + if (addRadius) { + this.radius = Math.min(this.width, this.height) / 2; + }; + + this.setSvg(); + } + + setSvg() { + this.svg = select(this.el) + .append('svg') + .attr('width', this.width + this.margin.left + this.margin.right) + .attr('height', this.height + this.margin.top + this.margin.bottom) + .append('g') + .attr('id', this.roughId) + .attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')'); + } + + resolveFont() { + if ( + this.font === 0 || + this.font === undefined || + this.font.toString().toLowerCase() === 'gaegu' + ) { + addFontGaegu(this.svg); + this.fontFamily = 'gaeguregular'; + } else if ( + this.font === 1 || + this.font.toString().toLowerCase() === 'indie flower' + ) { + addFontIndieFlower(this.svg); + this.fontFamily = 'indie_flowerregular'; + } else { + this.fontFamily = this.font; + } + } + + resolveData(data, processStackedData = false) { + // if data from file, read in + // else if data from json object, read in + if (typeof data === 'string') { + if (data.includes('.csv')) { + return () => { + csv(data).then(d => { + this.data = d; + this.drawFromFile(); + }); + }; + } else if (data.includes('.tsv')) { + return () => { + tsv(data).then(d => { + this.data = d; + this.drawFromFile(); + }); + }; + } else if (data.includes('.json')) { + return () => { + json(data).then((d) => { + this.data = d; + this.drawFromFile(); + }); + }; + } + } else { + return () => { + this.data = data; + if (processStackedData) { + for (let i = 0; i < data.length; ++i) { + let t = 0; + let keys = Object.keys(data[i]); + keys.forEach(d => { + if (d !== this.labels) { + t += data[i][d]; + data[i].total = t; + } + }); + } + }; + this.drawFromObject(); + }; + } + } + + drawFromFile() { + throw Error('Please implement drawFromFile()'); + } + + drawFromObject() { + throw Error('Please implement drawFromObject()'); + } + + setTitle(title, { marginTopFactor = 2, fontSizeMin = 40, fontSizeFactor = 4 }) { + this.svg.append('text') + .attr('x', this.width / 2) + .attr('y', 0 - (this.margin.top / marginTopFactor)) + .attr('class', 'title') + .attr('text-anchor', 'middle') + .style('font-size', (this.titleFontSize === undefined) ? + `${Math.min(fontSizeMin, Math.min(this.width, this.height) / fontSizeFactor)}px` : + this.titleFontSize) + .style('font-family', this.fontFamily) + .style('opacity', 0.8) + .text(title); + } +} + +export default Chart; diff --git a/src/Donut.js b/src/Donut.js index 5bd7878..51c53c0 100644 --- a/src/Donut.js +++ b/src/Donut.js @@ -1,5 +1,3 @@ -import { addFontGaegu, addFontIndieFlower } from './utils/addFonts'; -import { csv, tsv, json } from 'd3-fetch'; import { mouse, select, selectAll } from 'd3-selection'; import { arc, pie } from 'd3-shape'; import rough from 'roughjs/dist/rough.umd'; @@ -7,28 +5,21 @@ import { colors } from './utils/colors'; import { addLegend } from './utils/addLegend'; import { roughCeiling } from './utils/roughCeiling'; import get from 'lodash.get'; +import Chart from './Chart'; -class Donut { +class Donut extends Chart { constructor(opts) { + super(opts); + // load in arguments from config object - this.el = opts.element; // this.data = opts.data; - this.element = opts.element; this.margin = opts.margin || { top: 50, right: 20, bottom: 10, left: 20 }; - this.title = opts.title; this.colors = get(opts, 'colors', colors); this.highlight = opts.highlight; this.roughness = roughCeiling({ roughness: opts.roughness, ceiling: 30 }); this.strokeWidth = get(opts, 'strokeWidth', 0.75); this.innerStrokeWidth = get(opts, 'innerStrokeWidth', 0.75); - this.fillStyle = opts.fillStyle; - this.bowing = get(opts, 'bowing', 0); this.fillWeight = get(opts, 'fillWeight', 0.85); - this.simplification = get(opts, 'simplification', 0.2); - this.interactive = opts.interactive !== false; - this.titleFontSize = opts.titleFontSize; - this.tooltipFontSize = get(opts, 'tooltipFontSize', '0.95rem'); - this.font = get(opts, 'font', 0); this.dataFormat = typeof opts.data === 'object' ? 'object' : 'file'; this.labels = this.dataFormat === 'object' ? 'labels' : opts.labels; this.values = this.dataFormat === 'object' ? 'values' : opts.values; @@ -40,111 +31,13 @@ class Donut { this.legend = opts.legend !== false; this.legendPosition = get(opts, 'legendPosition', 'right'); // new width - this.initChartValues(opts); + this.initChartValues(opts, 300, 300, true); // resolve font this.resolveFont(); // create the chart this.drawChart = this.resolveData(opts.data); this.drawChart(); - if (opts.title !== 'undefined') this.setTitle(opts.title); - } - - initChartValues(opts) { - let width = opts.width ? opts.width : 300; - let height = opts.height ? opts.height : 300; - this.width = width - this.margin.left - this.margin.right; - this.height = height - this.margin.top - this.margin.bottom; - this.roughId = this.el + '_svg'; - this.graphClass = this.el.substring(1, this.el.length); - this.interactionG = 'g.' + this.graphClass; - this.radius = Math.min(this.width, this.height) / 2; - this.setSvg(); - } - - setSvg() { - this.svg = select(this.el) - .append('svg') - .attr('width', this.width + this.margin.left + this.margin.right) - .attr('height', this.height + this.margin.top + this.margin.bottom) - .append('g') - .attr('id', this.roughId) - .attr( - 'transform', - 'translate(' + this.margin.left + ',' + this.margin.top + ')' - ); - } - - resolveFont() { - if ( - this.font === 0 || - this.font === undefined || - this.font.toString().toLowerCase() === 'gaegu' - ) { - addFontGaegu(this.svg); - this.fontFamily = 'gaeguregular'; - } else if ( - this.font === 1 || - this.font.toString().toLowerCase() === 'indie flower' - ) { - addFontIndieFlower(this.svg); - this.fontFamily = 'indie_flowerregular'; - } else { - this.fontFamily = this.font; - } - } - - // add this to abstract base - resolveData(data) { - if (typeof data === 'string') { - if (data.includes('.csv')) { - return () => { - csv(data).then(d => { - // console.log(d); - this.data = d; - this.drawFromFile(); - }); - }; - } else if (data.includes('.tsv')) { - return () => { - tsv(data).then(d => { - // console.log(d); - this.data = d; - this.drawFromFile(); - }); - }; - } else if (data.includes('.json')) { - return () => { - json(data).then(d => { - // console.log(d); - this.data = d; - this.drawFromFile(); - }); - }; - } - } else { - return () => { - this.data = data; - this.drawFromObject(); - }; - } - } - - setTitle(title) { - this.svg - .append('text') - .attr('x', this.width / 2) - .attr('y', 0 - this.margin.top / 3) - .attr('class', 'title') - .attr('text-anchor', 'middle') - .style( - 'font-size', - this.titleFontSize === undefined - ? `${Math.min(40, Math.min(this.width, this.height) / 4)}px` - : this.titleFontSize - ) - .style('font-family', this.fontFamily) - .style('opacity', 0.8) - .text(title); + if (opts.title !== 'undefined') this.setTitle(opts.title, { marginTopFactor: 3 }); } addInteraction() { diff --git a/src/Line.js b/src/Line.js index 16ad2a6..7901a67 100644 --- a/src/Line.js +++ b/src/Line.js @@ -1,8 +1,6 @@ import { bisect, extent, max, min, range } from 'd3-array'; import { axisBottom, axisLeft } from 'd3-axis'; -import { csv, tsv } from 'd3-fetch'; import { format } from 'd3-format'; -import { addFontGaegu, addFontIndieFlower } from './utils/addFonts'; import { addLegend } from './utils/addLegend'; import { scaleLinear, scalePoint } from 'd3-scale'; import { mouse, select, selectAll } from 'd3-selection'; @@ -11,6 +9,7 @@ import rough from 'roughjs/dist/rough.umd'; import { colors } from './utils/colors'; import { roughCeiling } from './utils/roughCeiling'; import get from 'lodash.get'; +import Chart from './Chart'; const allDataExtent = (data) => { // get extend for all keys in data @@ -21,28 +20,20 @@ const allDataExtent = (data) => { return [dataMin, dataMax]; }; -class Line { +class Line extends Chart { constructor(opts) { + super(opts); + // load in arguments from config object - this.el = opts.element; - this.element = opts.element; this.margin = opts.margin || { top: 50, right: 20, bottom: 50, left: 100 }; - this.title = opts.title; this.roughness = roughCeiling({ roughness: opts.roughness, defaultValue: 2.2 }); - this.fillStyle = opts.fillStyle; - this.bowing = get(opts, 'bowing', 0); this.axisStrokeWidth = get(opts, 'axisStrokeWidth', 0.4); this.axisRoughness = get(opts, 'axisRoughness', 0.9); - this.interactive = opts.interactive !== false; this.stroke = get(opts, 'stroke', 'black'); this.fillWeight = get(opts, 'fillWeight', 0.85); - this.simplification = get(opts, 'simplification', 0.2); - this.colors = opts.colors; + this.colors = get(opts, 'colors', colors); this.strokeWidth = get(opts, 'strokeWidth', 8); - this.titleFontSize = opts.titleFontSize; this.axisFontSize = opts.axisFontSize; - this.tooltipFontSize = get(opts, 'tooltipFontSize', '0.95rem'); - this.font = get(opts, 'font', 0); this.dataFormat = (typeof opts.data === 'object') ? 'object' : 'file'; this.x = opts.x; this.y = (this.dataFormat === 'object') ? 'y' : opts.y; @@ -64,80 +55,13 @@ class Line { }); }; // new width - this.initChartValues(opts); + this.initChartValues(opts, 300, 400); // resolve font this.resolveFont(); // create the chart this.drawChart = this.resolveData(opts.data); this.drawChart(); - if (opts.title !== 'undefined') this.setTitle(opts.title); - } - - resolveFont() { - if ( - this.font === 0 || - this.font === undefined || - this.font.toString().toLowerCase() === 'gaegu' - ) { - addFontGaegu(this.svg); - this.fontFamily = 'gaeguregular'; - } else if ( - this.font === 1 || - this.font.toString().toLowerCase() === 'indie flower' - ) { - addFontIndieFlower(this.svg); - this.fontFamily = 'indie_flowerregular'; - } else { - this.fontFamily = this.font; - } - } - - initChartValues(opts) { - let width = opts.width ? opts.width : 300; - let height = opts.height ? opts.height : 400; - this.width = width - this.margin.left - this.margin.right; - this.height = height - this.margin.top - this.margin.bottom; - this.roughId = this.el + '_svg'; - this.graphClass = this.el.substring(1, this.el.length); - this.interactionG = 'g.' + this.graphClass; - this.setSvg(); - } - - setSvg() { - this.svg = select(this.el) - .append('svg') - .attr('width', this.width + this.margin.left + this.margin.right) - .attr('height', this.height + this.margin.top + this.margin.bottom) - .append('g') - .attr('id', this.roughId) - .attr('transform', - 'translate(' + this.margin.left + ',' + this.margin.top + ')'); - } - - // add this to abstract base - resolveData(data) { - if (typeof data === 'string') { - if (data.includes('.csv')) { - return () => { - csv(data).then(d => { - this.data = d; - this.drawFromFile(); - }); - }; - } else if (data.includes('.tsv')) { - return () => { - tsv(data).then(d => { - this.data = d; - this.drawFromFile(); - }); - }; - } - } else { - return () => { - this.data = data; - this.drawFromObject(); - }; - } + if (opts.title !== 'undefined') this.setTitle(opts.title, { fontSizeMin: 20 }); } addScales() { @@ -287,19 +211,6 @@ class Line { }); } - setTitle(title) { - this.svg.append('text') - .attr('x', (this.width / 2)) - .attr('y', 0 - (this.margin.top / 2)) - .attr('text-anchor', 'middle') - .style('font-size', (this.titleFontSize === undefined) ? - `${Math.min(20, Math.min(this.width, this.height) / 4)}px` : - this.titleFontSize) - .style('font-family', this.fontFamily) - .style('opacity', 0.8) - .text(title); - } - addInteraction() { const that = this; this.chartScreen = this.svg.append('g') @@ -423,9 +334,6 @@ class Line { } drawFromObject() { - // set default color - if (this.colors === undefined) this.colors = colors; - this.dataSources = Object.keys(this.data); this.initRoughObjects(); this.addScales(); @@ -489,10 +397,6 @@ class Line { } drawFromFile() { - - // set default colors - if (this.colors === undefined) this.colors = colors; - this.initRoughObjects(); this.addScales(); diff --git a/src/Pie.js b/src/Pie.js index 1aab87b..8259828 100644 --- a/src/Pie.js +++ b/src/Pie.js @@ -1,5 +1,3 @@ -import { addFontGaegu, addFontIndieFlower } from './utils/addFonts'; -import { csv, tsv, json } from 'd3-fetch'; import { mouse, select, selectAll } from 'd3-selection'; import { arc, pie } from 'd3-shape'; import rough from 'roughjs/dist/rough.umd'; @@ -7,28 +5,21 @@ import { colors } from './utils/colors'; import { addLegend } from './utils/addLegend'; import { roughCeiling } from './utils/roughCeiling'; import get from 'lodash.get'; +import Chart from './Chart'; -class Pie { +class Pie extends Chart { constructor(opts) { + super(opts); + // load in arguments from config object - this.el = opts.element; // this.data = opts.data; - this.element = opts.element; this.margin = opts.margin || { top: 50, right: 20, bottom: 10, left: 20 }; - this.title = opts.title; this.colors = get(opts, 'colors', colors); this.highlight = opts.highlight; this.roughness = roughCeiling({ roughness: opts.roughness, ceiling: 30, defaultValue: 0 }); this.strokeWidth = get(opts, 'strokeWidth', 0.75); this.innerStrokeWidth = get(opts, 'innerStrokeWidth', 1); - this.fillStyle = opts.fillStyle; - this.bowing = get(opts, 'bowing', 0); this.fillWeight = get(opts, 'fillWeight', 0.5); - this.simplification = get(opts, 'simplification', 0.2); - this.interactive = opts.interactive !== false; - this.titleFontSize = opts.titleFontSize; - this.tooltipFontSize = get(opts, 'tooltipFontSize', '0.95rem'); - this.font = get(opts, 'font', 0); this.dataFormat = (typeof opts.data === 'object') ? 'object' : 'file'; this.labels = (this.dataFormat === 'object') ? 'labels' : opts.labels; this.values = (this.dataFormat === 'object') ? 'values' : opts.values; @@ -40,107 +31,13 @@ class Pie { this.legend = opts.legend !== false; this.legendPosition = get(opts, 'legendPosition', 'right'); // new width - this.initChartValues(opts); + this.initChartValues(opts, 350, 450, true); // resolve font this.resolveFont(); // create the chart this.drawChart = this.resolveData(opts.data); this.drawChart(); - if (opts.title !== 'undefined') this.setTitle(opts.title); - } - - initChartValues(opts) { - let width = opts.width ? opts.width : 350; - let height = opts.height ? opts.height : 450; - this.width = width - this.margin.left - this.margin.right; - this.height = height - this.margin.top - this.margin.bottom; - this.roughId = this.el + '_svg'; - this.graphClass = this.el.substring(1, this.el.length); - this.interactionG = 'g.' + this.graphClass; - this.radius = Math.min(this.width, this.height) / 2; - this.setSvg(); - } - - setSvg() { - this.svg = select(this.el) - .append('svg') - .attr('width', this.width + this.margin.left + this.margin.right) - .attr('height', this.height + this.margin.top + this.margin.bottom) - .append('g') - .attr('id', this.roughId) - .attr('transform', - 'translate(' + this.margin.left + ',' + this.margin.top + ')'); - } - - resolveFont() { - if ( - this.font === 0 || - this.font === undefined || - this.font.toString().toLowerCase() === 'gaegu' - ) { - addFontGaegu(this.svg); - this.fontFamily = 'gaeguregular'; - } else if ( - this.font === 1 || - this.font.toString().toLowerCase() === 'indie flower' - ) { - addFontIndieFlower(this.svg); - this.fontFamily = 'indie_flowerregular'; - } else { - this.fontFamily = this.font; - } - } - - // add this to abstract base - resolveData(data) { - // if data from file, read in - // else if data from json object, read in - if (typeof data === 'string') { - if (data.includes('.csv')) { - return () => { - csv(data).then(d => { - console.log(d); - this.data = d; - this.drawFromFile(); - }); - }; - } else if (data.includes('.tsv')) { - return () => { - tsv(data).then(d => { - console.log(d); - this.data = d; - this.drawFromFile(); - }); - }; - } else if (data.includes('.json')) { - return () => { - json(data).then((d) => { - console.log(d); - this.data = d; - this.drawFromFile(); - }); - }; - } - } else { - return () => { - this.data = data; - this.drawFromObject(); - }; - } - } - - setTitle(title) { - this.svg.append('text') - .attr('x', (this.width / 2)) - .attr('y', 0 - (this.margin.top / 3)) - .attr('class', 'title') - .attr('text-anchor', 'middle') - .style('font-size', (this.titleFontSize === undefined) ? - `${Math.min(40, Math.min(this.width, this.height) / 4)}px` : - this.titleFontSize) - .style('font-family', this.fontFamily) - .style('opacity', 0.8) - .text(title); + if (opts.title !== 'undefined') this.setTitle(opts.title, { marginTopFactor: 3 }); } addInteraction() { diff --git a/src/Scatter.js b/src/Scatter.js index 76d09d3..b6f2f35 100644 --- a/src/Scatter.js +++ b/src/Scatter.js @@ -1,46 +1,37 @@ import { extent } from 'd3-array'; import { axisBottom, axisLeft } from 'd3-axis'; -import { csv, tsv } from 'd3-fetch'; import { format } from 'd3-format'; -import { addFontGaegu, addFontIndieFlower } from './utils/addFonts'; import { roughCeiling } from './utils/roughCeiling'; import { scaleLinear, scaleOrdinal } from 'd3-scale'; import { mouse, select, selectAll } from 'd3-selection'; import rough from 'roughjs/dist/rough.umd'; import get from 'lodash.get'; +import Chart from './Chart'; const defaultColors = ['pink', 'skyblue', 'coral', 'gold', 'teal', 'grey', 'darkgreen', 'pink', 'brown', 'slateblue', 'grey1', 'orange']; -class Scatter { +class Scatter extends Chart { constructor(opts) { + super(opts); + // load in arguments from config object - this.el = opts.element; // this.data = opts.data; - this.element = opts.element; this.margin = opts.margin || { top: 50, right: 20, bottom: 50, left: 100 }; - this.title = opts.title; this.colorVar = opts.colorVar; this.roughness = roughCeiling({ roughness: opts.roughness }); this.highlight = opts.highlight; this.highlightLabel = get(opts, 'highlightLabel', 'xy'); this.radius = get(opts, 'radius', 8); - this.fillStyle = opts.fillStyle; - this.bowing = get(opts, 'bowing', 0); this.axisStrokeWidth = get(opts, 'axisStrokeWidth', 0.4); this.axisRoughness = get(opts, 'axisRoughness', 0.9); - this.interactive = opts.interactive !== false; this.curbZero = opts.curbZero === true; this.innerStrokeWidth = get(opts, 'innerStrokeWidth', 1); this.stroke = get(opts, 'stroke', 'black'); this.fillWeight = get(opts, 'fillWeight', 0.85); - this.simplification = get(opts, 'simplification', 0.2); this.colors = opts.colors; this.strokeWidth = get(opts, 'strokeWidth', 1); - this.titleFontSize = opts.titleFontSize; this.axisFontSize = opts.axisFontSize; - this.tooltipFontSize = get(opts, 'tooltipFontSize', '0.95rem'); - this.font = get(opts, 'font', 0); this.dataFormat = (typeof opts.data === 'object') ? 'object' : 'file'; this.x = (this.dataFormat === 'object') ? 'x' : opts.x; this.y = (this.dataFormat === 'object') ? 'y' : opts.y; @@ -50,81 +41,13 @@ class Scatter { this.yLabel = get(opts, 'yLabel', ''); this.labelFontSize = get(opts, 'labelFontSize', '1rem'); // new width - this.initChartValues(opts); + this.initChartValues(opts, 300, 400); // resolve font this.resolveFont(); // create the chart this.drawChart = this.resolveData(opts.data); this.drawChart(); - if (opts.title !== 'undefined') this.setTitle(opts.title); - } - - resolveFont() { - if ( - this.font === 0 || - this.font === undefined || - this.font.toString().toLowerCase() === 'gaegu' - ) { - addFontGaegu(this.svg); - this.fontFamily = 'gaeguregular'; - } else if ( - this.font === 1 || - this.font.toString().toLowerCase() === 'indie flower' - ) { - addFontIndieFlower(this.svg); - this.fontFamily = 'indie_flowerregular'; - } else { - this.fontFamily = this.font; - } - } - - initChartValues(opts) { - let width = opts.width ? opts.width : 300; - let height = opts.height ? opts.height : 400; - this.width = width - this.margin.left - this.margin.right; - this.height = height - this.margin.top - this.margin.bottom; - this.roughId = this.el + '_svg'; - this.graphClass = this.el.substring(1, this.el.length); - this.interactionG = 'g.' + this.graphClass; - this.setSvg(); - } - - setSvg() { - this.svg = select(this.el) - .append('svg') - .attr('width', this.width + this.margin.left + this.margin.right) - .attr('height', this.height + this.margin.top + this.margin.bottom) - .append('g') - .attr('id', this.roughId) - .attr('transform', - 'translate(' + this.margin.left + ',' + this.margin.top + ')'); - } - - // add this to abstract base - resolveData(data) { - if (typeof data === 'string') { - if (data.includes('.csv')) { - return () => { - csv(data).then(d => { - console.log(d); - this.data = d; - this.drawFromFile(); - }); - }; - } else if (data.includes('.tsv')) { - return () => { - tsv(data).then(d => { - this.data = d; - this.drawFromFile(); - }); - }; - } - } else { - return () => { - this.data = data; - this.drawFromObject(); - }; - } + if (opts.title !== 'undefined') this.setTitle(opts.title, { fontSizeMin: 20 }); } addScales() { @@ -269,19 +192,6 @@ class Scatter { }); } - setTitle(title) { - this.svg.append('text') - .attr('x', (this.width / 2)) - .attr('y', 0 - (this.margin.top / 2)) - .attr('text-anchor', 'middle') - .style('font-size', (this.titleFontSize === undefined) ? - `${Math.min(20, Math.min(this.width, this.height) / 4)}px` : - this.titleFontSize) - .style('font-family', this.fontFamily) - .style('opacity', 0.8) - .text(title); - } - addInteraction() { // add highlight helper dom nodes diff --git a/src/StackedBar.js b/src/StackedBar.js index dd8491c..bfd6b3f 100644 --- a/src/StackedBar.js +++ b/src/StackedBar.js @@ -1,22 +1,20 @@ -import { addFontGaegu, addFontIndieFlower } from './utils/addFonts'; import { max } from 'd3-array'; import { axisBottom, axisLeft } from 'd3-axis'; -import { csv, tsv } from 'd3-fetch'; import { scaleBand, scaleLinear, scaleOrdinal } from 'd3-scale'; import { mouse, select, selectAll } from 'd3-selection'; import { colors } from './utils/colors'; import { roughCeiling } from './utils/roughCeiling'; import rough from 'roughjs/dist/rough.umd'; import get from 'lodash.get'; +import Chart from './Chart'; -class StackedBar { +class StackedBar extends Chart { constructor(opts) { + super(opts); + // load in arguments from config object - this.el = opts.element; this.data = opts.data; - this.element = opts.element; this.margin = opts.margin || { top: 50, right: 20, bottom: 70, left: 100 }; - this.title = opts.title; this.colors = get(opts, 'colors', colors); this.highlight = get(opts, 'highlight', 'coral'); this.roughness = roughCeiling({ roughness: opts.roughness }); @@ -25,15 +23,8 @@ class StackedBar { this.axisStrokeWidth = get(opts, 'axisStrokeWidth', 0.5); this.axisRoughness = get(opts, 'axisRoughness', 0.5); this.innerStrokeWidth = get(opts, 'innerStrokeWidth', 1); - this.fillStyle = opts.fillStyle; - this.bowing = get(opts, 'bowing', 0); this.fillWeight = get(opts, 'fillWeight', 0.5); - this.simplification = get(opts, 'simplification', 0.2); - this.interactive = opts.interactive !== false; - this.titleFontSize = opts.titleFontSize; this.axisFontSize = opts.axisFontSize; - this.tooltipFontSize = get(opts, 'tooltipFontSize', '0.95rem'); - this.font = get(opts, 'font', 0); this.dataFormat = typeof opts.data === 'object' ? 'object' : 'file'; this.labels = opts.labels; this.values = opts.values; @@ -42,56 +33,13 @@ class StackedBar { this.yLabel = get(opts, 'yLabel', ''); this.labelFontSize = get(opts, 'labelFontSize', '1rem'); // new width - this.initChartValues(opts); + this.initChartValues(opts, 350, 450); // resolve font this.resolveFont(); // create the chart - this.drawChart = this.resolveData(opts.data); + this.drawChart = this.resolveData(opts.data, true); this.drawChart(); - if (opts.title !== 'undefined') this.setTitle(opts.title); - } - - initChartValues(opts) { - let width = opts.width ? opts.width : 350; - let height = opts.height ? opts.height : 450; - this.width = width - this.margin.left - this.margin.right; - this.height = height - this.margin.top - this.margin.bottom; - this.roughId = this.el + '_svg'; - this.graphClass = this.el.substring(1, this.el.length); - this.interactionG = 'g.' + this.graphClass; - this.setSvg(); - } - - setSvg() { - this.svg = select(this.el) - .append('svg') - .attr('width', this.width + this.margin.left + this.margin.right) - .attr('height', this.height + this.margin.top + this.margin.bottom) - .append('g') - .attr('id', this.roughId) - .attr( - 'transform', - 'translate(' + this.margin.left + ',' + this.margin.top + ')' - ); - } - - resolveFont() { - if ( - this.font === 0 || - this.font === undefined || - this.font.toString().toLowerCase() === 'gaegu' - ) { - addFontGaegu(this.svg); - this.fontFamily = 'gaeguregular'; - } else if ( - this.font === 1 || - this.font.toString().toLowerCase() === 'indie flower' - ) { - addFontIndieFlower(this.svg); - this.fontFamily = 'indie_flowerregular'; - } else { - this.fontFamily = this.font; - } + if (opts.title !== 'undefined') this.setTitle(opts.title, { fontSizeFactor: 5 }); } // Helper Method to get the Total Value of the Stack @@ -108,44 +56,6 @@ class StackedBar { return d; } - // add this to abstract base - resolveData(data) { - if (typeof data === 'string') { - if (data.includes('.csv')) { - return () => { - csv(data).then(d => { - this.getTotal(d); - this.data = d; - this.drawFromFile(); - }); - }; - } else if (data.includes('.tsv')) { - return () => { - tsv(data).then(d => { - this.getTotal(d); - this.data = d; - this.drawFromFile(); - }); - }; - } - } else { - return () => { - this.data = data; - for (let i = 0; i < data.length; ++i) { - let t = 0; - let keys = Object.keys(data[i]); - keys.forEach(d => { - if (d !== this.labels) { - t += data[i][d]; - data[i].total = t; - } - }); - } - this.drawFromObject(); - }; - } - } - addScales() { this.xScale = scaleBand() .rangeRound([0, this.width]) @@ -288,24 +198,6 @@ class StackedBar { }); } - setTitle(title) { - this.svg - .append('text') - .attr('x', this.width / 2) - .attr('y', 0 - this.margin.top / 2) - .attr('class', 'title') - .attr('text-anchor', 'middle') - .style( - 'font-size', - this.titleFontSize === undefined - ? `${Math.min(40, Math.min(this.width, this.height) / 5)}px` - : this.titleFontSize - ) - .style('font-family', this.fontFamily) - .style('opacity', 0.8) - .text(title); - } - addInteraction() { selectAll(this.interactionG) // .data(this.data)