Published
Edited
Sep 28, 2021
Insert cell
Insert cell
Insert cell
Insert cell
axisExample = {
const svg = d3.create("svg").attr("width", width).attr("height", 70);

const simpleScale = d3
.scaleLinear()
.domain([Math.PI, Math.PI * 2])
.range([50, width-50]);

svg
.append("g")
.attr("transform", "translate(0,35)")
.call(
d3
.axisBottom(simpleScale)
.ticks(12)
.tickPadding(10)
.tickSizeInner(8)
.tickSizeOuter(16)
.tickFormat(d3.format(".2f"))
);

svg
.selectAll(".tick text")
.attr("font-size", "13px")
.attr("fill", "#566270")
.attr("font-family", "georgia");

svg.selectAll("g line").attr("stroke", "#00aaff").attr("stroke-width",3);

svg
.select("g path")
.attr("stroke", "#ff00aa")
.attr("stroke-width", 1)
.attr("stroke-dasharray", "8,2");
return svg.node();
}
Insert cell
Insert cell
{
d3.selectAll(".visualizationObjects")
.data(dataset)
.enter()
.append("element")
.attr("attribute", (d)=>d.property)
.attr("attribute", (state)=> state.property)
.attr("attribute", (d)=> {
const value = d.propertyName * d.otherProperty;
return value / d.anotherProperty;
})
.attr("attributeName", (d,i) => {
let value = d.propertyName * i
return value;
})
.attr("class","visualizationObjects");

return "that's data binding!";
}
Insert cell
emojiData = [
{ value: 50, emoji: "🐨" },
{ value: 89, emoji: "🐸" },
{ value: 40, emoji: "🐧" },
{ value: 7, emoji: "🦆" },
{ value: 40, emoji: "🐥" },
{ value: 52, emoji: "🐞" },
{ value: 12, emoji: "🐙" },
{ value: 32, emoji: "🐡" },
{ value: 17, emoji: "🐪" },
{ value: 78, emoji: "🦗" }
]
Insert cell
dataBinding = {
const emojiHeight = 250;
const emojiMargin = 50;
const svg = d3.create("svg").attr("width", width).attr("height", emojiHeight);

svg
.append("rect")
.attr("width", width)
.attr("height", emojiHeight)
.attr("stroke", "orange")
.attr("stroke-width", 10)
.attr("fill", "#eff");

const xScale = d3
.scaleLinear()
.domain([0, emojiData.length - 1])
.range([emojiMargin, width - emojiMargin]);

const yScale = d3
.scaleLinear()
.domain([0, 100])
.range([emojiHeight - emojiMargin, emojiMargin]);

svg
.selectAll(".emojiAnimals")
.data(emojiData)
.enter()
.append("text")
.attr("x", (d, i) => xScale(i))
.attr("y", (d) => yScale(d.value))
.text((d) => d.emoji)
.attr("font-size", 48)
.attr("text-anchor", "middle");

return svg.node();
}
Insert cell
{
const height = 200;
const svg = d3.create("svg").attr("width", width).attr("height", height);

const circles = d3.range(10).map((d) => {
svg
.append("circle")
.attr("cx", Math.random() * width)
.attr("cy", Math.random() * height)
.attr("r",5);
});

const selection = svg.selectAll("circle");
const emptySelection = svg.selectAll("something-we-did-not-make");

return selection
}
Insert cell
{
const height = 200;
const svg = d3.create("svg").attr("width", width).attr("height", height);

const numberOfCircles = 10;
const numberOfDataValues = 5;

const circles = d3.range(numberOfCircles).map((d) => {
svg
.append("circle")
.attr("cx", Math.random() * width)
.attr("cy", Math.random() * height)
.attr("r", 5)
});

const fakeData = d3.range(numberOfDataValues).map((d) => Math.random());

const comparedData = svg.selectAll("circle").data(fakeData);

return comparedData;
}
Insert cell
disabilityData = await d3.json(
"https://api.census.gov/data/2019/acs/acs1?get=NAME,B18102_006E,B18102_025E,B18103_007E,B18103_026E,B18102_007E,B18102_026E&for=state:*"
)
Insert cell
Insert cell
disabilityStates = {
const statesData = [];

for (let i=1 ; i < disabilityData.length ; i++) {
const state = disabilityData[i];

// [Q1. How can I display percentage with '.toFixed(2) * 100 + " %"'?]
// - it doesn't work when I add '.toFixed(2) * 100 + " %"' to all percentage data


const totalYoungPopulation = parseInt(state[1]) + parseInt(state[2]);
const visionDifficultyPercentage =
(parseInt(state[3])+parseInt(state[4])) / totalYoungPopulation;
const hearingDifficultyPercentage =
(parseInt(state[5])+parseInt(state[6])) / totalYoungPopulation;
const maleDifficultyPercentage =
(parseInt(state[3])+parseInt(state[5])) / parseInt(state[1]);
const femaleDifficultyPercentage =
(parseInt(state[4])+parseInt(state[6])) / parseInt(state[2]);
const totalYoungDifficultyPercentage =
(femaleDifficultyPercentage + maleDifficultyPercentage);


// [Q2. Why statesLable is not defined?]

const abbreviation = stateLabels.find(
(label) => label.fips == parseInt(state[7])
).abbreviation;

statesData.push({
name: state[0],
totalYoungPopulation,
visionDifficultyPercentage,
hearingDifficultyPercentage,
maleDifficultyPercentage,
femaleDifficultyPercentage,
totalYoungDifficultyPercentage,
abbreviation,
fipsCode: state[7]
});
}
statesData.sort((a,b) => d3.ascending(a.name, b.name));

return statesData;
}
Insert cell
viewof selectedStates = Inputs.table(disabilityStates)
Insert cell
selectedStates
Insert cell
visionDisabilityExtents = d3.extent(
selectedStates,
(state) => state.totalYoungDifficultyPercentage
)
Insert cell
import {color} from "@jashkenas/inputs"
Insert cell
viewof simpleTopic = Inputs.select(
[
"maleDifficultyPercentage",
"femaleDifficultyPercentage",
"visionDifficultyPercentage",
"hearingDifficultyPercentage"
],
{label: "visualizationTopic", value: "visionDifficultyPercentage"}
)
Insert cell
viewof margin = Inputs.range([ 0 , 100 ] , {label: "margin", step: 1 })
Insert cell
viewof height = Inputs.range([200,400], {label: "heihgt", step: 10})
Insert cell
viewof bgColor = color({
value: "#FFFFF3",
description: "What color do you want the background to be"
})
Insert cell
viewof circleColor = color({
value: "#58C1AA",
description: "What color do you want the circles to be"
})
Insert cell
simpleViz = {
const svg = d3.create("svg").attr("width", width).attr("height", height);

svg
.append("rect")
.attr("width", width)
.attr("height", height)
.attr("fill", bgColor),

svg
//"g" > group
.append("g")
.attr("transform", "translate(0,"+(height-margin)+")")
.call(xAxis)
.call((g) => {
g.selectAll("line");
});

svg
.append("g")
.attr("transform", "translate("+margin+")")
.call(yAxis)
.call((g) => {
g.select(".domain").remove();
g.selectAll("line").attr("opacity", ".2");
});

svg
.selectAll(".tick text")
.attr("font-size", "10px")
.attr("fill", "#566270")
.attr("font-family", "futura");

svg.selectAll("line").attr("stroke", "#566270");
svg
.selectAll(".disabilityDots")
.data(disabilityStates)
.enter()
.append("circle")
.attr("cx", (d) => abbreviationToPixelsX(d.abbreviation))
// .attr("cx", (d) => fipsCodeToPixelsX(d.fipsCode))
.attr("cy", (d) => percentToPixelsY(d[simpleTopic]))
.attr("r", 5)
.attr("fill", circleColor)
// where has "disabilityDots" from?
.attr("class", "disabilityDots");

return svg.node();
}
Insert cell
// fipsCodeToPixelsX = d3
// .scalePoint()
// .domain(disabilityStates.map((d) => d.fipsCode))
// .range([margin, width-margin])
// .padding(1)
Insert cell
abbreviationToPixelsX = d3
.scalePoint()
.domain(disabilityStates.map((d) => d.abbreviation))
.range([margin, width-margin])
.padding(1)
Insert cell
percentToPixelsY = d3
.scaleLinear()
.domain([0, 0.05])
.range([height-margin, margin])
Insert cell
xAxis = d3
.axisBottom(abbreviationToPixelsX)
// .axisBottom(fipsCodeToPixelsX)
.tickPadding(10)
.tickSizeInner(5)
.tickSizeOuter(0)
Insert cell
yAxis = d3
.axisLeft(percentToPixelsY)
.ticks(5)
.tickSize(-width + margin * 2)
.tickPadding(10)
.tickFormat(d3.format(".0%"))
Insert cell
Insert cell
Insert cell
Insert cell
map = {

const svg = d3.create("svg").attr("width", width).attr("height", height);

const visualizationKeys =
vizTopic == "Females vs Males"
? ["femaleDifficultyPercentage", "maleDifficultyPercentage"]
: ["hearingDifficultyPercentage", "visionDifficultyPercentage"];

svg
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height)
.attr("fill", bgColor);

svg
.append("g")
.attr("transform", "translate(0," + (height - margin) + ")")
.call(xAxis)
.call((g) => {
g.selectAll("line");
});

svg
.append("g")
.attr("transform", "translate(" + margin + ")")
.call(yAxis)
.call((g) => {
g.select(".domain").remove();
g.selectAll("line").attr("stroke-dasharray", "2,4");
});

svg
.selectAll(".tick text")
.attr("font-size", "10px")
.attr("fill", "#566270")
.attr("font-family", "menlo");

svg.selectAll("line").attr("stroke", "#566270");

svg
.selectAll(".dumbell")
.data(disabilityStates)
.enter()
.append("line")
.attr("x1", (d) => abbreviationToPixelsX(d.abbreviation))
// .attr("x1", (d) => fipsCodeToPixelsX(d.fipsCode))
.attr("y1", (d) => percentToPixelsY(d[visualizationKeys[0]]))
.attr("x2", (d) => abbreviationToPixelsX(d.abbreviation))
// .attr("x2", (d) => fipsCodeToPixelsX(d.fipsCode))
.attr("y2", (d) => percentToPixelsY(d[visualizationKeys[1]]))
.attr("stroke", (d) =>
d[visualizationKeys[0]] > d[visualizationKeys[1]]
? colorFemaleHearing
: colorMaleVision
)
.attr("stroke-width", 2)
.attr("class", "dumbell");

