Public
Edited
Oct 24, 2023
8 forks
Importers
68 stars
Insert cell
Insert cell
Insert cell
population2radius = d3.scaleSqrt() // instead of scaleLinear()
.domain([0, 2e9])
.range([0, 300])
Insert cell
population2radius(1.386e9) // China’s 1.386 billion citizens are represented by a circle of radius = 250px
Insert cell
population2radius(127e6) // Japan’s population of 127 millions is represented by a circle of radius = 76px
Insert cell
population2radius(427e3) // Brunei shows up as a small circle
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const color = d3.scaleOrdinal(d3.schemePaired.slice(7));

const strokeWidth = 8;

const population2radius = d3.scaleSqrt()
.domain([0, 2e9])
.range([0 + strokeWidth / 2, 300 + strokeWidth / 2]); // 🌶

return svg`<svg width=${width} height=200px stroke-width=${strokeWidth} stroke=#ddd>
<g transform="translate(50,100)" style="text-anchor: middle; font-family: sans-serif; font-weight: bold;">
<circle r=${population2radius(427e3)} cx=20 fill="${color("Brunei")}" />
<text dx=20 dy=${-10 - strokeWidth / 2} stroke=none fill=#555>Brunei</text>
<circle r=${population2radius(56.72e6)} cx=220 fill="${color("China")}" />
<text dx=220 fill="white" stroke=none>S. Africa</text>
<circle r=${population2radius(127e6)} cx=500 fill="${color("Japan")}" />
<text dx=500 fill="white" stroke=none>Japan</text>
</g>
</svg>`;
}
Insert cell
Insert cell
Insert cell
{
const values = [5, 20, 50, 100]; // hint: add 0 in this array…

const scale = d3.scaleSqrt()
.domain([0, d3.max(values)])
.range([1, 100]); // … then change 1 to 0

return svg`<svg width=${width} height=230px><g transform="translate(200,10)">
${values.map(
v =>
svg`<g><circle cy="${200 - scale(v)}"
r="${scale(v)}" stroke=black fill=none />
<text y="${200 - 2 * scale(v) + 3}"
style="dominant-baseline: hanging; text-anchor: middle;"
>${v}</text>
</g>`
)}</g></svg>`;
}
Insert cell
Insert cell
visualizeScale(d3.scaleSqrt())
Insert cell
Insert cell
Insert cell
Insert cell
visualizeScale(d3.scaleSqrt().domain([-1, 1]))
Insert cell
Insert cell
visualizeScale(
d3.scaleSqrt()
.domain([-400, -100, 0, 400])
.range([0, 1, 10, 15])
)
Insert cell
Insert cell
visualizeScale(
d3.scaleSqrt()
.domain([-100, 100])
.rangeRound([-10, 10])
)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
paint = d3.scalePow()
.exponent(k)
.range(["yellow", "red"])
Insert cell
Insert cell
Insert cell
visualizeScale(d3.scalePow().exponent(1 / 3))
Insert cell
Insert cell
visualizeScale(
d3.scalePow()
.exponent(1.2)
.range([0.0999, 1])
)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// adapted from http://lasp.colorado.edu/~bagenal/MATH/math0.html#tables
objects = [
{ name: "Milky Way Galaxy", size: 1e18 }, // sizes in km
{ name: "Nearest Star", size: 1e13 },
{ name: "The Solar System", size: 1e9 },
{ name: "The Sun", size: 1e6 },
{ name: "The Earth", size: 1e3 },
{ name: "A Mountain", size: 75 },
{ name: "A Human", size: 1e-3 },
{ name: "A Cell", size: 1e-8 },
{ name: "An Atom", size: 1e-12 },
{ name: "A Proton", size: 1e-15 }
]
Insert cell
scaleUniverse = d3.scaleLog().domain([1e-15, 1e20])
Insert cell
Insert cell
Insert cell
Insert cell
scaleBinary = d3.scaleLog()
.base(2)
.domain([16, 2 ** 20])
Insert cell
Insert cell
Insert cell
d3.scaleLog().domain([-100, -1])(-10)
Insert cell
Insert cell
powers = d3.scaleLog().domain([0.01, 100000])
Insert cell
// by default, ticks are displayed in scientific notation (SI)...
visualizeTicks(powers)
Insert cell
// ... but you can pass explicit format to ticks
// see https://d3js.org/d3-format#locale_format
visualizeTicks(powers, [5, "~g"])
Insert cell
Insert cell
Insert cell
binaryScale = d3.scaleLog()
.base(2)
.domain([1, 32])
Insert cell
visualizeTicks(
binaryScale,
[10, "b"] // 💡 see https://d3js.org/d3-axis#axis_ticks
)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
days = [
// l: label ; v: value
{ l: "The Big Bang", v: -13.8e9 * 365.24 },
{ l: "Dinosaur extinction", v: -65e6 * 365.24 },
{ l: "The founding of Rome", v: -(800 + 2019) * 365.24 },
{ l: "Last year", v: -365 },
{ l: "Yesterday", v: -1 },
{ l: "Now", v: +0 },
// { l: "In 2 hours", v: +2 / 24 },
{ l: "Tomorrow", v: +1 },
{ l: "Next year", v: +365 },
{ l: "2100", v: +365.24 * 91 },
{ l: "Asimov’s Foundation", v: +12000 * 365.24 },
{ l: "Sun dies", v: 6e9 * 365 }
]
Insert cell
{
const scale = d3.scaleSymlog()
.domain(d3.extent(days, d => d.v))
.constant(0.1) // try 0.01 to leave room for "in 2 hours"
.range([width * 0.05, width * 0.95]);

const svg = d3.create("svg")
.attr("width", width)
.attr("height", 100)
.attr("style", "text-anchor:middle; font-family: sans-serif; font-size:12px");

svg.append("line")
.attr("x1", scale.range()[0])
.attr("x2", scale.range()[1])
.attr("y1", 50)
.attr("y2", 50)
.attr("stroke", "#999");
const g = svg.selectAll("g")
.data(days)
.join("g")
.attr("transform", d => `translate(${scale(d.v)}, 50)`);

g.append("circle")
.attr("r", 4)
.attr("fill", d => (d.l === "Now" ? "red" : "black"));
g.append("text")
.attr("y", (_, i) => -8 + 30 * (i % 2))
.attr("dx", 3)
.text(d => d.l);

return svg.node();
}
Insert cell
Insert cell
paintRgb = d3.scaleSqrt()
.range(["blue", "red"])
.interpolate(d3.interpolateHsl)
Insert cell
paintHsl = paintRgb.copy()
.interpolate(d3.interpolateHslLong)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
radius = d3.scaleSqrt([0, 100], [0, 30])
Insert cell
radius(-1e-6) // 🕷 if this is used as a circle’s radius, it might create a bug
Insert cell
{
const clamped = d3.scaleSqrt([0, 100], [0, 30]).clamp(true);
return clamped(-1e-6); // 👍 fixed !
}
Insert cell
radius.clamp() // read the clamping state.
Insert cell
Insert cell
x = d3.scaleLinear([0, 1], [60, width * 0.95]).unknown(10)
Insert cell
values = Array.from({ length: 100 }, (_, i) => i % 10 === 0 ? NaN : Math.random())
Insert cell
Insert cell
Insert cell
function visualizeScale(scale) {
const w = Math.min(600, width),
h = 300,
m = width > 599 ? 30 : 10;
const x = d3.scaleLinear()
.domain(d3.extent(scale.domain()))
.nice()
.range([m, w - m]),
y = d3.scaleLinear()
.domain(d3.extent(scale.range()))
.nice()
.range([h - m, m]),
svg = d3.create("svg")
.attr("width", width + 20)
.attr("height", h + 20),
g = svg.append("g"),
line = [];

for (let i = m + 1e-6; i < w - m; i += 1) {
const X = x.invert(i),
Y = scale(X),
j = y(Y);
line.push([i, j]);
}

g.append("path")
.attr("d", "M" + line.join("L"))
.style("stroke", "black")
.style("fill", "none");

g.append("g")
.attr("transform", `translate(${m},0)`)
.call(d3.axisLeft(y));
g.append("g")
.attr("transform", `translate(0,${y(0)})`)
.call(d3.axisBottom(x));

return svg.node();
}
Insert cell
function visualizeTicks(scale, tickArguments) {
const height = 20, m = width > 599 ? 90 : 10;

if (tickArguments === undefined) tickArguments = [];

scale.range([m, width - m]);

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

svg.append("g").call(d3.axisBottom(scale).ticks(...tickArguments));

return svg.node();
}
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