|
import Ember from 'ember'; |
|
import Chart from '../lib/chart'; |
|
import Scales from '../lib/chart-scale'; |
|
import Shapes from '../lib/chart-shapes'; |
|
|
|
const { |
|
Component, |
|
computed |
|
} = Ember; |
|
|
|
const log = console.log; |
|
|
|
export default Component.extend({ |
|
width: 400, |
|
height: 150, |
|
showXaxis: true, |
|
showYaxis: false, |
|
|
|
// Adjust margins so that the axes fit |
|
margin: {top: 5, bottom: 30, left: 30, right: 0}, |
|
|
|
graphWidth: computed('width', 'margin', function() { |
|
const width = this.get('width'); |
|
const margin = this.get('margin'); |
|
return Chart.calcGraphWidth(width, margin.left, margin.right); |
|
}), |
|
graphHeight: computed('height', 'margin', function() { |
|
const height = this.get('height'); |
|
const margin = this.get('margin'); |
|
return Chart.calcGraphWidth(height, margin.top, margin.bottom); |
|
}), |
|
|
|
xScale: computed('graphWidth', 'data', function() { |
|
const data = this.getAttr('data'); |
|
const domain = Scales.computeExtent(data, (d) => d.x); |
|
const graphWidth = this.get('graphWidth'); |
|
const range = [0, graphWidth]; |
|
return Scales.createScale(d3.scaleTime, domain, range); |
|
}), |
|
yScale: computed('graphHeight', 'data', function() { |
|
const data = this.getAttr('data'); |
|
const domain = Scales.computeExtent(data, (d) => d.y); |
|
const graphHeight = this.get('graphHeight'); |
|
const range = [graphHeight, 0]; |
|
return Scales.createScale(d3.scaleLinear, domain, range); |
|
}), |
|
|
|
xAxisTransform: computed('graphHeight', function() { |
|
const graphHeight = this.get('graphHeight'); |
|
return `translate(0,${graphHeight})`; |
|
}), |
|
|
|
lineFn: computed('xScale', 'yScale', function() { |
|
const xScale = this.get('xScale'); |
|
const yScale = this.get('yScale'); |
|
const xAccessor = (d) => xScale(d.x); |
|
const yAccessor = (d) => yScale(d.y); |
|
return Shapes.createLine(xAccessor, yAccessor, d3.curveLinear); |
|
}), |
|
|
|
didUpdateAttrs(attrs) { |
|
this._super(...arguments); |
|
|
|
const data = this.getAttr('data'); |
|
const lineFn = this.get('lineFn'); |
|
const xScale = this.get('xScale'); |
|
const yScale = this.get('yScale'); |
|
|
|
this.redrawPath(data, lineFn); |
|
if (this.get('showXaxis')) { |
|
this.redrawXaxis(xScale); |
|
} |
|
if (this.get('showYaxis')) { |
|
this.redrawYaxis(yScale); |
|
} |
|
}, |
|
|
|
didInsertElement() { |
|
this._super(...arguments); |
|
|
|
const el = this.element; |
|
const width = this.get('width'); |
|
const height = this.get('height'); |
|
const margin = this.get('margin'); |
|
const svg = Chart.baseSvg(el, width, height, margin); |
|
|
|
const lineFn = this.get('lineFn'); |
|
const xScale = this.get('xScale'); |
|
const yScale = this.get('yScale'); |
|
|
|
const data = this.getAttr('data'); |
|
const path = svg.append('path') |
|
.data(data) |
|
.attr('class', 'chart-line') |
|
.attr('d', lineFn); |
|
|
|
if (this.get('showXaxis')) { |
|
const xAxis = d3.axisBottom(xScale); |
|
const xAxisTransform = this.get('xAxisTransform'); |
|
svg.append('g') |
|
.attr('class', 'axis xAxis') |
|
.attr('transform', xAxisTransform) |
|
.call(xAxis) |
|
.selectAll('text') |
|
.attr('transform', 'rotate(-25)') |
|
.style('text-anchor', 'end'); |
|
} |
|
if (this.get('showYaxis')) { |
|
const yAxis = d3.axisLeft(yScale); |
|
svg.append('g') |
|
.attr('class', 'axis yAxis') |
|
.call(yAxis); |
|
} |
|
}, |
|
|
|
redrawPath(data, lineFn) { |
|
d3.select('.chart-line') |
|
.data(data) |
|
.transition().duration(750) |
|
.attr('d', lineFn); |
|
}, |
|
|
|
redrawXaxis(xScale) { |
|
d3.select('.xAxis') |
|
.transition().duration(750) |
|
.call(d3.axisBottom(xScale)) |
|
.selectAll('text') |
|
.attr('transform', 'rotate(-25)') |
|
.style('text-anchor', 'end'); |
|
}, |
|
|
|
redrawYaxis(yScale) { |
|
d3.select('.yAxis') |
|
.transition().duration(750) |
|
.call(d3.axisLeft(yScale)); |
|
} |
|
}); |