1 of 22

Discussion 7: More D3, Mapbox

2 of 22

First: more advanced JS

3 of 22

Arrow functions

Traditional Function

Arrow Function (Concise)

Arrow Function ({} block)

  • Shorthand for writing functions in JS
    • Syntax: (inputs) => output
  • Make your code more concise, especially for inline or callback functions.
  • Implicit return - No {} needed if function is a one-liner
  • When using {} in arrow functions, must explicitly use return

4 of 22

Ternary operator

Equivalent if-else statement:

  • More compact way of writing an if-else statement

In this example:

  • If selection is true: Filter commits where isCommitSelected(selection, d) returns true.
  • If selection is undefined, null, false, etc: Return an empty array [].

5 of 22

Object expansion

  • The ... (spread operator) copies all properties from the following object into a new object
  • Allows you to easily extend or modify an existing object by adding to or overwriting existing properties

In this example:

  • Existing CSV row fields are copied first (...row)
  • Fields (line, depth, etc.) are overwritten or added, ensuring proper data types (e.g., converting strings to Number or Date).

6 of 22

Object.defineProperty()

  • Adds or modifies a property of an object with precise control over its characteristics

In this example:

  • lines property is hidden from accidental display or processing
  • Property is read-only and hidden, but still accessible when needed (ret.lines works explicitly).
  • Good for attaching metadata or internal data to objects safely

7 of 22

Native JavaScript events vs. D3.js events

8 of 22

Native JavaScript events

Native JS events: standard browser events

  • Handled by the browser's DOM API
  • Use methods like addEventListener() or inline event handlers
  • Examples:
    • mouseover
    • mouseout
    • click
    • keydown

9 of 22

Native JavaScript event examples

Event

Trigger

click

Mouse click

dblclick

Double click

mouseover

Pointer enters (bubbles)

mouseout

Pointer leaves (bubbles)

mousemove

Mouse moves

contextmenu

Right-click

keydown

Key is pressed

keyup

Key is released

focus

Element gains focus

blur

Element loses focus

input

Input or textarea value changes

10 of 22

D3.js events

Events using D3

D3-only events

Events using .on()

  • Created and managed by D3 internally
  • Triggered through D3 behaviors
  • Compatible with standard browser events (mouseover, click)
  • Adds D3-only events (drag, zoom, brush)
  • Syntax: .on('event', handler).

D3-only event examples:

  • brush → interactive selection area
  • drag → drag behavior
  • zoom → zoom and pan

11 of 22

D3.js-Only Event Examples

D3.js event examples

Feature / Behavior

Description

Typical Use Case

d3.drag

Enables dragging behavior for elements

Move nodes, bars, shapes

d3.zoom

Enables zooming and panning

Maps, scatterplots, timelines

d3.brush

Enables area brushing for selection

Select ranges on scatterplots, timelines

d3.pointer(event)

Returns pointer position relative to a container

Precise cursor tracking inside SVG/Canvas

d3.dispatch

Custom event dispatcher for components

Trigger and manage user-defined events

d3.timer

Frame-optimized custom timer (like requestAnimationFrame)

Continuous or custom animations

d3.timeout

Timer that fires once after a delay

Trigger an action after delay

d3.interval

Creates a repeating timer (like setInterval)

Loop animations, data refresh

d3.brush().filter()

Controls when brush is allowed

Disable brushing on invalid inputs

12 of 22

Grouping with D3.js

13 of 22

d3.map

  • Useful for transforming, restructuring, summarizing data
  • How it works:
    • Iterates over an array
    • Applies a function to each element
    • Returns a new array with the results
    • Does not modify the original array.
  • This example:
    • Processes a nested array of elements with the structure [commit, lines]
    • Returns an array of objects

14 of 22

d3.groups

Example result:

  • Pass in data and a function
  • Applies function to every element of the iterable. Groups together elements sharing the same output
  • Outputs a nested array of key-value pairs, where:
    • The first item is the key (the function output)
    • The second item is an array of all items sharing the same key
  • Can group by multiple keys using multiple functions

Key to group by

Key to group by

15 of 22

d3.rollup

Input (lines)

Output

Example

  • Group by one or more keys, then additionally apply an aggregation function.
  • Returns a Map object where:
    • Keys are the grouped function outputs
    • Values are the result of applying an aggregation function to the group

Aggregator applied to every group

Key to group by

Output of aggregator

Key

Aggregator comes first!

16 of 22

Comparing grouping functions

Function

Description

Returns

Use Case

d3.group

Groups data by key(s)

Map

Organize data into groups, no aggregation

d3.rollup

Groups and aggregates data by key(s)

Map

Get summary statistic per group

d3.rollups/d3.groups

Same as group and rollup, but returns array format

Array of [key, value] pairs

Easier iteration over key-value pairs

17 of 22

Mapbox GL JS

18 of 22

What is Mapbox GL?

  • 🔍 JavaScript library for rendering interactive maps in the browser using WebGL (a cross-platform API for rendering vector graphics)
  • 🎨 Supports dynamic styling of maps at runtime (change colors, layers, labels programmatically)
  • ⚡ High performance, especially with large datasets and complex styles
  • 📱 Optimized for modern browsers and touch-enabled devices
  • 🔌 Highly customizable with support for layers, data-driven styling, and custom controls

19 of 22

Creating a Map

  • container: id of html element where map will be placed
  • style: url to a preset style theme
  • center: latitude and longitude on the globe
  • Mapbox will handle the rest!

20 of 22

Map.on()

Syntax (where map is a mapboxgl.Map object):

map.on('load', async () => {

//code

});

  • We need this because the map loads asynchronously, which can take time
  • Don’t want to run code that depends on the map before the map loads in
  • Map.on() ensures that the map and its style have fully loaded before running the inner async function

21 of 22

What goes inside map.on()?

Inside:

  • Adding data sources (map.addSource())�
  • Adding layers (map.addLayer())�
  • Adding custom controls or UI tied to the map�
  • Setting specific styles, filters, or paints after the style loads
  • Any asynchronous code that depends on the map being ready

Outside:

  • Instantiating the map (new mapboxgl.Map({...}))�
  • Setting up HTML controls, UI buttons, sliders�
  • Declaring variables, global configs, or styles�
  • Functions that do not depend on the map being fully styled (e.g., input event handlers)

22 of 22

Checkoff - rollup()

What is the value of result after the following code runs?

Hint: d3.sum(v, fn) applies fn to every element of v and sums up the results.