block by mmazanec22 321d578efac8a1372eb1a04f2067b56a

Updating Bar Graph

Full Screen

index.html

<!DOCTYPE html>
<html>
<head>

    <script src="https://d3js.org/d3.v3.min.js"></script>
    <script type="text/javascript" src='./updateHistogram.js'></script>
    <link rel="stylesheet" type="text/css" href="./styles.css">
  
</head>
<body>
    <div class='parent-div'></div>
</body>
</html>

styles.css

html, body {
    height: 100%;
    width: 100%;
    overflow: hidden;
}

.parent-div {
    height: 100%;
    width: 100%;
}

.bar {
    fill-opacity: 0.2;
    stroke: white;
    fill: dodgerblue;
}

.axis .domain {
    stroke: none;
    fill: none;
}

.axis text {
    fill: dodgerblue;
    font-size: 0.6rem;
    letter-spacing: 0.05rem;
    fill-opacity: 0.8;
}

.axis line {
    stroke: dodgerblue;
}

updateHistogram.js

document.addEventListener("DOMContentLoaded", function() {
    const parentDiv = d3.select('.parent-div');
    const example = new Histogram(parentDiv);
    setInterval(function() {
        example.update()
    }, 2000)
});

class Histogram {

    constructor(parentDiv) {
        this.parentDiv = parentDiv;
        this.width = 900
        this.height = 500
        this.verticalMargins = 40
        this.horizontalMargins = 20
        this.originalTimeDomain = [new Date(1980, 1), new Date(2017, 1)]
        this.graphWidth = this.width - this.horizontalMargins * 2
        this.graphHeight = this.height - this.verticalMargins * 2
        this.histX = d3.scale.linear()
            .domain(this.originalTimeDomain)
            .range([0, this.graphWidth]);
        this.histLayout = d3.layout.histogram()
            .bins(this.histX.ticks(this.graphWidth / 10))
            
        this.draw()
    }

    draw() {
        const svg = this.parentDiv.append('svg')
            .attr('position', 'absolute')
            .attr('preserveAspectRatio', 'xMinYMin meet')
            .attr('width', this.width)
            .attr('height', this.height)

        let dataToUse = this.makeData();

        const xData = this.histLayout(dataToUse);

        const yMax = d3.max(xData, d => d.length);

        const y = d3.scale.linear()
            .domain([0, yMax])
            .range([this.graphHeight, 0]);

        const xAxis = d3.svg.axis()
            .scale(this.histX)
            .orient('top')
            .tickFormat(d => new Date(d).getYear());

        const barGroup = svg.append('g')
            .attr('class', 'bar-group')

        const bars = barGroup.selectAll('.bar')
            .data(xData);

        bars.exit()
            .transition()
            .duration(750)
            .attr('height', 0);

        const barWidth = this.graphWidth / xData.length

        bars.enter().append('rect')
            .attr('class', 'bar')
            .attr('y', 0.1)
            .attr('height', 0)
            .attr('width', barWidth)
            .attr('transform', d => `translate(${this.histX(d.x) + this.horizontalMargins}, ${this.verticalMargins})`)

        bars.transition()
            .duration(750)
            .attr('height', d => this.graphHeight - y(d.length));

        const xAxisElements = svg.append('g')
            .attr('class', 'x axis')
            .attr('transform', `translate(${this.horizontalMargins} ${this.verticalMargins})`)
            .call(xAxis);

        xAxisElements.selectAll('path, line')
            .style('shape-rendering', 'crispEdges');
    }

    update() {
        const self = this;
        let dataToUse = self.makeData();

        const newXData = self.histLayout(dataToUse);

        // Max height should be large enough to see the buckets where there is only one;
        // but small enough that it looks like bars have changed when they have
        const yMax = Math.max(d3.max(newXData, d => d.length), 16 / 2);

        const y = d3.scale.linear()
            .domain([0, yMax])
            .range([self.graphHeight, 0]);

        const bars = d3.selectAll('.bar')
            .data(newXData);

        bars.exit().attr('height', 0);

        bars.transition()
            .duration(750)
            .attr('height', d => self.graphHeight - y(d.length));

    }

    makeData(length = 500) {
        return new Array(500).fill({}).map(function() {
            const year = Math.random() * (2017 - 1980) + 1980;
            const month = Math.random() * (12 - 1) + 1;
            const day = Math.random() * (30 - 1) + 1;
            const hours = Math.random() * 23;
            const minutes = Math.random() * 59 + 1;
            return new Date(year, month, day, hours, minutes);
        }).sort((a, b) => a - b)

    }
}