Skip to content

Commit

Permalink
doing lots of experiments and working on various sketching utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
mattdesl committed Jul 2, 2018
1 parent 5c8b837 commit aa4cd26
Show file tree
Hide file tree
Showing 17 changed files with 1,766 additions and 1,009 deletions.
124 changes: 124 additions & 0 deletions examples/canvas-distributions-2.js
@@ -0,0 +1,124 @@
const canvasSketch = require('canvas-sketch');
const Random = require('./util/random');
const { lerp, clamp, clamp01 } = require('./util/math');
const { cubicSpline, resampleLineBySpacing, getPolylinePerimeter } = require('./util/geom');
const { vec2 } = require('gl-matrix');
const polylineNormals = require('./util/polyline-util');
const defined = require('defined');

const colors = {
background: '#f4d9be',
foreground: '#ff911c',
pen: '#1975ff'
};

const settings = {
// animation: true,
// When exporting, use the seed as the suffix
// This way we can reproduce it more easily later
animation: true,
dimensions: [ 1280, 1280 ]
// units: 'in',
// pixelsPerInch: 300
};

const sketch = ({ context, width, height }) => {
const margin = -1;

const circle = (x, y, radius, steps = 8) => {
const points = [];
for (let i = 0; i < steps; i++) {
const t = i / steps;
const angle = Math.PI * 2 * t + Math.PI / 4;
const px = x + Math.cos(angle) * radius;
const py = y + Math.sin(angle) * radius;
points.push([ px, py ]);
}
return points;
};

const rough = (path, opt = {}) => {
const roughness = defined(opt.roughness, 1);
const jitter = defined(opt.jitter, 1);
const spacing = defined(opt.spacing, 0.1);
const closed = opt.closed;
const isSpline = opt.spline;
const tension = defined(opt.tension, 0.5);
const segments = defined(opt.segments, 25);
const dist = opt.dist || ((...args) => Random.gaussian(...args));

const perturbed = path.map(point => {
const p = dist() * jitter;
return vec2.scaleAndAdd([], point, Random.onCircle(), p);
});
const spline = isSpline ? cubicSpline(perturbed, tension, segments, closed) : perturbed;
let points = resampleLineBySpacing(spline, spacing, closed);
points = points.map(point => {
const r = dist() * roughness;
return vec2.scaleAndAdd([], point, Random.onCircle(), r);
});
return points;
};

const path = circle(width / 2, height / 2, width * 0.175, 8);
const lineWidth = 3;
const shapes = [ {
spacing: 15,
jitter: 7,
roughness: 0.5,
dist: () => Random.gaussian(),
spline: true,
segments: 100,
tension: 0.5,
closed: true
}, {
spacing: 15,
jitter: 10,
roughness: 0.75,
dist: () => Random.gaussian(),
spline: true,
segments: 100,
tension: 0.5,
closed: true
} ].map(opts => rough(path, opts));

const backgroundShape = rough(circle(width / 2, height / 2, width * 0.575, 4), {
spacing: 10,
jitter: 10,
roughness: 0.5,
spline: true,
segments: 100,
tension: 0.025,
closed: true
});

// Render the shapes
return ({ time, frame }) => {
context.fillStyle = 'white';
context.lineJoin = 'round';
context.fillRect(0, 0, width, height);

context.beginPath();
backgroundShape.forEach(point => {
context.lineTo(point[0], point[1]);
});
context.closePath();
context.strokeStyle = context.fillStyle = colors.background;
context.fill();

shapes.forEach((points, i) => {
context.lineWidth = lineWidth;
context.beginPath();
points.forEach(point => {
context.lineTo(point[0], point[1]);
});
context.closePath();
const stroke = i > 0;
context.strokeStyle = context.fillStyle = stroke ? colors.pen : colors.foreground;
if (stroke) context.stroke();
else context.fill();
});
};
};

canvasSketch(sketch, settings);
120 changes: 120 additions & 0 deletions examples/canvas-distributions.js
@@ -0,0 +1,120 @@
const canvasSketch = require('canvas-sketch');
const Random = require('./util/random');
const { lerp, clamp, clamp01 } = require('./util/math');
const { vec2 } = require('gl-matrix');

const colors = {
background: '#f4d9be',
foreground: '#ff911c',
pen: '#1975ff'
};

const settings = {
// animation: true,
// When exporting, use the seed as the suffix
// This way we can reproduce it more easily later
animation: true,
dimensions: [ 9, 14 ],
units: 'in',
pixelsPerInch: 300
};

const sketch = ({ context, width, height }) => {
const margin = -1;

const pointCount = 500;
const aspect = width / height;
const points = Array.from(new Array(pointCount)).map((_, i) => {
const t = pointCount <= 1 ? 0.5 : i / (pointCount - 1);
const size = width * 0.45;
const position = vec2.add([], [ width / 2, height / 2 ], Random.onSquare([ aspect * size, 1 * size ]));
// const position = vec2.add([], [ width / 2, height / 2 ], Random.onCircle(2));
// const position = [ lerp(margin, width - margin, t), height / 2 ];
return {
attractionRadius: Random.range(0, 1),
attractionForce: Random.gaussian(0, 0.1),
maxFriends: Random.rangeFloor(0, pointCount),
friends: [],
radius: 0.01 * Random.gaussian(1, 0.1),
speed: Random.gaussian(0.0, 0.025),
velocity: Random.onCircle(),
history: [],
lineWidth: Math.abs(0.01 * Random.gaussian(1, 0.25)),
previous: position.slice(),
newPointThrehold: Math.abs(Random.gaussian(0, 0.0001)),
position
};
});

points.forEach(point => {
const other = Random.shuffleArray(points).filter(p => p !== point);
point.friends = other.slice(0, point.maxFriends);
});

const step = () => {
points.forEach(point => {
const offset = Random.insideCircle(Random.gaussian(0, 0.1));
vec2.add(point.position, point.position, offset);

vec2.scaleAndAdd(point.position, point.position, point.velocity, point.speed);

point.friends.forEach(friend => {
const distance = vec2.distance(friend.position, point.position);
if (distance <= point.attractionRadius) {
const strength = 1 - clamp01(distance / point.attractionRadius);
const force = vec2.sub([], friend.position, point.position);
vec2.normalize(force, force);
vec2.scaleAndAdd(point.velocity, point.velocity, force, point.attractionForce * strength);
}
});

const maxVel = 2;
point.velocity = point.velocity.map(n => clamp(n, -maxVel, maxVel));
vec2.scale(point.velocity, point.velocity, 0.98);

if (vec2.distance(point.position, point.previous) >= point.newPointThrehold) {
point.history.push(point.position.slice());
point.previous = point.position.slice();
}
});
};

const clearing = false;

// Render the shapes
return ({ time, frame }) => {
if (frame === 0 || clearing) {
context.fillStyle = 'white';
context.fillRect(0, 0, width, height);
}
step();

// context.fillStyle = 'white';
// context.fillRect(0, 0, width, height);

points.forEach(point => {
point.history.forEach(history => {
context.beginPath();
context.arc(history[0], history[1], point.radius, 0, Math.PI * 2, false);
context.fillStyle = 'black';
context.fill();
});
});

// points.forEach(point => {
// context.beginPath();
// point.history.forEach(p => context.lineTo(p[0], p[1]));
// context.lineWidth = point.lineWidth;
// context.globalAlpha = 0.5;
// context.stroke();
// // point.history.forEach(history => {
// // context.beginPath();
// // context.arc(history[0], history[1], point.radius, 0, Math.PI * 2, false);
// // context.fillStyle = 'black';
// // context.fill();
// // });
// });
};
};

canvasSketch(sketch, settings);

0 comments on commit aa4cd26

Please sign in to comment.