Created
September 5, 2016 12:10
-
-
Save jorgeyp/01999787b46460cde001e78023a6efe7 to your computer and use it in GitHub Desktop.
Proteus barchart D3 v4 minus transitions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SvgBarchartStrategy extends SvgChart { | |
constructor(chartContext) { | |
super(chartContext); | |
//Create range function | |
this.xAxisName = 'x'; | |
this.yAxisName = 'y'; | |
// this.x = d3.scale.ordinal().rangeRoundBands([0, this.width], 0.1); | |
this.x = d3.scaleBand() | |
.rangeRound([0, this.width]) | |
.padding(0.1) | |
.align(0.5); | |
// this.y = d3.scale.linear().range([this.height, 0]); | |
this.y = d3.scaleLinear().rangeRound([this.height, 0]); | |
this.isStacked = false; | |
//Create axes | |
// this.xAxis = d3.svg.axis() | |
// .scale(this.x) | |
// .orient('bottom') | |
// .ticks(10); | |
this.xAxis = d3.axisBottom(this.x) | |
.ticks(10); | |
// this.yAxis = d3.svg.axis() | |
// .scale(this.y) | |
// .orient('left') | |
// .innerTickSize(-this.width) | |
// .outerTickSize(0) | |
// .tickPadding(20) | |
// .ticks(this.ticks, this.tickLabel); | |
this.yAxis = d3.axisLeft(this.y) | |
.tickFormat(d3.format(',')) | |
.tickSizeInner(-this.width) | |
.tickSizeOuter(0) | |
.tickPadding(20) | |
.ticks(this.ticks, this.tickLabel); | |
this.keyFunction = ((d) => d.x); | |
} | |
/** | |
* Renders a barchart based on data object | |
* @param {Object} data Data Object. Contains an array with x and y properties. | |
* | |
*/ | |
draw(data) { | |
super.draw(data); | |
var c = []; | |
for (var d of data) { | |
c = c.concat(d3.keys(d).filter((k) => k !== 'key' && k !== 'total')); | |
} | |
this.categories = Array.from(new Set(c)); | |
data.forEach((d) => { | |
d.categories = this.categories.map((category) => { | |
return {category: category, value: +d[category]}; | |
}); | |
}); | |
var stack = d3.stack(); | |
this.series = stack.keys(this.categories)(data); | |
if (this.stacked) { | |
this.x.domain(data.map((d) => d.key)); | |
this.y.domain([0, d3.max(data, (d) => d.total)]).nice(); | |
var layer = this.svg.selectAll('.layer') | |
.data(this.series); | |
// .attr('class', 'layer') | |
// .attr('fill', (d, i) => this.colorScale(i)); | |
var layerEnter = layer.enter().append('g'); | |
// .attr('class', 'layer') | |
// .attr('fill', (d, i) => this.colorScale(i)); | |
var layerMerge = layer.merge(layerEnter) | |
.attr('class', 'layer') | |
.attr('fill', (d, i) => this.colorScale(i)); | |
this._bar = layerMerge.selectAll('rect') | |
.data((d) => d); | |
var barEnter = this._bar.enter().append('rect'); | |
this._barMerge = this._bar.merge(barEnter) | |
.attr("x", (d) => this.x(d.data.key)) | |
.attr("y", (d) => this.y(d[1])) | |
.attr("height", (d) => this.y(d[0]) - this.y(d[1])) | |
.attr("width", this.x.bandwidth()); | |
// this._transition2Grouped(); | |
} | |
else { // grouped | |
this.x.domain(data.map((d) => d.key)); | |
this.xGroup = d3.scaleBand() | |
.domain(this.categories) | |
.range([0, this.x.bandwidth()]); | |
this.y.domain([0, d3.max(data, (d) => d3.max(d.categories, (d) => d.value))]); | |
// //Calculate max value | |
// this.y.domain([0, d3.max(data, function(o){ | |
// var numbers = []; | |
// for (let k in o) { | |
// if (o.hasOwnProperty(k) && k !== 'total' && k !== 'key') { | |
// numbers.push(o[k]); | |
// } | |
// } | |
// return d3.max(numbers); | |
// })]).nice(); | |
var group = this.svg.selectAll('.group') | |
.data(data); | |
var groupEnter = group.enter().append('g') | |
.attr('transform', (d) => 'translate(' + this.x(d.key) + ')'); | |
var groupMerge = group.merge(groupEnter) | |
.attr('class', 'group') | |
.attr('transform', (d) => 'translate(' + this.x(d.key) + ')'); | |
this._bar = groupMerge.selectAll('rect') | |
.data((d) => d.categories); | |
var barEnter = this._bar.enter().append('rect'); | |
this._barMerge = this._bar.merge(barEnter) | |
.attr('width', this.xGroup.bandwidth()) | |
.attr("x", (d) => this.xGroup(d.category)) | |
.attr('fill', (d, i) => this.colorScale(i)) | |
.attr("y", (d) => this.y(d.value)) | |
.attr("height", (d) => this.height - this.y(d.value)); | |
} | |
this._updateAxis(); | |
this._applyCSS(); | |
} | |
_transition2Stacked() { | |
// var yStackMax = d3.max(this.layers, (layer) => d3.max(layer, (d) => d.y0 + d.y)); | |
// | |
// console.log('yStackMax', yStackMax); | |
// var n = this.layers.length; | |
// | |
// this.y.domain([0, yStackMax]); | |
// | |
// this._bars.transition() | |
// .duration(200) | |
// .attr('y', (d) => this.y(d.y0 + d.y)) | |
// .attr('height', (d) => this.y(d.y0) - this.y(d.y0 + d.y)) | |
// .transition() | |
// .attr('x', (d) => this.x(d.x)) | |
// .attr('width', this.x.rangeBand()) | |
// .call(this._endAllTransitions, () => this._barTransitionEnd(this._bars)); | |
this._updateYaxis(); | |
this._applyCSS(); | |
} | |
_transition2Grouped() { | |
// TODO | |
// this._updateYaxis(); | |
// this._applyCSS(); | |
} | |
/** | |
* This function is fired when all transitions ends. | |
* To avoid errors, this function add d3 listener (instead of adding before transitions ends). | |
*/ | |
_barTransitionEnd(bars) { | |
bars.on('mousedown.user', this.events.down) | |
.on('mouseup.user', this.events.up) | |
.on('mouseleave.user', this.events.leave) | |
.on('mouseover.user', this.events.over) | |
.on('click.user', this.events.click); | |
// Add tooltips to the bars | |
if (this.tooltip) { | |
bars.on('mouseover.tip', this.tooltip.show) | |
.on('mouseout.tip', this.tooltip.hide); | |
} | |
} | |
_initialize() { | |
var transition = null; | |
super._initialize(); | |
//Initialize SVG | |
this._initialized = true; | |
} | |
/** | |
* This method adds config options to the chart context. | |
* @param {Object} config Config object | |
*/ | |
_loadConfigOnContext(config) { | |
config = config || { events: {} }; | |
if (!config.events) { | |
config.events = {}; | |
} | |
super._loadConfigOnContext(config); | |
this.stacked = typeof (config.stacked) === 'undefined' ? _default[this.constructor.name].stacked : config.stacked; | |
//Just for testing purposes | |
return this; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment