Published
Edited
Aug 10, 2019
1 star
Insert cell
Insert cell
firstName = "Cameron"
Insert cell
lastName = "Yick"
Insert cell
handle = "hydrosquall"
Insert cell
width
Insert cell
height
Insert cell
// Based on the 10print design, introduced through the Daniel Shiffman Coding Train
function badgeCode(g, ctx, frameNumber) {
// Slightly off black
ctx.fillStyle = '#333'
// Experiments with tinting the background with the d3 background
// ctx.fillStyle = chroma.blend('#2c3e50', "#333", 'screen');
ctx.fillRect(0, 0, width, height);
ctx.lineWidth = 14;
ctx.lineCap = "square";
// Using non-matching xStepSize and lineHeight works nicer for designs where I'm not changing opacity.
const cellSize = 50;
const stepSize = cellSize;
const lineHeight = cellSize;
const probability = .20;
const drawLine = (x0, y0, x1, y1) => {
ctx.beginPath();
ctx.moveTo(x0, y0);
ctx.lineTo(x1, y1);
ctx.stroke();
}
const drawRow = (yStart) => {
for (let i = 0; i < width; i += 1) {
const xPoints = [i * stepSize, (i + 1) * stepSize];
const yPoints = [yStart, yStart + lineHeight];
// Generate Gradient Noise for this cell
const noiseVal = noise.simplex3(i * stepSize, yStart, frameNumber);
let isFlip = noiseVal < probability;
// Decide whether to introduce drawing variation
const points = isFlip ?
[xPoints[0], yPoints[0], xPoints[1], yPoints[1]] :
[xPoints[0], yPoints[1], xPoints[1], yPoints[0]];

const grayValue = 1 - Math.round(noiseVal * 255);
// const grayValue = 1;

let opacityValue;
if (gradientDirection === 'horizontal') {
opacityValue = 1 - (i * stepSize / width) + .2;
} else if (gradientDirection === 'vertical') {
opacityValue = opacityValue = 1 - (yStart / height) + .15;
} else {
opacityValue = 1;
}
let strokeStyle;
if (!isFlip) {
strokeStyle = chroma(bgColor).alpha(opacityValue - 0.1);
} else {
strokeStyle = chroma(`rgb(${grayValue}, ${grayValue}, ${grayValue})`).alpha(opacityValue);
}
ctx.strokeStyle = strokeStyle;
drawLine(...points);
}
}
// Render each row of the 10print
for (let i = 0; i < height; i += lineHeight) {
drawRow(i)
}
}
Insert cell
isTextLight = true
Insert cell
viewof gradientDirection = radio({
options: ["vertical","horizontal", 'none'].map(option => ({ value: option, label: option})),
value: 'vertical'
})
Insert cell
// #ffc576 - lighter
// #e19f44 - darker
viewof bgColor = color('#e19f44');
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import {preview, animation, download, width, height, d3}
with {firstName, lastName, handle, isTextLight, badgeCode}
from "b93171820ba3f268"
Insert cell
Insert cell
md`
## External Resources

- Prior investigations with [10Print](https://cam-sketch.netlify.com/?path=/info/p5js-code-art--10print)
- chroma.js for color adjustments
- NoiseJS for simplex noise
- Jeremy Ashkenas's input knobs
- Badge Builder Template
`
Insert cell
NoiseJS = require('https://bundle.run/noisejs@2.1.0');
Insert cell
// Tried to get OpenSimplexNoise to work, but ran into issues, Revisit if 4d is needed someday.
noise = {
const localNoise = new NoiseJS.Noise()
const seed = 0;
localNoise.seed(seed);
return localNoise;
}
Insert cell
import {color, radio} from "@jashkenas/inputs"
Insert cell
chroma = require('chroma-js')
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more