A sketch is a function that takes an SCanvas and draws with it. The examples call this argument s or p:
import { SCanvas } from "solandra"
const sketch = (s: SCanvas) => {
s.background(45, 30, 95)
s.setFillColor(220, 70, 40)
s.fill(new Circle({ at: s.meta.center, r: 0.3 }))
}The canvas width is always 1, regardless of its pixel size. Its height is 1 / aspectRatio, so the same sketch can render at different resolutions.
The meta property tells you about the drawing area:
s.meta.top // 0
s.meta.left // 0
s.meta.right // 1
s.meta.bottom // 1 / aspectRatio (1 for a square canvas)
s.meta.center // [0.5, 0.5 / aspectRatio]
s.meta.aspectRatio // width / heightPoints are [x, y] tuples. The origin is at the top left; x increases to the right and y increases downwards.
This example marks the corners, edges and centre:
const { center, bottom, right } = s.meta
s.background(210, 30, 20)
s.lineWidth = 0.005
s.setStrokeColor(0, 0, 90)
s.draw(new Line([0, 0], [right, bottom]))
s.draw(new Line([right, 0], [0, bottom]))
s.setFillColor(20, 90, 60)
s.fill(new Circle({ at: center, r: 0.05 }))
s.setFillColor(50, 90, 60)
const corners = [
[0, 0],
[right, 0],
[right, bottom],
[0, bottom],
]
corners.forEach((at) => {
s.fill(new Circle({ at, r: 0.03 }))
})Pass a shape to s.draw or s.fill. Both accept anything that implements Traceable; see Shapes.
s.draw(shape) strokes the outline with the current stroke colour and line widths.fill(shape) fills the interior with the current fill colour (or gradient)s.background(0, 0, 95)
s.setStrokeColor(220, 80, 30)
s.lineWidth = 0.02
s.draw(new Rect({ at: [0.1, 0.1], w: 0.35, h: 0.35 }))
s.setFillColor(340, 80, 60)
s.fill(new Rect({ at: [0.55, 0.55], w: 0.35, h: 0.35 }))Colours use HSLA: hue (0–360), saturation (0–100), lightness (0–100) and optional alpha (0–1). See Colour for gradients, palettes and mixing.
s.background(45, 20, 95) // hue, saturation, lightness
s.setFillColor(220, 70, 50, 0.5) // ...and optional alpha
s.setStrokeColor(0, 0, 20)The FromSpec variants take a { h, s, l, a } object:
const brand = { h: 175, s: 80, l: 40 }
s.setFillColorFromSpec(brand)
s.backgroundFromSpec({ h: 45, s: 20, l: 95 })Line width uses canvas units: 0.01 is 1% of the canvas width. You can also set caps, joins and dashes:
s.background(0, 0, 15)
s.setStrokeColor(45, 90, 70)
s.lineWidth = 0.02
s.lineStyle = { cap: "round" }
s.draw(new Line([0.1, 0.2], [0.9, 0.2]))
s.lineStyle = { cap: "butt" }
s.draw(new Line([0.1, 0.4], [0.9, 0.4]))
s.dash = { pattern: [0.04, 0.02] }
s.draw(new Line([0.1, 0.6], [0.9, 0.6]))
s.dash = { pattern: [0.005, 0.02] }
s.lineStyle = { cap: "round" }
s.draw(new Line([0.1, 0.8], [0.9, 0.8]))Dash lengths use canvas units, not pixels.
Set a shadow with shadow and remove it with clearShadow. Blur and offsets use canvas units:
s.background(210, 20, 95)
s.shadow = {
size: 0.03,
dX: 0.01,
dY: 0.02,
color: { h: 210, s: 40, l: 30, a: 0.6 },
}
s.setFillColor(340, 70, 55)
s.fill(new Star({ at: [0.35, 0.4], r: 0.2, n: 5 }))
s.clearShadow()
s.setFillColor(220, 70, 55)
s.fill(new Circle({ at: [0.7, 0.65], r: 0.15 }))s.inDrawing(point) checks whether a point is inside the canvas. Use it to stop a random walk at the edge:
s.background(0, 0, 10)
s.lineWidth = 0.005
s.times(20, (n) => {
s.setStrokeColor(180 + n * 6, 80, 60, 0.8)
const path = SimplePath.startAt(s.meta.center)
let pt = s.meta.center
while (s.inDrawing(pt)) {
pt = s.perturb({ at: pt, magnitude: 0.1 })
path.addPoint(pt)
}
s.draw(path.chaiken({ n: 2 }))
})draw and fillSolandra was made by James Porter.
Check out the GitHub page or install with npm i solandra