Public
Edited
May 31, 2023
Insert cell
Insert cell
import { select, dataset } from "@observablehq/stdlib"
Insert cell
div = {
return d3.create("div").node();
}
Insert cell
{
// Load the Palmer Penguins dataset
const penguins = await d3.csv(
"https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv"
);

// Extract the required columns
const species = penguins.map((d) => d.species);
const billLength = penguins.map((d) => d.bill_length_mm);
const bodyMass = penguins.map((d) => d.body_mass_g);

// Create a container for the visualization
const container = d3.select("body").append("div");

// Create the scatter plot
const svg = container.append("svg").attr("width", 600).attr("height", 400);

const xScale = d3
.scaleLinear()
.domain([Math.min(...billLength), Math.max(...billLength)])
.range([50, 550]);

const yScale = d3
.scaleLinear()
.domain([Math.min(...bodyMass), Math.max(...bodyMass)])
.range([350, 50]);

svg
.selectAll("circle")
.data(penguins)
.enter()
.append("circle")
.attr("cx", (d) => xScale(d.bill_length_mm))
.attr("cy", (d) => yScale(d.body_mass_g))
.attr("r", 5)
.attr("fill", "steelblue");

// Add axes
svg
.append("g")
.attr("transform", "translate(0, 350)")
.call(d3.axisBottom(xScale));

svg
.append("g")
.attr("transform", "translate(50, 0)")
.call(d3.axisLeft(yScale));

// Add labels
svg
.append("text")
.attr("x", 300)
.attr("y", 390)
.attr("text-anchor", "middle")
.text("Bill Length (mm)");

svg
.append("text")
.attr("transform", "rotate(-90)")
.attr("x", -200)
.attr("y", 20)
.attr("text-anchor", "middle")
.text("Body Mass (g)");
div.append(svg.node());
}
Insert cell
{
let canvas = d3.create("canvas").node();
// Vertex shader source code
const vertexShaderSource = `
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
}
`;

// Fragment shader source code
const fragmentShaderSource = `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // Red color for wildfires
}
`;

// Initialize WebGL context
const gl = canvas.getContext("webgl");

// Create and compile the shader program
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (success) {
return shader;
}

console.log(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
}

// Create the vertex and fragment shaders
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(
gl,
gl.FRAGMENT_SHADER,
fragmentShaderSource
);

// Create the shader program
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

// Set up vertex data
const positions = [-1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1];
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

const positionAttributeLocation = gl.getAttribLocation(program, "a_position");
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

// Clear the canvas and draw
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 6);
return canvas;
}
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