Public
Edited
Nov 22, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
<!DOCTYPE html>
<html>
<head>
<!-- Set a title that will appear on the tab of your browser -->
<title>Simple Webpage</title>
<!-- Link your page to your css file -->
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<!-- Add a title to your webpage -->
<h1>Simple Webpage</h1>

<!-- Add a paragraph -->
<p>Simple Webpage using HTML, css and JavaScript.</p>
<!-- Include your JavaScript content -->
<script src="main.js"></script>
</body>
</html>
Insert cell
Insert cell
/* This code will color your title (h1) in blue */
h1{
color: blue;
}
Insert cell
Insert cell
// Functions will be written here
Insert cell
Insert cell
Insert cell
Insert cell
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap" rel="stylesheet">
Insert cell
Insert cell
body{
font-family: 'Roboto', sans-serif;
}
Insert cell
Insert cell
Insert cell
<script src="https://d3js.org/d3.v7.min.js"></script>
Insert cell
Insert cell
<h1>Webpage with a chart</h1>
Insert cell
Insert cell
// Access the html container
var body = d3.select("body")

// Create a svg
// Note that width, margin and height are not defined yet
var svg = body.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)

// Add an inner container
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
Insert cell
Insert cell
// Define dimensions
var width = 300
var height = 300

var margin = {top: 5, right: 5, bottom: 50, left: 50}
Insert cell
Insert cell
// Create a x scale tranforming linearily any number between 0 and 30 to a number between 0 and width
var xScale = d3.scaleLinear()
.domain([0, 30])
.range([0, width])

// Create a y scale tranforming linearily any number between 0 and 60 to a number between height and 0
var yScale = d3.scaleLinear()
.domain([0, 60])
.range([height, 0])
Insert cell
Insert cell
// Draw the x axis by calling the axisBottom function on your x scale
g.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale))

// Draw the y axis by calling the axisLeft function on your y scale
g.append("g")
.call(d3.axisLeft(yScale))
Insert cell
Insert cell
d3.csv("penguins.csv").then(function(penguins) {

var data = penguins
...
})
Insert cell
Insert cell
penguins.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Now, still inside the function, display the data.
Insert cell
// Draw a circle for each datum
g.selectAll(".point")
.data(data)
.enter()
.append("circle")
.attr("class", "point")
.attr("cx", d => xScale(d.culmen_depth_mm))
.attr("cy", d => yScale(d.culmen_length_mm))
.attr("r", 2)
Insert cell
Insert cell
var penguinsNoNan = penguins.filter(function(d){
return (d.species
&& d.island
&& d.culmen_length_mm
&& d.culmen_depth_mm
&& d.flipper_length_mm
&& d.body_mass_g
&& d.sex)
})
var data = penguinsNoNan
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Create a x scale
var x = d3.scaleLinear()
.domain(d3.extent(data, d => d.culmen_depth_mm))
.range([0, width])

// Create a y scale
var y = d3.scaleLinear()
.domain(d3.extent(data, d => d.culmen_length_mm))
.range([height, 0])
Insert cell
Insert cell
// Add x title
g.append("text")
.attr("text-anchor", "middle")
.attr("alignment-baseline", "after-edge")
.attr("x", width/2)
.attr("y", height + margin.bottom)
.text("culmen_depth_mm")

// Add y title
g.append("text")
.attr("text-anchor", "middle")
.attr("alignment-baseline", "hanging")
.attr("transform", "rotate(-90)")
.attr("x", -height/2)
.attr("y", -margin.left)
.text("culmen_length_mm")
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Create a radius scale
var rScale = d3.scaleLinear()
.domain(d3.extent(data, d => d.body_mass_g))
.range([1, 10])

// Create a color scale
// Identify all the categories of islands
var islandCat = Array.from(d3.group(data, d => d.island)).map(d => d[0])
// Note that for the colour the scale is ordinal and the range refer to a set of existing scheme
var colorScale = d3.scaleOrdinal()
.domain(islandCat)
.range(d3.schemeTableau10)
Insert cell
Insert cell
Insert cell
// Draw a circle for each datum
g.selectAll(".point")
.data(data)
.enter()
.append("circle")
.attr("class", "point")
.attr("cx", d => xScale(d.culmen_depth_mm))
.attr("cy", d => yScale(d.culmen_length_mm))
.attr("r", d => rScale(d.body_mass_g))
.attr("fill", d => colorScale(d.island))
Insert cell
Insert cell
var margin = {top: 5, right: 100, bottom: 50, left: 50}
Insert cell
// Draw colour legend
var colourLegend = g.selectAll(".colourLegend")
.data(islandCat)
.enter()
.append("g")
.attr("class", "colourLegend")
.attr("transform", (d, i) => ("translate(" + (width + 20) + "," + (margin.top + i*18) + ")"))
colourLegend.append("circle")
.attr("r", 5)
.attr("fill", d => colorScale(d))
colourLegend.append("text")
.attr("transform", "translate(15,0)")
.attr("alignment-baseline", "middle")
.text(d => d)
// Draw size legend
var sizeLegend = g.append("g")
.attr("transform", (d, i) => ("translate(" + (width + 20) + "," + (margin.top + 4*18) + ")"))

// Smallest bubble
sizeLegend.append("circle")
.attr("r", 1)
sizeLegend.append("text")
.attr("transform", "translate(15,0)")
.attr("alignment-baseline", "middle")
.text(d3.min(data, d => d.body_mass_g) + " g")

