├── .gitignore ├── History.md ├── Makefile ├── Readme.md ├── examples └── simple.js ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 1.3.3 / 2016-10-06 2 | ================== 3 | 4 | * Fix Incorrect dates in history 5 | 6 | 1.3.2 / 2016-10-06 7 | ================== 8 | 9 | * Fix size calculation 10 | 11 | 1.3.1 / 2016-09-09 12 | ================== 13 | 14 | * allow 0 padding 15 | 16 | 1.3.0 / 2016-09-09 17 | ================== 18 | 19 | * add option to set axis character 20 | * change default axis character to '.' 21 | 22 | 23 | 1.2.0 / 2016-09-05 24 | ================== 25 | 26 | * add options to set point characters 27 | * update docs 28 | * update repo link 29 | 30 | 1.1.1 / 2014-03-25 31 | ================== 32 | 33 | * rename 34 | 35 | 1.1.0 / 2014-02-27 36 | ================== 37 | 38 | * add excess head clipping for rolling data 39 | 40 | 1.0.1 / 2014-02-27 41 | ================== 42 | 43 | * bump array-matrix to try and get npm to work 44 | 45 | 1.2.0 / 2014-02-26 46 | ================== 47 | 48 | * add value mapping support 49 | 50 | 1.1.0 / 2014-02-26 51 | ================== 52 | 53 | * change to make .sort an option 54 | * docs 55 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | test: 3 | @./node_modules/.bin/mocha \ 4 | --require should \ 5 | --reporter dot \ 6 | --bail 7 | 8 | .PHONY: test -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 2 | # Chart 3 | 4 | Ascii bar chart for nodejs. 5 | 6 | ![](https://dl.dropboxusercontent.com/u/6396913/misc/Screen%20Shot%202014-02-27%20at%208.56.42%20AM.png) 7 | 8 | ## Installation 9 | 10 | ``` 11 | $ npm install jstrace/chart 12 | ``` 13 | 14 | ## Example 15 | 16 | When `data` exceeds the available width the data will "roll" to the tail-end 17 | of the array. This may become an option in the future, but that's the default 18 | behaviour for now ;) 19 | 20 | ```js 21 | var chart = require('chart'); 22 | var clear = require('clear'); 23 | 24 | var data = [1, 2, ...]; 25 | 26 | clear(); 27 | console.log(chart(data, { 28 | width: 130, 29 | height: 30, 30 | pointChar: '█', 31 | negativePointChar: '░' 32 | })); 33 | ``` 34 | 35 | # License 36 | 37 | MIT 38 | -------------------------------------------------------------------------------- /examples/simple.js: -------------------------------------------------------------------------------- 1 | 2 | var chart = require('..'); 3 | var clear = require('clear'); 4 | 5 | var data = [ 6 | 1, 7 | 5, 8 | 5, 9 | 13, 10 | 3, 11 | 2, 12 | 0, 13 | 2, 14 | 34, 15 | 22, 16 | 15, 17 | 12, 18 | 8, 19 | 4, 20 | 3, 21 | 6, 22 | 18, 23 | -5, 24 | -15, 25 | -11, 26 | -23, 27 | -3, 28 | 10, 29 | 18, 30 | 23, 31 | 17, 32 | 4, 33 | 5, 34 | 6, 35 | 3, 36 | 12, 37 | 10, 38 | 7, 39 | -4, 40 | 17, 41 | 30, 42 | 27, 43 | 25, 44 | 23, 45 | 16, 46 | 14, 47 | 12, 48 | 8, 49 | 6, 50 | 4, 51 | 2 52 | ]; 53 | 54 | clear(); 55 | console.log(chart(data)); 56 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var matrix = require('array-matrix'); 7 | 8 | /** 9 | * Expose `chart()`. 10 | */ 11 | 12 | module.exports = chart; 13 | 14 | /** 15 | * Return ascii chart of `data`. 16 | * 17 | * - `width` total chart width [130] 18 | * - `height` total chart height [30] 19 | * - `padding` edge padding [3] 20 | * - `pointChar` character used to plot a point [█] 21 | * - `negativePointChar` character used to plot a negative point [░] 22 | * - `axisChar` character used to draw axis [.] 23 | * 24 | * @param {Array} data 25 | * @param {Object} [opts] 26 | * @return {String} 27 | * @api public 28 | */ 29 | 30 | function chart(data, opts) { 31 | opts = opts || {}; 32 | 33 | // options 34 | var w = opts.width || 130; 35 | var h = opts.height || 30; 36 | var pc = opts.pointChar || '█'; 37 | var nc = opts.negativePointChar || '░'; 38 | var ac = opts.axisChar || '.'; 39 | 40 | // padding 41 | var pad = typeof opts.padding === 'number' ? opts.padding : 3; 42 | w -= pad * 2; 43 | h -= pad * 2; 44 | 45 | // setup 46 | var out = matrix(w, h); 47 | var m = max(data) || 0; 48 | var label = Math.abs(m).toString(); 49 | var labelw = label.length; 50 | var labelp = 1; 51 | 52 | // chart sizes void of padding etc 53 | var ch = h; 54 | var cw = w - labelw - labelp; 55 | 56 | // fill 57 | for (var y = 0; y < h; y++) { 58 | for (var x = 0; x < w; x++) { 59 | out[y][x] = ' '; 60 | } 61 | } 62 | 63 | // y-axis labels 64 | for (var i = 0; i < labelw; i++) { 65 | out[0][i] = label[i]; 66 | } 67 | 68 | out[h - 1][labelw - labelp] = '0'; 69 | 70 | // y-axis 71 | for (var y = 0; y < h; y++) { 72 | out[y][labelw + labelp] = ac; 73 | } 74 | 75 | // x-axis 76 | var x = labelw + labelp; 77 | while (x < w) { 78 | out[h - 1][x++] = ac; 79 | out[h - 1][x++] = ' '; 80 | } 81 | 82 | // strip excess from head 83 | // so that data may "roll" 84 | var space = Math.floor(w / 2) - 1; 85 | var excess = Math.max(0, data.length - space); 86 | if (excess) data = data.slice(excess); 87 | 88 | // plot data 89 | var x = labelw + labelp + 2; 90 | for (var i = 0; i < data.length; i++) { 91 | var d = data[i]; 92 | var p = d / m; 93 | var y = Math.round((h - 2) * p); 94 | var c = y < 0 ? nc : pc; 95 | if (y < 0) y = -y; 96 | 97 | while (y--) { 98 | out[Math.abs(y - h) - 2][x] = c; 99 | } 100 | 101 | x += 2; 102 | } 103 | 104 | // Return string 105 | var str = string(out, h); 106 | return pad ? padding(str, pad) : str; 107 | } 108 | 109 | /** 110 | * Apply padding. 111 | */ 112 | 113 | function padding(str, n) { 114 | var linew = str.split('\n')[0].length; 115 | var line = Array(linew).join(' ') + '\n'; 116 | 117 | // y 118 | str = Array(n).join(line) + str; 119 | str = str + Array(n).join(line); 120 | 121 | // x 122 | str = str.replace(/^/gm, Array(n).join(' ')); 123 | return str; 124 | } 125 | 126 | /** 127 | * Convert matrix to a string. 128 | */ 129 | 130 | function string(out) { 131 | var buf = []; 132 | 133 | for (var i = 0; i < out.length; i++) { 134 | buf.push(out[i].join('')); 135 | } 136 | 137 | return buf.join('\n'); 138 | } 139 | 140 | /** 141 | * Return max in array. 142 | */ 143 | 144 | function max(data) { 145 | var n = Math.abs(data[0]); 146 | 147 | for (var i = 1; i < data.length; i++) { 148 | n = Math.abs(data[i]) > n ? Math.abs(data[i]) : n; 149 | } 150 | 151 | return n; 152 | } 153 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chart", 3 | "version": "1.3.3", 4 | "repository": "jstrace/chart", 5 | "description": "Ascii bar chart", 6 | "keywords": [ 7 | "ascii", 8 | "chart", 9 | "bar", 10 | "stats", 11 | "data", 12 | "cli", 13 | "terminal" 14 | ], 15 | "dependencies": { 16 | "array-matrix": "1.0.0" 17 | }, 18 | "devDependencies": { 19 | "mocha": "*", 20 | "should": "*", 21 | "bytes": "~0.2.1", 22 | "clear": "0.0.1" 23 | }, 24 | "license": "MIT" 25 | } 26 | --------------------------------------------------------------------------------