The current time is available as s.t, in seconds. To animate a sketch, redraw it each frame with a new time and use s.t to calculate positions, sizes or colours.
A sketch that depends only on its seed, time and canvas size can reproduce any frame. Fix the time to render a still image.
const sketch = (s: SCanvas) => {
s.background(220, 30, 15)
s.setFillColor(45, 90, 60)
s.fill(
new Circle({
at: [0.5 + 0.3 * Math.cos(s.t), 0.5 + 0.3 * Math.sin(s.t)],
r: 0.08,
})
)
}s.oscillate moves smoothly between two values. Set rate to control its speed:
s.oscillate() // between 0 and 1
s.oscillate({ from: 0.1, to: 0.4 }) // between 0.1 and 0.4
s.oscillate({ from: 0, to: 360, rate: 0.5 }) // slower, e.g. for hues.background(0, 0, 12)
s.forHorizontal({ n: 14, margin: 0.1 }, ([x, y], [dX, dY], _c, i) => {
const h = s.oscillate({ from: 0.1, to: 1, rate: 2 + i * 0.15 })
s.setFillColor(170 + i * 8, 80, 60)
s.fill(
new Rect({
at: [x + dX * 0.15, y + (dY * (1 - h)) / 2],
w: dX * 0.7,
h: dY * h,
})
)
})Pass s.t into Perlin noise to create motion that varies smoothly over time:
s.background(210, 50, 12)
s.lineWidth = 0.004
s.times(24, (n) => {
const path = SimplePath.withPoints(
s.build(s.range, { from: 0.05, to: 0.95, n: 30 }, (x) => [
x,
0.5 +
0.35 *
perlin2(x * 2 + s.t * 0.3, n * 0.15 + s.t * 0.1) *
Math.sin(x * Math.PI),
])
)
s.setStrokeColor(150 + n * 5, 70, 60, 0.7)
s.draw(path.chaiken({ n: 2 }))
})The canvas components on this site create an SCanvas with the same seed each frame. Random values stay the same if you make the same calls in the same order. Here, positions stay fixed while radii change with time:
s.background(260, 30, 10)
s.times(80, (n) => {
const at = s.randomPoint() // same every frame (seeded)
const phase = s.random() * Math.PI * 2
const r = 0.01 + 0.03 * Math.abs(Math.sin(s.t * 2 + phase))
s.setFillColor(40 + s.random() * 40, 90, 65, 0.9)
s.fill(new Circle({ at, r }))
})To run your own animation loop, pass the time as the fourth SCanvas constructor argument and redraw with requestAnimationFrame. Creating an instance each frame also resets the random sequence:
import { SCanvas } from "solandra"
const ctx = canvasElement.getContext("2d")!
const size = { width: canvasElement.width, height: canvasElement.height }
const seed = 42
let start: number | undefined
const frame = (ms: number) => {
start ??= ms
const s = new SCanvas(ctx, size, seed, (ms - start) / 1000)
ctx.clearRect(0, 0, size.width, size.height)
sketch(s)
requestAnimationFrame(frame)
}
requestAnimationFrame(frame)StatefulSketch adds an initialState() function and a handleMessage reducer for interactions such as clicks. See the source of the interactive examples.
Solandra was made by James Porter.
Check out the GitHub page or install with npm i solandra