APPROACH: I really wanted to create a line that alternates between lines and curves. I got stuck with applying and reapplying matrix transformation with push() and pop(). I ended up using a stack of matrix transformations. I also wanted the animation of watching the line 'walk' be really satisfying so I used p5.func to use several different easing functions. I found that tuning various parameters in the way I transform the matrix between strokes was incredible sensitive and produced several interesting results. LIVE EXAMPLE + CODE
let FUNCS = ['quadraticIn', 'quadraticOut', 'quadraticInOut', 'doubleQuadraticBezier', 'doubleQuadraticSigmoid', 'quadraticBezier', 'quadraticBezierStaircase', 'cubicIn', 'cubicOut', 'cubicInOut', 'brycesCubic', 'cubicBezier', 'cubicBezierThrough2Points', 'doubleCubicOgee', 'doubleCubicOgeeSimplified', 'quarticIn', 'quarticOut', 'quarticInOut', 'generalizedQuartic', 'quinticIn', 'quinticOut', 'quinticInOut'] let MIN_SPEED = 5, MAX_SPEED = 15, UPDATE = 0.1 let context = {} let transforms = [] let e = new p5.Ease() function setup() { createCanvas(windowWidth, windowHeight, SVG) angleMode(DEGREES) stroke(0) strokeWeight(5) updateContext(width/2, height/2) } function draw() { // apply transformations push() for (const [type, vec] of transforms) { switch (type) { case 'translate': translate(vec.x, vec.y); break; case 'rotate': rotate(atan2(vec.y, vec.x)); break; } } // draw line line(...lineargs()) // exit condition if (context.prog >= 1) updateContext(context.width, 0) context.prog = min(1, context.prog + UPDATE * context.speed) pop() } function lineargs() { var val = e[context.easing](context.prog) * context.width return [0, 0, val, 0] } function updateContext(x, y) { context.start = createVector(x, y) if (context.dir == undefined) context.dir = p5.Vector.random2D() else context.dir = createVector(random(-.1, .1), random(1, 4)) // else context.dir = createVector(1, random(-1, 1)) context.speed = random(MIN_SPEED, MAX_SPEED) context.easing = random(FUNCS) context.width = random(random(0,10), random(10, 100)) // context.width = 5 context.prog = 0. transforms.push(['translate', context.start]) transforms.push(['rotate', context.dir]) } function keyPressed() { if (key == 'd') { noLoop() save('plot.svg') loop() } }