ui/app/components/spark-line/component.js

127 lines
3.2 KiB
JavaScript

import Ember from 'ember';
import { formatPercent, formatMib, formatKbps } from 'ui/utils/util';
const formatters = {
value: (value) => { return value; },
percent: formatPercent,
mib: formatMib,
kbps: formatKbps
};
const DOT_SIZE = 2;
export default Ember.Component.extend({
data: null,
tagName: 'span',
classNames: ['spark-line'],
attributeBindings: ['cssSize:style','tooltip'],
width: null,
height: 20,
min: 0,
max: null,
interpolation: 'step-after',
formatter: 'value',
prefix: '',
svg: null,
line: null,
dot: null,
x: null,
y: null,
init() {
window.spark = this;
this._super();
},
didInsertElement() {
this._super();
},
hasData: function() {
if ( this.get('data.length') > 0 && !this.get('svg') )
{
this.create();
}
}.observes('data.length'),
cssSize: function() {
return new Ember.Handlebars.SafeString('width: ' + this.get('width') + 'px; height: ' + this.get('height') + 'px');
}.property('width','height'),
lastValue: function() {
var data = this.get('data');
if ( data && data.get('length') )
{
return data.objectAt(data.get('length')-1);
}
}.property('data.[]'),
tooltip: function() {
return (this.get('prefix')||'') + formatters[this.get('formatter')](this.get('lastValue'));
}.property('prefix','lastValue','formatter'),
create() {
var svg = d3.select(this.$()[0])
.append('svg:svg')
.attr('width','100%')
.attr('height','100%');
this.set('svg', svg);
this.set('x', d3.scale.linear());
this.set('y', d3.scale.linear());
var line = d3.svg.area()
.x((d,i) => { return this.get('x')(i); })
.y0(this.get('height'))
.y1((d) => { return this.get('y')(d); });
this.set('line', line);
this.updateLine();
svg.append('path').attr('class','spark-path').attr('d', line(this.get('data')));
svg.append('rect').attr('class','spark-dot').attr('width', DOT_SIZE).attr('height', DOT_SIZE);
},
updateLine: function() {
var line = this.get('line');
var interp = this.get('interpolation');
if ( line )
{
line.interpolate(interp);
}
}.observes('interpolation'),
update: function() {
var svg = this.get('svg');
var data = (this.get('data')||[]).slice();
var x = this.get('x');
var y = this.get('y');
var line = this.get('line');
var width = this.get('width');
var height = this.get('height');
if ( svg && data && x && y && line )
{
x.domain([0, data.get('length')-1]);
x.range([0, width-1]);
var min = this.get('min') === null ? d3.min(data) : this.get('min');
var max = this.get('max') === null ? d3.max(data) : this.get('max');
y.domain([min,max]);
y.range([height,0]);
y.rangeRound([height,0]);
//console.log('update', data[data.length-2], data[data.length-1], x.domain(), x.range(), y.domain(), y.range());
svg.selectAll('rect')
.attr('x', width-DOT_SIZE)
.attr('y', Math.max(0, Math.min(y(data[data.length-1]) - DOT_SIZE/2, height-DOT_SIZE)));
svg.selectAll('path')
.data([data])
.attr('d', line);
}
}.observes('data','data.[]'),
});