Public
Edited
Jun 7, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function* pachinko_l(random, extent, h=360, s=50, n=100, height = 200) {
const dodge = dodger(radius * 2 + 1);
const margin = {top: 0, right: 30, bottom: 20, left: 30};
const values = Float64Array.from({length: n}, random);
if (extent === undefined) extent = d3.extent(values);
const x = d3.scaleLinear(extent, [margin.left, width - margin.right]).nice();

const svg = d3.select(DOM.svg(width, height)).style("overflow", "visible");
yield svg.node();

svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x));

for (let i = 0; i < n; ++i) {
if (i % 20 == 0) yield svg.node();
const cx = x(values[i]);
const cy = height - margin.bottom - dodge(cx) - radius - 1;
if (cy < margin.top) break;
svg.append("circle")
.attr("cx", cx)
.attr("cy", -400)
.attr("r", radius)
.attr("cy", cy)
.attr("fill", `hsl(${h}, ${s}%, ${values[i]}%)`);
}

yield svg.node();
}
Insert cell
function* pachinko_hsl(random, extent, s=50, l=50, n=100, height = 200) {
const dodge = dodger(radius * 2 + 1);
const margin = {top: 0, right: 30, bottom: 20, left: 30};
const values = Float64Array.from({length: n}, random);
if (extent === undefined) extent = d3.extent(values);
const x = d3.scaleLinear(extent, [margin.left, width - margin.right]).nice();

const svg = d3.select(DOM.svg(width, height)).style("overflow", "visible");
yield svg.node();

svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x));

for (let i = 0; i < n; ++i) {
if (i % 20 == 0) yield svg.node();
const cx = x(values[i]);
const cy = height - margin.bottom - dodge(cx) - radius - 1;
if (cy < margin.top) break;
svg.append("circle")
.attr("cx", cx)
.attr("cy", -400)
.attr("r", radius)
.attr("cy", cy)
.attr("fill", `hsl(${values[i]}, ${s}%, ${l}%)`);
}

yield svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
lumDef = (rgb = []) => { return 0.2126*rgb[0] + 0.7152*rgb[1] + 0.0722*rgb[2] }
Insert cell
Y_601 = (rgb = []) => { return 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2] }
Insert cell
Y_2020 = (rgb = []) => { return 0.2627*rgb[0] + 0.6780*rgb[1] + 0.0593*rgb[2] }
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
toRGBarray("#568923")
Insert cell
clickColors({string:"rgb(86, 137, 35)", code:"#568923"})
Insert cell
clickColors = (color) => {
const clamph = (max, value) => { return value >= 0 ? value%360 : value%360 + 360 }
const clamp = (min, max, value) => { return Math.max(min, Math.min(max, value)) }
const randNormVal = (min, max, mu, sigma) => { return Math.floor(clamp(min, max, max*d3.randomNormal(mu, sigma)())) }
const randNormValh = (max, mu, sigma) => { return Math.floor(clamph(max, max*d3.randomNormal(mu, sigma)())) }
const randVal = (min, max) => { return Math.floor(Math.abs(Math.random() * (max - min) + min)) }
const colorKnobs = {
method: "hsl",
rgb: {
r_min: 74,
r_max: 149,
g_min: 0,
g_max: 85,
b_min: 191,
b_max: 98,
},
hsl: {
h_min: 0,
h_max: 360,
s_min: 32,
s_max: 62,
l_min: 25,
l_max: 39,
},
s_rgb: {
r_mu: 127,
g_mu: 127,
b_mu: 127,
r_sigma: 255,
g_sigma: 255,
b_sigma: 255,
},
s_hsl: {
h_mu: 180,
s_mu: 50,
l_mu: 50,
h_sigma: 360,
s_sigma: 100,
l_sigma: 100,
},
};
const randomColorRGB = (colorKnobs) => {
const r = randVal(colorKnobs.rgb.r_min, colorKnobs.rgb.r_max);
const g = randVal(colorKnobs.rgb.g_min, colorKnobs.rgb.g_max);
const b = randVal(colorKnobs.rgb.b_min, colorKnobs.rgb.b_max);
const newcolor = d3.rgb(`rgb(${r}, ${g}, ${b})`);
return ({
string: `rgb(${r},${g},${b})`,
code: newcolor ? newcolor.formatHex() : "#090909",
});
};
const randomColorHSL = (colorKnobs) => {
const h = randVal(colorKnobs.hsl.h_min, colorKnobs.hsl.h_max);
const s = randVal(colorKnobs.hsl.s_min, colorKnobs.hsl.s_max);
const l = randVal(colorKnobs.hsl.l_min, colorKnobs.hsl.l_max);
const newcolor = d3.hsl(`hsl(${h}, ${s}%, ${l}%)`);
return ({
string: `hsl(${h},${s}%,${l}%)`,
code: newcolor ? newcolor.formatHex() : "#090909",
});
};
const genColors = (num, colorKnobs, randFunc) => {
return Array.from({ length: num }, () => randFunc(colorKnobs));
};
const genKnobsRGB = () => {
return({
r_min: randVal(0, 255),
r_max: randVal(0, 255),
g_min: randVal(0, 255),
g_max: randVal(0, 255),
b_min: randVal(0, 255),
b_max: randVal(0, 255),
});
};
const genKnobsHSL = () => {
return({
h_min: randVal(0, 360),
h_max: randVal(0, 360),
s_min: randVal(0, 100),
s_max: randVal(0, 100),
l_min: randVal(0, 100),
l_max: randVal(0, 100),
});
};
const randNormValRGB = (colorKnobs) => {
const r = randNormVal(0, 255, colorKnobs.s_rgb.r_mu, colorKnobs.s_rgb.r_sigma);
const g = randNormVal(0, 255, colorKnobs.s_rgb.g_mu, colorKnobs.s_rgb.g_sigma);
const b = randNormVal(0, 255, colorKnobs.s_rgb.b_mu, colorKnobs.s_rgb.b_sigma);
const newcolor = d3.rgb(`rgb(${r}, ${g}, ${b})`);
return ({
string: `rgb(${r}, ${g}, ${b})`,
code: newcolor ? newcolor.formatHex() : "#090909",
});
};
const randNormValHSL = (colorKnobs) => {
const h = randNormValh(360, colorKnobs.s_hsl.h_mu, colorKnobs.s_hsl.h_sigma);
const s = randNormVal(0, 100, colorKnobs.s_hsl.s_mu, colorKnobs.s_hsl.s_sigma);
const l = randNormVal(0, 100, colorKnobs.s_hsl.l_mu, colorKnobs.s_hsl.l_sigma);
const newcolor = d3.hsl(`hsl(${h}, ${s}%, ${l}%)`);
return ({
string: `hsl(${h}, ${s}%, ${l}%)`,
code: newcolor ? newcolor.formatHex() : "#090909",
});
};
const genColorKnobs = (s_rgRGB, s_rgHSL) => {
const method = Math.random() > 0.5 ? "hsl" : "rgb";
const rgRGB = genKnobsRGB();
const rgHSL = genKnobsHSL();
return({
method: method,
rgb: rgRGB,
hsl: rgHSL,
s_rgb: s_rgRGB,
s_hsl: s_rgHSL,
});
};
let color_rgb;
let color_hsl;
if (color.string.slice(0,3) == "hsl") {
color_hsl = d3.hsl(color.string);
color_rgb = d3.rgb(color_hsl);
} else {
color_rgb = d3.rgb(color.string);
color_hsl = d3.hsl(color_rgb);
}
const new_s_hsl = {
h_mu: color_hsl.h,
s_mu: color_hsl.s,
l_mu: color_hsl.l,
h_sigma: colorKnobs.s_hsl.h_sigma,
s_sigma: colorKnobs.s_hsl.s_sigma,
l_sigma: colorKnobs.s_hsl.l_sigma,
};
const new_s_rgb = {
r_mu: color_rgb.r,
g_mu: color_rgb.g,
b_mu: color_rgb.b,
r_sigma: colorKnobs.s_rgb.r_sigma,
g_sigma: colorKnobs.s_rgb.g_sigma,
b_sigma: colorKnobs.s_rgb.b_sigma,
};

const newColorKnobs = genColorKnobs(new_s_rgb, new_s_hsl);
const newColors = newColorKnobs.method == "hsl" ? genColors(16, colorKnobs, randNormValHSL) :
genColors(16, colorKnobs, randNormValRGB);
return({newColorKnobs: newColorKnobs,
newColors: newColors})
}
Insert cell
clamp = (min, max, value) => { return Math.max(min, Math.min(max, value)) }
Insert cell
clamph = (max, value) => { return value >= 0 ? value%360 : value%360 + 360 }
Insert cell
clampr = (min, max, value) => {
if (value >= max) {
return 2*max - value;
} else if (value <= min) {
return min + (min-value);
} else {
return value;
}
}
Insert cell
clamp(0, 100, clampr(0, 100, -5))
Insert cell
clampr(0, 100, 101)
Insert cell
randNormVal = (min, max, mu, sigma) => { return Math.floor(clamp(min, max, d3.randomNormal(mu, sigma)())) }
Insert cell
randNormValh = (max, mu, sigma) => { return Math.floor(clamph(max, d3.randomNormal(mu, sigma)())) }
Insert cell
h1 = randNormValh(360, 147, 360)
Insert cell
r1 = randNormVal(0, 100, 50, 100)
Insert cell
d3.randomNormal(150, 255)()
Insert cell
d3.hsl(`hsl(106,44%,0%)`)
Insert cell
d3.hsl(`hsl(106, 44%, 100%)`)
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