// Largest bubble
sizeLegend.append("circle")
.attr("transform", "translate(0,18)")
.attr("r", 10)
sizeLegend.append("text")
.attr("transform", "translate(15,18)")
.attr("alignment-baseline", "middle")
.text(d3.max(data, d => d.body_mass_g) + " g")
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Draw a circle for each datum
g.selectAll(".point")
.data(data)
.enter()
.append("circle")
.attr("class", "point")
.attr("cx", d => x(d.culmen_depth_mm))
.attr("cy", d => y(d.culmen_length_mm))
.attr("r", d => r(d.body_mass_g))
.attr("fill", d => color(d.island))
.on("mouseover", (event, d) => onMouseOver(event, d))
.on("mouseout", onMouseOut)
Insert cell
Insert cell
function onMouseOver(event, d) {
var mouse = d3.pointer(event, d3.select("body").node())
// Create a tooltip that will appear on mouse over and disapear on mouse out.
tooltip.style("display", null)
.style("left", (mouse[0] + 20) + "px")
.style("top", (mouse[1] + 20) + "px")
.html(d.sex)
}

function onMouseOut() {
tooltip.style("display", "none");
}
Insert cell
Insert cell
var tooltip = d3.select("body").append("div")
.style("display", "none")
.style("position", "absolute")
.style("background-color", "#FFFA")
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
width = 500
Insert cell
height = 500
Insert cell
xScale = d3.scaleLinear()
.domain(d3.extent(penguinsNoNan, d => d.culmen_depth_mm))
.range([0, width])
Insert cell
Insert cell
chart = {

// Define dimensions, defined globally
// var width = 300;
// var height = 300;
var margin = {top: 5, right: 100, bottom: 50, left: 50};

var data = penguinsNoNan;

// Create a svg
// DIFFERENT FROM HOMEMADE WEBSITE
var svg = d3.create("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);

var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// Create a x scale, defined globally
// var xScale = d3.scaleLinear()
// .domain(d3.extent(data, d => d.culmen_depth_mm))
// .range([0, width]);
// Create a y scale
var yScale = d3.scaleLinear()
.domain(d3.extent(data, d => d.culmen_length_mm))
.range([height, 0]);
// Create a radius scale
var rScale = d3.scaleLinear()
.domain(d3.extent(data, d => d.body_mass_g))
.range([0, 10]);
// Create a color scale
var islandCat = Array.from(d3.group(data, d => d.island)).map(d => d[0])
var colorScale = d3.scaleOrdinal()
.domain(islandCat)
.range(d3.schemeTableau10)
// Draw the x axis
g.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale))
// Add x title
g.append("text")
.attr("text-anchor", "middle")
.attr("alignment-baseline", "after-edge")
.attr("x", width/2)
.attr("y", height + margin.bottom)
.text("culmen_depth_mm");
// Draw the y axis
g.append("g")
.call(d3.axisLeft(yScale))
// Add y title
g.append("text")
.attr("text-anchor", "middle")
.attr("alignment-baseline", "hanging")
.attr("transform", "rotate(-90)")
.attr("x", -height/2)
.attr("y", -margin.left)
.text("culmen_length_mm");

// Draw colour legend
var colourLegend = g.selectAll(".colourLegend")
.data(islandCat)
.enter()
.append("g")
.attr("class", "colourLegend")
.attr("transform", (d, i) => ("translate(" + (width + 20) + "," + (margin.top + i*18) + ")"))
colourLegend.append("circle")
.attr("r", 5)
.attr("fill", d => colorScale(d))
colourLegend.append("text")
.attr("transform", "translate(15,0)")
.attr("alignment-baseline", "middle")
.text(d => d)
// Draw size legend
var sizeLegend = g.append("g")
.attr("transform", (d, i) => ("translate(" + (width + 20) + "," + (margin.top + 4*18) + ")"))
sizeLegend.append("circle")
.attr("r", 1)
sizeLegend.append("text")
.attr("transform", "translate(15,0)")
.attr("alignment-baseline", "middle")
.text(d3.min(data, d => d.body_mass_g) + " g")
sizeLegend.append("circle")
.attr("transform", "translate(0,18)")
.attr("r", 10)
sizeLegend.append("text")
.attr("transform", "translate(15,18)")
.attr("alignment-baseline", "middle")
.text(d3.max(data, d => d.body_mass_g) + " g")

// Draw a circle for each datum
g.selectAll(".point")
.data(data)
.enter()
.append("circle")
.attr("class", "point")
.attr("cx", d => xScale(d.culmen_depth_mm))
.attr("cy", d => yScale(d.culmen_length_mm))
.attr("r", d => rScale(d.body_mass_g))
.attr("fill", d => colorScale(d.island))
.on("mouseover", (event, d) => onMouseOver(event, d))
.on("mouseout", onMouseOut)
var tooltip = d3.select("body").append("div")
.style("display", "none")
.style("position", "absolute")
.style("background-color", "#FFFA")
function onMouseOver(event, d) {
var mouse = d3.pointer(event, d3.select("body").node())

tooltip.style("display", null)
.style("left", (mouse[0] + 20) + "px")
.style("top", (mouse[1] + 20) + "px")
.html(d.sex)
}

function onMouseOut() {
tooltip.style("display", "none");
}

// DIFFERENT FROM HOMEMADE WEBSITE
return svg.node();

}
Insert cell
Insert cell
Insert cell
Plot.plot({
marks: [
Plot.rectY(penguins, Plot.binX({y: "count"}, {x: "body_mass_g"})),
Plot.ruleY([0])
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more