Built with blockbuilder.org
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> | |
| <style> | |
| .axis .domain, | |
| .axis line { | |
| stroke: black; | |
| fill: none; | |
| stroke-width: 1; | |
| } | |
| .axis text { | |
| fill: black; | |
| } | |
| .panel { | |
| fill: white; | |
| } | |
| svg { | |
| border: 1px solid silver; | |
| } | |
| .line { | |
| stroke: skyblue; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="chart-container"></div> | |
| <script> | |
| // Utilities | |
| ////////////////////////////////////////// | |
| var piper = {}; | |
| piper.utils = { | |
| pipeline: function(){ | |
| var fns = arguments; | |
| var that = this; | |
| return function(config) { | |
| for (var i = 0; i < fns.length; i++) { | |
| console.log(i, 'before', config); | |
| var cache = fns[i].call(this, config); | |
| config = that.mergeAll(config, cache); | |
| console.log(i, 'after', config); | |
| } | |
| }; | |
| }, | |
| override: function(_objA, _objB){ for(var x in _objB){ if(x in _objA){ _objA[x] = _objB[x]; } } }, | |
| merge: function(obj1, obj2) { | |
| for (var p in obj2) { | |
| if (obj2[p] && obj2[p].constructor == Object ) { | |
| if (obj1[p]) { | |
| this.merge(obj1[p], obj2[p]); | |
| continue; | |
| } | |
| } | |
| obj1[p] = obj2[p]; | |
| } | |
| }, | |
| mergeAll: function(){ | |
| var newObj = {}; | |
| var objs = arguments; | |
| for(var i = 0; i < objs.length; i++){ | |
| this.merge(newObj, objs[i]); | |
| } | |
| return newObj; | |
| } | |
| }; | |
| // Modules | |
| ////////////////////////////////////////// | |
| var data = function(_config){ | |
| var config = { | |
| data: null | |
| }; | |
| piper.utils.override(config, _config); | |
| var dataConverted = config.data.map(function(d, i){ return {x: i, y: d}; }); | |
| return { | |
| dataConverted: dataConverted | |
| }; | |
| }; | |
| var scaleX = function(_config){ | |
| var config = { | |
| dataConverted: null, | |
| margin: null, | |
| width: null | |
| }; | |
| piper.utils.override(config, _config); | |
| var chartWidth = config.width - config.margin.left - config.margin.right; | |
| var dataX = config.dataConverted.map(function(d){ return d.x; }); | |
| var scaleX = d3.scale.linear() | |
| .domain(d3.extent(dataX)) | |
| .range([0, chartWidth]); | |
| return { | |
| scaleX: scaleX | |
| }; | |
| }; | |
| var scaleY = function(_config){ | |
| var config = { | |
| dataConverted: null, | |
| margin: null, | |
| height: null | |
| }; | |
| piper.utils.override(config, _config); | |
| var chartHeight = config.height - config.margin.top - config.margin.bottom; | |
| var dataY = config.dataConverted.map(function(d){ return d.y; }); | |
| var scaleY = d3.scale.linear() | |
| .domain(d3.extent(dataY)) | |
| .range([0, chartHeight]); | |
| return { | |
| scaleY: scaleY | |
| }; | |
| }; | |
| var axisX = function(_config){ | |
| var config = { | |
| scaleX: null | |
| }; | |
| piper.utils.override(config, _config); | |
| var axisX = d3.svg.axis().scale(config.scaleX) | |
| .orient('bottom') | |
| .ticks(10); | |
| return { | |
| axisX: axisX | |
| }; | |
| }; | |
| var axisY = function(_config){ | |
| var config = { | |
| scaleY: null | |
| }; | |
| piper.utils.override(config, _config); | |
| var axisY = d3.svg.axis().scale(config.scaleY) | |
| .orient('left') | |
| .ticks(6); | |
| return { | |
| axisY: axisY | |
| }; | |
| }; | |
| var panelComponent = function(_config){ | |
| var config = { | |
| container: null, | |
| width: null, | |
| height: null, | |
| margin: null | |
| }; | |
| piper.utils.override(config, _config); | |
| var root = d3.select(config.container) | |
| .append('svg') | |
| .attr({ | |
| 'class': 'chart', | |
| width: config.width, | |
| height: config.height | |
| }); | |
| var panel = root.append('g') | |
| .attr({ | |
| 'class': 'panel', | |
| transform: 'translate(' + config.margin.left + ',' + config.margin.top + ')' | |
| }); | |
| return { | |
| root: root, | |
| panel: panel | |
| }; | |
| }; | |
| var axisComponentX = function(_config){ | |
| var config = { | |
| axisX: null, | |
| height: null, | |
| panel: null, | |
| margin: null | |
| }; | |
| piper.utils.override(config, _config); | |
| config.panel.append('g') | |
| .attr({ | |
| 'class': 'x axis', | |
| transform: 'translate(' + [0, config.height - config.margin.top - config.margin.bottom] + ')' | |
| }) | |
| .call(config.axisX); | |
| return {}; | |
| }; | |
| var axisComponentY = function(_config){ | |
| var config = { | |
| axisY: null, | |
| panel: null | |
| }; | |
| piper.utils.override(config, _config); | |
| config.panel.append('g') | |
| .attr({'class': 'y axis'}) | |
| .call(config.axisY); | |
| return {}; | |
| }; | |
| var shapes = function(_config){ | |
| var config = { | |
| panel: null, | |
| dataConverted: null, | |
| scaleX: null, | |
| scaleY: null | |
| }; | |
| piper.utils.override(config, _config); | |
| var line = d3.svg.line() | |
| .x(function(d){ return config.scaleX(d.x); }) | |
| .y(function(d){ return config.scaleY(d.y); }); | |
| config.panel.datum(config.dataConverted) | |
| .append('path') | |
| .attr({ | |
| 'class': 'line', | |
| d: line | |
| }); | |
| return {}; | |
| }; | |
| // Pipeline | |
| ////////////////////////////////////////// | |
| var lineChart = piper.utils.pipeline( | |
| data, | |
| scaleX, | |
| scaleY, | |
| axisX, | |
| axisY, | |
| panelComponent, | |
| axisComponentX, | |
| axisComponentY, | |
| shapes | |
| ); | |
| // Usage | |
| ////////////////////////////////////////// | |
| var dataset = d3.range(100).map(function(d, i){ return Math.random()*100; }); | |
| var config = { | |
| container: document.querySelector('.chart-container'), | |
| data: dataset, | |
| width: 400, | |
| height: 300, | |
| margin: {top: 20, right: 20, bottom: 40, left: 40} | |
| }; | |
| lineChart(config); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment