MEMEDIA SS25
05. DATA WORKSHOP
2025-05-13Lecturer: Kim Albrecht
Summer 2025
Design Process


Data
Dieser Datensatz enthält über 80.000 Berichte über UFO-Sichtungen aus dem letzten Jahrhundert vom National UFO Reporting Center (NUFORC).
Source:
https://www.kaggle.com/datasets/NUFORC/ufo-sightings/data
Filter
Represent
Tutorial: Daten zu Grafiken codieren
Einführung
Dieses Tutorial behandelt die grundlegenden Themen, die du brauchst, um interaktive und dynamische Visualisierungen zu erstellen. Folge dem Ablauf und probiere gerne die Codebeispiele aus. Es gibt viele Wege und Stile zu programmieren. Höre also nicht nur auf mich, sondern erkunde auch andere Perspektiven und Quellen. Hier ein paar Empfehlungen zum Einstieg:
Einrichtung deiner Umgebung
Benötigte Tools: Code-Editor: Wir verwenden Visual Studio Code für diese Übung. Installiere die Erweiterung Live Server, um deinen Fortschritt einfach im Browser anzeigen zu können. Wenn du bereits deine eigene Umgebung hast: Super! Solange du einen lokalen Server hast, mit dem du arbeiten kannst, ist alles gut.
Grundlagen in HTML, CSS und JavaScript
Um Visualisierungen mit d3.js zu erstellen, ist es wichtig, mit HTML, CSS und JavaScript vertraut zu sein.
- HTML: Die Struktur deiner Visualisierung.
- CSS: Das Styling deiner Elemente (z. B. Farben, Größen).
- JavaScript: Die Logik hinter deiner Visualisierung.
Diese Präsentation erklärt die Grundkonzepte sehr gut.
HTML (Hypertext Markup Language)
HTML ist das Rückgrat von Webinhalten. Es strukturiert eine Webseite durch eine Reihe verschachtelter Elemente, die mit Tags beschrieben werden. Diese Tags sagen dem Browser, wie Inhalte dargestellt werden sollen.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Basic HTML Page</title>
</head>
<body>
<h1>Welcome to D3.js!</h1>
<p>This is a simple HTML page.</p>
</body>
</html>
Für eine Einführung in HTML empfehle ich dieses Video:
CSS (Cascading Style Sheets)
CSS wird verwendet, um HTML-Inhalte zu gestalten und visuell aufzuwerten. Es ermöglicht dir, Farben, Schriftarten, Abstände und Layouts anzuwenden, um eine ansprechende Benutzeroberfläche zu schaffen.
h1 {
color: red;
}
p {
font-size: 10px;
}
Für eine Einführung in CSS empfehle ich dieses Video:
JavaScript
JavaScript ist eine vielseitige Skriptsprache, die Interaktivität und dynamisches Verhalten auf Webseiten ermöglicht. Es kann HTML-Elemente manipulieren, auf Benutzereingaben reagieren und Daten laden.
<script>
console.log('Hello World!');
</script>
Grundlagen
HTML-Grundgerüst
Lass uns mit einem grundlegenden HTML-Gerüst starten und es Schritt für Schritt erweitern. Am Ende des Tutorials haben wir den vollständigen Code für die Visualisierung.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Data Visualization with d3.js</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
</style>
</head>
<body>
<script>
// JavaScript code will go here
</script>
</body>
</html>
Daten laden
D3 ermöglicht das Laden externer Datensätze in verschiedenen Formaten wie CSV, JSON oder TSV. Für unsere Übung verwenden wir einen Datensatz über weltweite UFO-Sichtungen mit verschiedenen Datenarten: kategorisch, numerisch, ortsbezogen und zeitlich.
Daten laden wir mit d3.tsv()
. Beispiel:
d3.tsv("ufo-sightings-1910-1990.tsv").then(function(data) {
console.log(data);
// Hier beginnt die Visualisierung...
});
Minimales Beispiel
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Data Visualization with d3.js</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<script>
const svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 500);
d3.tsv("ufo-sightings-1910-1990.tsv").then(function(data) {
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", 250)
.attr("cy", 250)
.attr("r", d => d.duration/10)
.style("fill", "none")
.style("stroke", "black");
});
</script>
</body>
</html>
Probiere, diese Datei zu verändern:
- Farbe der Kreise ändern
- Linienbreite der Kreise ändern
- Position der Kreise manipulieren
- Etwas Zufälligkeit mit
Math.random()
hinzufügen - Kannst du Kreise in Rechtecke verwandeln?
- Kannst du andere Daten laden für
d => d.duration/10
Verfeinerungen
Margins und SVG vorbereiten
Die bisherige Methode funktioniert, aber es ist hilfreich, Margins für dein SVG-Element hinzuzufügen. Anstelle von:
const svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 500);
…nutzen wir eine bessere Struktur:
// Set margins and dimensions
const margin = {top: 20, right: 20, bottom: 20, left: 20};
const width = 800 - margin.left - margin.right;
const height = 600 - margin.top - margin.bottom;
// Create SVG element
const svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate("+margin.left+","+margin.top+")");
Arbeiten mit Skalen
Eines der wichtigsten Konzepte in d3.js sind Skalen. Sie wirken harmlos, sind aber zentral. In meiner eigenen Arbeit gehören sie zu den meistgenutzten Funktionen in d3.js.
References:
Learn D3: Scales
d3-scale
Die grundlegende Idee von Skalen ist die Abbildung von Daten auf Ausgabewerte. Wenn du z. B. ein Ereignis aus 500 Jahren darstellen willst, musst du diese Zeitspanne auf den Bildschirm bringen. Dafür sind Skalen da.
Lineare Skalen
Für quantitative Daten:
// Linear scale for circle size (duration)
const sizeScale = d3.scaleLinear()
.domain([0, d3.max(data, d => +d.duration)])
.range([2, 20]);
Zeit-Skalen
Für Zeitdaten:
// Time scale for x-axis (datetime)
const xScale = d3.scaleTime()
.domain(d3.extent(data, d => new Date(d.datetime)))
.range([0, width]);
Band-Skalen
Für kategorische/ordinale Daten (Positionskodierung):
// Band scale for y-axis (shape)
const yScale = d3.scaleBand()
.domain([...new Set(data.map(d => d.shape))])
.range([0, height])
.padding(0.1);
Ordinale Skalen
Für Kategorien wie Länder:
// Color scale for country
const colorScale = d3.scaleOrdinal(d3.schemeCategory10)
.domain([...new Set(data.map(d => d.country))]);
Skalierte Visualisierungselemente hinzufügen
Now, add circles based on the dataset using the newly defined scales:
// Add circles
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", d => xScale(new Date(d.datetime)))
.attr("cy", d => yScale(d.shape))
.attr("r", d => sizeScale(+d.duration))
.attr("fill", d => colorScale(d.country));
Achsen hinzufügen
// Create x-axis (time scale)
const xAxis = d3.axisBottom(xScale);
svg.append("g")
.attr("transform", `translate(0, ${height})`)
.call(xAxis);
// Create y-axis (band scale)
const yAxis = d3.axisLeft(yScale);
svg.append("g")
.call(yAxis);
Animationen hinzufügen
.attr("r", 0)
.transition()
.duration(1000)
.attr("r", d => sizeScale(+d.duration))
Gesamter Code
Hier ist der vollständige HTML-, CSS- und JavaScript-Code, der alle Teile zusammenbringt, um die komplette Visualisierung zu erstellen:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Data Visualization with d3.js</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
</style>
</head>
<body>
<script>
// Set margins and dimensions
const margin = {top: 20, right: 30, bottom: 50, left: 80};
const width = 800 - margin.left - margin.right;
const height = 600 - margin.top - margin.bottom;
// Create SVG element
const svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate("+margin.left+","+margin.top+")");
d3.tsv("ufo-sightings-1910-1990.tsv").then(function(data) {
console.log(data);
// Linear scale for circle size (duration)
const sizeScale = d3.scaleLinear()
.domain([0, d3.max(data, d => +d.duration)])
.range([2, 20]);
// Band scale for y-axis (shape)
const yScale = d3.scaleBand()
.domain([...new Set(data.map(d => d.shape))])
.range([0, height])
.padding(0.1);
// Time scale for x-axis (datetime)
const xScale = d3.scaleTime()
.domain(d3.extent(data, d => new Date(d.datetime)))
.range([0, width]);
// Color scale for country
const colorScale = d3.scaleOrdinal(d3.schemeCategory10)
.domain([...new Set(data.map(d => d.country))]);
// Add circles based on data
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", d => xScale(new Date(d.datetime)))
.attr("cy", d => yScale(d.shape))
.attr("r", d => sizeScale(+d.duration))
.attr("fill", d => colorScale(d.country));
// Create x-axis (time scale)
const xAxis = d3.axisBottom(xScale);
svg.append("g")
.attr("transform", `translate(0, ${height})`)
.call(xAxis);
// Create y-axis (band scale)
const yAxis = d3.axisLeft(yScale);
svg.append("g")
.call(yAxis);
});
</script>
</body>
</html>