Published
Edited
Apr 18, 2022
10 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// const svg = d3.select(DOM.svg(params.svg.width, params.svg.height))
// .attr("id", "heatmap");
// const chartBackground = svg.append("rect")
// .attr("id", "chart-background")
// .attr("fill", "#F6F6F6")
// .attr("x", 0)
// .attr("y", 0)
// .attr("width", params.svg.width)
// .attr("height", params.svg.height);
// const plot = svg.append("g")
// .attr("id", "plot")
// .attr("transform", `translate(${params.plot.x}, ${params.plot.y})`);

// return svg.node();
Insert cell
Insert cell
// const chartTitle = svg.append("g")
// .attr("class", "chart-title")
// .attr("transform", width >= 840 ? `translate(${params.plot.x}, 5)` : `translate(15, 5)`)
// .append("text")
// .attr("id", "title-text")
// // .attr("text-anchor", "middle")
// // .attr("x", `${params.svg.width / 2}`)
// .attr("text-anchor", "start")
// .attr("x", 0)
// .attr("y", 0)
// .attr("dy", "2em")
// .style("font-weight", "700")
// .style("font-size", "clamp(.7rem, 2.5vw, 1.2rem)") // minimum, preferred, maximum
// .text(data.title);
// const chartSubtitle = svg.append("g")
// .attr("class", "chart-subtitle")
// .attr("transform", width >= 840 ? `translate(${params.plot.x}, 0)` : `translate(15, 0)`)
// .append("text")
// .attr("id", "subtitle-text")
// .attr("text-anchor", "start")
// .attr("x", 0)
// .attr("y", 0)
// .attr("dy", "4em")
// .style("font-weight", "400")
// .style("font-size", "clamp(.7rem, 2.5vw, 1.2rem)") // minimum, preferred, maximum
// .text(width >= 480 ? data.subtitle : data.subtitle.substr(0, 25) + "…"); // truncation
Insert cell
Insert cell
// svg.append("g")
// .attr("transform", `translate(${params.svg.width - params.margin.right}, ${params.svg.height})`)
// .append("text")
// .attr("id", "byline")
// .attr("x", 0)
// .attr("y", 0)
// .attr("dy", "-2.5em")
// .attr("text-anchor", "end")
// .text('@DiDoesDigital');
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
//@import url('https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&display=swap');
//@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,400;0,700;1,400;1,700&display=swap');

typographyStyles = html`<style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;700&display=swap');

text {
fill: #282541;
font: 400 12px/1.4 "Noto Sans", sans-serif;
}

#title {
fill: #282541;
font: 700 16px/1.4 "Noto Sans", sans-serif;
}
`
Insert cell
Insert cell
html`<style>
blockquote {
color: #949494;
font-size: 24px;
}

/* https://css-tricks.com/almanac/properties/q/quotes/ */
blockquote p::before {
content: open-quote;
quotes: "“" "”";
font-size: 60px;
position: absolute;
top: -20px;
left: -10px;
}

</style>`
Insert cell
Insert cell
Insert cell
Insert cell
// const legend = svg.append("g")
// .attr("class", "legend")
// // Reposition the legend after yielding the SVG node
// .call(d3Legend
// .legendColor()
// .shape("rect")
// .shapeWidth(d3.max([scale.x.bandwidth(), 24]))
// .shapeHeight(scale.y.bandwidth())
// .shapePadding(d3.max([scale.x.bandwidth() + 5, 24 + 5]))
// .labelOffset(scale.y.bandwidth() + 5)
// .title("Legend")
// .orient('horizontal')
// .cellFilter(d => d.data !== 0) // skip zero, if it's not interesting
// .labelAlign('start')
// .labelFormat('d')
// .scale(scale.color)
// .cells(4)
// .ascending(true)
// .labels(["None", "One", "Two", "Three"])
// );

// yield svg.node(); // yield, so that legend.node().getBBox() has results
// // Calculate how much to shift legend group to fit in our plot area nicely
// // via https://bl.ocks.org/sjengle/4e8777bed44557dadafa
// const legendBounds = legend.node().getBBox();
// const legendXShift = params.svg.width - legendBounds.width - params.margin.right;
// const legendYShift = -legendBounds.y + 16 //(params.margin.top - legendBounds.height);
// legend.attr("transform", `translate(${legendXShift}, ${legendYShift})`);
Insert cell
Insert cell
// scale = {
// const x = d3.scaleBand()
// .domain(xAxisData)
// .range([0, params.plot.width]);

