UNPKG

blessed-contrib

Version:

Build dashboards (or any other application) using ascii/ansi art and javascript.

150 lines (125 loc) 4.18 kB
'use strict'; var blessed = require('blessed') , Node = blessed.Node , Canvas = require('./canvas'); function Donut(options) { if (!(this instanceof Node)) { return new Donut(options); } options = options || {}; this.options = options; this.options.stroke = options.stroke || 'magenta'; this.options.fill = options.fill || 'white'; this.options.radius = options.radius || 14; this.options.arcWidth = options.arcWidth || 4; this.options.spacing = options.spacing || 2; this.options.yPadding = options.yPadding || 2; this.options.remainColor = options.remainColor || 'black'; this.options.data = options.data || []; Canvas.call(this, options); var self = this; this.on('attach', function() { this.setData(self.options.data); }); } Donut.prototype = Object.create(Canvas.prototype); Donut.prototype.calcSize = function() { this.canvasSize = {width: Math.round(this.width*2-5), height: this.height*4-12}; if (this.canvasSize.width % 2 == 1) this.canvasSize.width--; if (this.canvasSize.height % 4 != 1) this.canvasSize.height += (this.canvasSize.height % 4); }; Donut.prototype.type = 'donut'; var cos = Math.cos; var sin = Math.sin; var pi = 3.141592635; Donut.prototype.setData = function(data){ this.update(data); }; Donut.prototype.update = function(data) { if (!this.ctx) { throw 'error: canvas context does not exist. setData() for line charts must be called after the chart has been added to the screen via screen.append()'; } var c = this.ctx; c.save(); c.translate(0,-this.options.yPadding); c.strokeStyle = this.options.stroke; c.fillStyle = this.options.fill; c.clearRect(0, 0, this.canvasSize.width, this.canvasSize.height); var cheight = this.canvasSize.height; var cwidth = this.canvasSize.width; function makeRound(percent, radius, width, cx, cy, color){ var s = 0; var points = 370; c.strokeStyle = color || 'green'; while(s<radius){ if (s < (radius - width)) { s++; continue; } var slice = 2 * pi / points; c.beginPath(); var p = parseFloat(percent*360); for(var i = 0;i<=points;i++){ if (i>p) continue; var si = i-90; var a = slice * si; c.lineTo(Math.round(cx+s*cos(a)), Math.round(cy+s*sin(a))); } c.stroke(); c.closePath(); s++; } } var donuts = data.length; var radius = this.options.radius; var width = this.options.arcWidth; var remainColor = this.options.remainColor; var middle = cheight / 2; var spacing = (cwidth - (donuts * radius * 2)) / (donuts + 1); function drawDonut(label, percent, radius, width, cxx, middle, color, percentAltNumber){ makeRound(100, radius, width, cxx, middle, remainColor ); makeRound(percent, radius, width, cxx, middle, color); var ptext = percentAltNumber ? percentAltNumber.toFixed(0) : parseFloat(percent*100).toFixed(0) + '%'; c.fillText(ptext, cxx - Math.round(parseFloat((c.measureText(ptext).width)/2)) + 3, middle); c.fillText(label, cxx - Math.round(parseFloat((c.measureText(label).width)/2)) + 3, (middle + radius) + 5); } function makeDonut(stat, which){ var left = radius + (spacing * which) + (radius * 2 * (which - 1)); var percent = stat.percent; if (percent > 1.001){ percent = parseFloat(percent / 100).toFixed(2); } var label = stat.label; var percentAltNumber = stat.percentAltNumber; var color = stat.color || 'green'; var cxx = left; drawDonut(label, percent, radius, width, cxx, middle, color, percentAltNumber); } function makeDonuts(stats){ for(var l = 0; l<=stats.length-1;l++){ makeDonut(stats[l], l+1); } } if (data.length){ makeDonuts(data); } this.currentData = data; c.strokeStyle = 'magenta'; c.restore(); return; }; Donut.prototype.getOptionsPrototype = function() { return { spacing: 1, yPadding: 1, radius: 1, arcWidth: 1, data: [ { color: 'red', percent: '50', label: 'a'} , { color: 'blue', percent: '20', label: 'b'} , { color: 'yellow', percent: '80', label: 'c'} ] }; }; module.exports = Donut;