Skip to content

cr2007/F20DV-Lab3

Repository files navigation

F20DV Lab 3

← Lab 2 Lab 3 Lab 4 →

Open in GitHub Codespaces

Interactions

  • Name: Chandrashekhar Ramaprasad (cr2007)
  • Course: Data Visualization and Analytics (F20DV)

Progress

100%


Tutorial 9: D3 Selection and Events

Lab 3 - Tutorial 9

Exercise: Highlight and Tooltips

In this exercise, we added two simple interactions with our bar charts for basic interaction with the charts.

Firstly, we implemented a way to highlight the Bar Charts when the mouse cursor was hovered over the bars.

Secondly, we added a simple tooltip text that is displayed to show additional information about the bars when the cursor is hovered over the bars.

Code

<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> <script>hljs.highlightAll();</script>
barChart.js
export default class BarChart {

// ...

#updateBars() {
    this.bars = this.bars
        .data(this.data, (d) => d[0])
        // ...
        .on("mouseover", (event, datum) => {
        // Highlight the bar on cursor hover
            d3.select(event.target)
            .classed("highlighted", true)
        })
        .on("mouseout", (event, datum) => {
            // Remove the highlight on cursor out
            d3.select(event.target)
            .classed("highlighted", false)
        });

    // Add tooltips
    // Adds a title element to all bars
    this.bars.selectAll("title")
        .data(d => [d])
        .join("title")
        .text(d => `${d[0]}: ${d[1]}`);
}

// ...

}


Tutorial 10: Linked Interactions

Lab 3 - Tutorial 10

Exercise: Linked Selection and Filters

Code

main.js
"use strict";

import BarChart from './visualizations/barChart_tut10.js';

/***** Exercise: Linked Selection and Filters *****/ let data = await d3.csv("data/movies_mock.csv", d => { return { year: +d.release_year, revenues: parseFloat(d.revenues), genre: d.genre } });

let bar1 = new BarChart("#bar1", 800, 400, [10, 40, 65, 10]), bar2 = new BarChart("#bar2", 800, 400, [10, 40, 65, 10]), bar3 = new BarChart("#bar3", 800, 400, [10, 40, 65, 10]);

let sortYears = (a, b) => a[0] - b[0]; let yearRevenues = d3.flatRollup(data, v => d3.sum(v, d => d.revenues), d => d.year).sort(sortYears), yearCount = d3.flatRollup(data, v => v.length, d => d.year).sort(sortYears), genreCount = d3.flatRollup(data, v => v.length, d => d.genre);

bar1.setLabels("Year", "Total Revenues") .render(yearRevenues); bar2.setLabels("Year", "Total Number of Releases") .render(yearCount); bar3.setLabels("Genre", "Total Number of Releases") .render(genreCount);

let highlightYear = (e, d) => { let year = d[0]; bar1.highlightBars([year]); bar2.highlightBars([year]); }

let rmvHighlightYear = (e, d) => { bar1.highlightBars(); bar2.highlightBars(); }

bar1.setBarHover(highlightYear).setBarOut(rmvHighlightYear); bar2.setBarHover(highlightYear).setBarOut(rmvHighlightYear);

let filterGenre = (e, d) => { let genre = d[0]; let filteredData = data.filter(d => d.genre === genre), yearRevenuesFiltered = d3.flatRollup(filteredData, v => d3.sum(v, d => d.revenues), d => d.year).sort(sortYears), yearCountFiltered = d3.flatRollup(filteredData, v => v.length, d => d.year).sort(sortYears);

bar1.setLabels("Year", `Revenues: ${genre}`)
    .render(yearRevenuesFiltered);
bar2.setLabels("Year", `Number of Releases: ${genre}`)
    .render(yearCountFiltered);

}

bar3.setBarClick(filterGenre);

barChart.js
export default class BarChart {
    // Attributes
// ...

// Add Object attributes for storing callback references
barClick = () => {};
barHover = () => {};
barOut   = () => {};

// ...

#updateBars() {
    this.bars = this.bars
        // ...

    // ...

    this.#updateEvents();

    // ...
}

#updateEvents() {
    // Rebind these callbacks to events
    this.bars
        .on("mouseover", this.barHover)
        .on("mouseout", this.barOut)
        .on("click", (e, d) => {
            console.log(`Bar Clicked: ${d}`);
            this.barClick(e, d);
        });
}

// ...

setBarClick(f = () => {}) {
    // Register new callback
    this.barClick = f;

    // Rebind callback to event
    this.#updateEvents();

    // Return this for chaining
    return this;
}

setBarHover(f = () => {}) {
    // Register new callback
    this.barHover = f;

    // Rebind callback to event
    this.#updateEvents();

    // Return this for chaining
    return this;
}

setBarOut(f = () => {}) {
    // Register new callback
    this.barOut = f;

    // Rebind callback to event
    this.#updateEvents();

    // Return this for chaining
    return this;
}

highlightBars(keys = []) {
    // Reset Highlight for all bars
    this.bars.classed("highlighted", false);

    // Filter bars and set new highlights
    this.bars.filter(d => keys.includes(d[0]))
        .classed("highlighted", true);

    return this; // to allow chaining
}

}


Tutorial 11: D3 Transitions

Lab 3 - Tutorial 11

Exercise: Let's Make an Animated Bar Chart

Adds an animated element for the bar chart using D3 Transitions.

There is a visual feedback when bar3 is clicked, showing an animation in bar1 and bar2.

Code

barChart.js
export default class BarChart {
    // ...
#updateBars() {
    // Bind and join rectangles to data
    this.bars = this.bars
    .data(this.data, (d) => d[0])
    .join(
        // Initial placement of new rectangles
        enter => enter.append("rect")
                .attr("x", (d) => this.scaleX(d[0]))
                .attr("y", (d) => this.scaleY(0)) // Aligned at Bottom
                .attr("width", this.scaleX.bandwidth())
                .attr("height", 0), // No height
        // Leave existing rectangles untouched
        update => update,
        exit => exit.transition().duration(300)
                .attr("y", d => this.scaleY(0)) // Aligned at bottom
                .attr("height", 0) // No Height
                .remove() // Destroy rectangle when finished
    )
    .classed("bar", true);

    // Animate Placement and sizing (enter + update only)
    this.bars.transition().duration(500)
        .attr("x", (d) => this.scaleX(d[0]))
        .attr("y", (d) => this.scaleY(d[1]))
        .attr("width", this.scaleX.bandwidth())
        .attr("height", (d) => this.scaleY(0) - this.scaleY(d[1]));
}

}


Tutorial 12: Advanced Behaviours

Lab 3 - Tutorial 12

Exercise: D3 Behaviours Sandbox

Code

main.js