// const y = d3.scaleBand()
// .domain(yAxisData)
// .range([params.plot.height, 0]);

// const size = d3.scaleSqrt()
// .domain(d3.extent(data, d => d.words))
// .range([5, width / 32]);

// const color = d3.scaleOrdinal()
// .domain(d3.map(data, d => d.revisionMode))
// .range(["#4EA376", "#9885D5"])

// const color2 = d3.scaleSequential()
// .interpolator(d3.interpolatePurples)
// .domain([0, 3]);

// return {x: x, y: y, size: size, color: color}
// }
Insert cell
Insert cell
// const gx = svg.append("g")
// .attr("id", "x-axis")
// .attr("class", "axis")
// .attr("transform", `translate(${params.plot.x}, ${params.plot.y})`)
// .call(axis.x)
// .call(g => g.selectAll(".tick text").attr('dx', '0.25em'));

// const gy = svg.append("g")
// .attr("id", "y-axis")
// .attr("class", "axis")
// .attr("transform", `translate(${params.plot.x}, ${params.plot.y})`)
// .call(axis.y);

Insert cell
// const xAxis = d3.axisBottom(scale.x)
// .ticks(width / 120)
// .tickPadding(6)
// .tickSizeOuter(0)
// .tickSizeInner(0)
// .tickFormat(d3.timeFormat('%-I:%M %p'))
Insert cell
// axis = {
// const x = d3.axisTop(scale.x)
// .tickPadding(3)
// .tickSizeOuter(0)
// .tickSizeInner(0)
// .call(g => g.selectAll(".tick text").attr("fill", "#202630").style("font-size", 16).attr("font-family", "'Source Sans Pro', sans-serif"))
// .call(g => g.selectAll("path.domain").attr("stroke", "#202630"));
// const y = d3.axisLeft(scale.y)
// .tickPadding(3)
// .tickSizeOuter(0)
// .tickSizeInner(0);

// return {x: x, y: y};
// }
Insert cell
Insert cell
Insert cell
// const tooltip = d3.create("div")
// .attr("id", "tooltip")
// .attr("class", "tooltip")
// .html(`
// <div class="tooltip-name">
// <span id="name"></span> // Update id
// </div>
// <div class="tooltip-value">
// <span id="value"></span> // Update id
// </div>
// <div class="tooltip-date">
// <span id="date"></span> // Update id
// </div>
// `);

// // function onMouseEnter(d) { // d3@5
// function onMouseEnter(event, d) { // d3@6
// const xPos = scale.x(d.x); // Update x
// const yPos = scale.y(d.y); // Update y
// tooltip.style("opacity", 1);
// tooltip.style("transform", `translate(calc( -50% + ${xPos}px), calc(-100% + ${yPos}px))`);
// tooltip.select("#name") // Update id
// .text(d.y); // Update y
// tooltip.select("#value") // Update id
// .text(d.x); // Update x
// tooltip.select("#date") // Update id
// .text(d3.timeFormat("%d %b %Y")(d.date)); // Update date
// }
// function onMouseLeave() {
// tooltip.style("opacity", 0);
// }
// const circles = svg.selectAll("g.circles")
// .join("circle")
// .attr("fill", "#5F428F")
// .attr("r", 30)
// .attr("cx", d => scale.x(d.x))
// .attr("cy", d => scale.y(d.y))
// .on("mouseenter", onMouseEnter)
// .on("mouseleave", onMouseLeave);

// return html`
// <figure style="max-width: 100%;" role="group">
// <div id="chart-wrapper" class="wrapper">
// ${tooltip.node()}
// ${svg.node()}
// </div>
// </figure>
// </div>`;



// stylesTooltip = html`
// <style>
// #chart-wrapper {
// position: relative;
// }

// text {
// font-family: "Source Sans Pro", "Noto Sans", sans-serif;
// }