svg
.selectAll(".circlesCategoryA")
.data(disabilityStates)
.enter()
.append("circle")
.attr("cx", (d) => abbreviationToPixelsX(d.abbreviation))
// .attr("cx", (d) => fipsCodeToPixelsX(d.fipsCode))
.attr("cy", (d) => percentToPixelsY(d[visualizationKeys[0]]))
.attr("r", 5)
.attr("fill", colorFemaleHearing)
.attr("class", "circlesCategoryA")
.on("mouseover", (e, d) => tooltipShow(e, d, 0))
.on("mouseout", (event, datum) => tooltipHide(event, datum));

svg
.selectAll(".circlesCategoryB")
.data(disabilityStates)
.enter()
.append("circle")
.attr("cx", (d, i) => abbreviationToPixelsX(d.abbreviation))
.attr("cy", (d) => percentToPixelsY(d[visualizationKeys[1]]))
.attr("r", 5)
.attr("fill", colorMaleVision)
.attr("class", "circlesCategoryB")
.on("mouseover", (e, d) => tooltipShow(e, d, 1))
.on("mouseout", (event, datum) => tooltipHide(event, datum));

svg
.append("text")
.text("")
.attr("y", margin / 2)
.attr("id", "tooltip")
.attr("opacity", 0)
.attr("font-family", "menlo")
.attr("font-size", "10px")
.attr("text-anchor", "middle");

return svg.node();
}
Insert cell
tooltipHide = (e, d) => {
d3.select(e.target).transition().attr("r", 5);
d3.select("#tooltip").transition().delay(500).attr("opacity", 0);
}
Insert cell
tooltipShow = (event, data, dotCategory) => {
const visualizationKeys =
vizTopic == "Females vs Males"
? ["femaleDifficultyPercentage", "maleDifficultyPercentage"]
: ["hearingDifficultyPercentage", "visionDifficultyPercentage"];

d3.select(event.target).transition().attr("r", 8);
d3.select("#tooltip")
.attr("x", abbreviationToPixelsX(data.abbreviation))
// .attr("x", fipsCodeToPixelsX(data.fipsCode))
.text(
data.name +
" : " +
d3.format(".2%")(data[visualizationKeys[dotCategory]]) +
" " +
visualizationKeys[dotCategory]
)
.transition()
.attr("opacity", 1);
}
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