D3 Updating stacked bar chart
https://codereview.stackexchange.com/q/204586/120114
by samonela
HTML
<script src="https://cdn.rawgit.com/chrisvfritz/459a93673c5f2e362464125381e51515/raw/9e07d5bda30203dc788894cba18749a3bb44e79d/get-players.js"></script>
<script src="https://unpkg.com/d3"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<chart :stacked-xor-y="stacked" :tasks="tasks" :svg-width="svgWidth" :svg-height="svgHeight"></chart>
<button @click="toggleStacked">
change bars layout
</button> {{stacked}}
</div>
<script type="text/x-template" id="chart-template">
<div>
<svg ref="stacked-svg-tasks" id="stacked-svg-tasks" :width="svgWidth" :height="svgHeight"></svg>
</div>
</script>
JavaScript
Vue.component('chart', {
template: '#chart-template',
name: 'TasksStackedBarChart',
props: ['tasks', 'svgWidth', 'svgHeight', 'stackedXorY'],
data() {
return {
X_AXIS_HEIGHT: 20,
Y_AXIS_WIDTH: 50,
svgMargin: {
top: 20
},
barChartGroup: {
width: 0,
height: 0,
x: 0,
y: 0,
},
GbT: 50, // gap between tasks
stageWidth: 0,
toalStages: 0,
xPosOfTasks: [],
yScale: null,
yScaleDomainEnd: 0,
};
},
created() {
this.barChartGroup.width = this.svgWidth - this.Y_AXIS_WIDTH;
this.barChartGroup.height = this.svgHeight - this.X_AXIS_HEIGHT;
this.barChartGroup.x = this.Y_AXIS_WIDTH;
this.barChartGroup.y = this.X_AXIS_HEIGHT;
this.toalStages = this.tasks.map(v => v.taskStages.length).reduce((s, v) => s + v, 0);
this.stageWidth = this.getStageWidth();
this.xPosOfTasks = this.getXPosOfTask(this.GbT, this.tasks, this.stageWidth, this.stackedXorY);
this.yScaleDomainEnd = this.getLongestTask();
this.yScale = this.getScaleForTask(this.barChartGroup.height, this.yScaleDomainEnd);
},
mounted() {
this.chartBuilder();
},
methods: {
getScaleForTask(rangeEnd, domainEnd) {
const calcRangeEnd = rangeEnd - this.svgMargin.top - this.X_AXIS_HEIGHT;
return d3.scaleLinear()
.range([0, calcRangeEnd])
.domain([0, domainEnd]);
},
getLongestTask() {
return d3.max(this.tasks.map(t => t.taskTotalTime));
},
getStageWidth() { // will keep using this. to see if it's better to work like this or i should pass parameters
const numOfChartBars = this.stackedXorY ? this.toalStages : this.tasks.length;
return Math.floor((this.svgWidth - (this.GbT * (this.tasks.length + 1))) / numOfChartBars);
},
getPosOfStage(stage, stageIndex) {
const x = stageIndex * this.stageWidth * this.stackedXorY;
// this sets the bars at the bottom than this.yScale(s.y)...