// .tooltip {
// background-color: #fff;
// box-shadow: 0 6px 8px rgba(60, 57, 65, .3), 0 1px 1px rgba(60, 57, 65, .1);
// font-family: "Source Sans Pro", "Noto Sans", sans-serif;
// left: 0;
// opacity: 0;
// padding: 0.5em 1em;
// pointer-events: none;
// border-radius: 5px;
// position: absolute;
// text-align: center;
// top: -12px;
// transition: opacity 0.2s linear, transform 0.0s ease-in-out;
// z-index: 1;
// }

// .tooltip:before {
// background-color: #fff;
// border-left-color: transparent;
// border-top-color: transparent;
// bottom: 0;
// content: '';
// height: 12px;
// left: 50%;
// position: absolute;
// transform-origin: center center;
// transform: translate(-50%, 50%) rotate(45deg);
// width: 12px;
// z-index: 1;
// }

// .tooltip-name {
// margin-bottom: 0.2em;
// font-size: 1em;
// line-height: 1.4;
// font-weight: 700;
// }

// .tooltip-value {
// margin-bottom: 0.2em;
// font-size: 0.8em;
// line-height: 1.4;
// font-weight: 400;
// }

// .tooltip-date {
// margin-bottom: 0.2em;
// font-size: 0.8em;
// line-height: 1.4;
// font-weight: 400;
// }
// </style>
// `
Insert cell
Insert cell
// viewof sortFunction = select({
// title: "Sort",
// description: "Select the sort function to use for sorting rows.",
// options: ["RatedByMostKitties", "RatedTopGoodieByMostKitties"],
// value: "RatedByMostKitties"
// })

// Usage:
// // if (sortFunction === "RatedByMostKitties") { return "doX" } else if (sortFunction === "RatedTopGoodieByMostKitties") { return "doY" }
Insert cell
Insert cell
// params = {
// let output = {};
// output["svg"] = {
// "width": width,
// "height": d3.max([width / 1.618, 450]) // golden ratio
// };
// output["margin"] = {
// "top": 168,
// "right": d3.max([width / 24, 12]),
// "bottom": 72,
// "left": d3.max([width / 6, 72])
// };
// output["plot"] = {
// "x": output["margin"]["left"],
// "y": output["margin"]["top"],
// "width": output["svg"]["width"] - output["margin"]["left"] - output["margin"]["right"],
// "height": output["svg"]["height"] - output["margin"]["top"] - output["margin"]["bottom"]
// };

// return output;
// }
Insert cell
Insert cell
// rawData = d3.csvParse(await FileAttachment("someFileName.csv").text(), d3.autoType)
Insert cell
// data = {
// const timeParser = d3.timeParse("%d %b %Y");
// const csvString = await FileAttachment("filename.csv").text();
// const rowConversionFunction = ({
// "Title": title,
// "URL": url,
// "Number of cells": y,
// "Date": x
// }) => ({
// title,
// url,
// x: timeParser(x),
// y: +y
// });
// const dataObjectTarget = d3.csvParse(csvString, rowConversionFunction);
// const extraPropertiesSource = {
// xAxisLabel: "Date →",
// yAxisLabel: "↑ Cells",
// title: "The number of cells written over time"
// };
// return Object.assign(dataObjectTarget, extraPropertiesSource);
// }
Insert cell
// const timeParser = d3.timeParse("%d/%m/%Y %H:%M:%S"); // 02/07/2020 07:33:01
// const rowConversionFunction = ({
// "field1": field1,
// "field2": field2,
// "numberStoredAsString": num,
// "dateField": date
// }) => {
// return {
// field1,
// field2: field2,
// num: +num,
// date: timeParser(datetime)
// }
// };
// let dataObjectTarget = await d3.tsvParse(tsv, rowConversionFunction);

// // tsv = `field1 field2 numberStoredAsString dateField
// // value1 value2 value3 value4`
Insert cell
Insert cell
// format = d3.format(",d") // 1,000 - group separated (e.g. comma for thousands) decimal notation, rounded to integer
Insert cell
Insert cell
import {toc} from "@tomshanley/indented-toc"
Insert cell
Insert cell
// import {select} from "@jashkenas/inputs"
Insert cell
// d3Legend = require('d3-svg-legend'); // https://d3-legend.susielu.com/
Insert cell
// d3 = require("d3@5")
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