Skip to content

Instantly share code, notes, and snippets.

@GerardoLSJ
Created November 23, 2017 18:24
Show Gist options
  • Select an option

  • Save GerardoLSJ/d67c21535e681e382dc2ad28c1c19c5d to your computer and use it in GitHub Desktop.

Select an option

Save GerardoLSJ/d67c21535e681e382dc2ad28c1c19c5d to your computer and use it in GitHub Desktop.
Create a reusable chart component with Angular and D3.js RESPONSIVE TO WINDOW CHANGES
// ORIGINAL POST AND CREDITS:
// https://keathmilligan.net/create-a-reusable-chart-component-with-angular-and-d3-js/
// I just added a few changes to make it responsive
import { Component, OnInit, OnChanges, ViewChild, ElementRef, Input, ViewEncapsulation } from '@angular/core';
import * as d3 from 'd3';
@Component({
selector: 'app-bar-chart',
templateUrl: './bar-chart.component.html',
styleUrls: ['./bar-chart.component.scss'],
encapsulation: ViewEncapsulation.None,
host: {
'(window:resize)': 'onResize($event)'
}
})
export class BarChartComponent implements OnInit, OnChanges {
@ViewChild('chart') private chartContainer: ElementRef;
@Input() private data: Array<any>;
private margin: any = { top: 20, bottom: 20, left: 20, right: 20};
private chart: any;
private width: number;
private height: number;
private xScale: any;
private yScale: any;
private colors: any;
private xAxis: any;
private yAxis: any;
private d3Element: any;
private d3Svg: any;
constructor() { }
onResize(event){
event.target.innerWidth; // window width
console.log(event.target.innerWidth)
this.createChart()
}
ngOnInit() {
this.d3Element = this.chartContainer.nativeElement;
this.d3Svg = d3.select( this.d3Element).append('svg')
this.chart = this.d3Svg.append('g')
this.xAxis = this.d3Svg.append('g')
this.yAxis = this.d3Svg.append('g')
this.createChart();
if (this.data) {
this.updateChart();
}
}
ngOnChanges() {
if (this.chart) {
this.updateChart();
}
}
createChart() {
var element = this.d3Element
this.width = element.offsetWidth - this.margin.left - this.margin.right;
this.height = element.offsetHeight - this.margin.top - this.margin.bottom;
this.d3Svg
.attr('width', element.offsetWidth)
.attr('height', element.offsetHeight);
// chart plot area
this.chart
.attr('class', 'bars')
.attr('transform', `translate(${this.margin.left}, ${this.margin.top})`);
/* define X & Y domains*/
const xDomain = this.data.map(d => d[0]);
const yDomain = [0, d3.max(this.data, d => d[1])];
// create scales
this.xScale = d3.scaleBand().padding(0.1).domain(xDomain).rangeRound([0, this.width]);
this.yScale = d3.scaleLinear().domain(yDomain).range([this.height, 0]);
// bar colors
this.colors = d3.scaleLinear().domain([0, this.data.length]).range(<any[]>['red', 'blue']);
// x & y axis
this.xAxis
.attr('class', 'axis axis-x')
.attr('transform', `translate(${this.margin.left}, ${this.margin.top + this.height})`)
.call(d3.axisBottom(this.xScale));
this.yAxis
.attr('class', 'axis axis-y')
.attr('transform', `translate(${this.margin.left}, ${this.margin.top})`)
.call(d3.axisLeft(this.yScale));
this.updateChart()
}
updateChart() {
// update scales & axis
this.xScale.domain(this.data.map(d => d[0]));
this.yScale.domain([0, d3.max(this.data, d => d[1])]);
this.colors.domain([0, this.data.length]);
this.xAxis.transition().call(d3.axisBottom(this.xScale));
this.yAxis.transition().call(d3.axisLeft(this.yScale));
const update = this.chart.selectAll('.bar')
.data(this.data);
// remove exiting bars
update.exit().remove();
// update existing bars
this.chart.selectAll('.bar').transition()
.attr('x', d => this.xScale(d[0]))
.attr('y', d => this.yScale(d[1]))
.attr('width', d => this.xScale.bandwidth())
.attr('height', d => this.height - this.yScale(d[1]))
.style('fill', (d, i) => this.colors(i));
// add new bars
update
.enter()
.append('rect')
.attr('class', 'bar')
.attr('x', d => this.xScale(d[0]))
.attr('y', d => this.yScale(0))
.attr('width', this.xScale.bandwidth())
.attr('height', 0)
.style('fill', (d, i) => this.colors(i))
.transition()
.delay((d, i) => i * 10)
.attr('y', d => this.yScale(d[1]))
.attr('height', d => this.height - this.yScale(d[1]));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment