Skip to content

Instantly share code, notes, and snippets.

@lkpttn
Last active January 3, 2019 00:30
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lkpttn/63eb3f16e0c46b42226728f5977bd62a to your computer and use it in GitHub Desktop.
Save lkpttn/63eb3f16e0c46b42226728f5977bd62a to your computer and use it in GitHub Desktop.
Canvas exercise for mattdesl's Frontend Masters course.
const canvasSketch = require('canvas-sketch');
const { lerp } = require('canvas-sketch-util/math');
const random = require('canvas-sketch-util/random');
const palettes = require('nice-color-palettes');
const settings = {
// Defines settings for canvas size, exports, etc
dimensions: [2048, 2048],
};
// Encapsulates the entire project in a single function.
const sketch = () => {
// Picks a random 5 color palette from the library
const palette = random.pick(palettes);
const symbols = ['▬', '‑', '‒', '—', '‑', '‒', '—', '▲', '●'];
// Create an array of points
// We want to set up all the data in one place, and keep it separate from the rendering
// All randomness and generation happens here, not in the render function
const createGrid = () => {
const points = [];
const count = 60;
// Nested for loop to create x and y coordinates
for (let x = 0; x < count; x++) {
for (let y = 0; y < count; y++) {
// Working in uv space instead of final pixel coordinates
// For added flexibility
const u = count <= 1 ? 0.5 : x / (count - 1);
const v = count <= 1 ? 0.5 : y / (count - 1);
// Using 2D noise will return relatively similar values that move slowly between -1 and 1
const radius = 0.03 + Math.abs(random.noise2D(u, v, 2) * 0.05);
points.push({
radius: radius,
color: random.pick(palette),
rotation: random.noise2D(u, v),
character: random.pick(symbols),
postion: [u, v],
});
}
}
return points;
};
// Filter will return an array based on the function it recieves
// Here it's removing grid points randomly, about half
const points = createGrid().filter(() => random.value() > 0.5);
const margin = 300;
// Returns a function, a render function
// Feed it "props"
return ({ context, width, height }) => {
context.fillStyle = '#F2F2F2';
context.fillRect(0, 0, width, height);
points.forEach(data => {
// Destructure the data parameter so we can access the grid object properties
const { postion, color, radius, rotation, character } = data;
const [u, v] = postion;
// Need to turn uv values back into real pixels
// Using linear interpolation to start the grid
// Lerp returns a value between min and max, interpolated by t
// From our earlier function, the uv values are between 0 and 1, suitable for interpolation
const x = lerp(margin, width - margin, u);
const y = lerp(margin, height - margin, v);
context.save();
context.fillStyle = color;
context.font = `${radius * width}px "Arial"`;
context.translate(x, y);
context.rotate(rotation);
context.fillText(character, 0, 0);
context.restore();
// context.beginPath();
// context.arc(x, y, radius * width, 0, Math.PI * 2, false);
// context.fillStyle = color;
// context.fill();
});
};
};
canvasSketch(sketch, settings);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment