# 01 · Canvas API (the `ig` commands) Your code runs inside the tool as the body of an `async` function. `ig` is ready to use. Use `await` for commands that load something (`ig.commons`, `ig.icon`, `ig.paint`, `ig.myPhoto`, `ig.svg`, `ig.fx`). Coordinates are in pixels. `(0, 0)` is the top-left corner of the page. The default page is **1080 × 1350**. Everything you draw becomes a separate object that the maker can move, edit and restyle. ## Style: `ig.useStyle(yourChoices)` Start every design with `ig.useStyle`, passing your own palette and fonts. Where the maker fixed something in the tool, her choice replaces yours. Then use only `C.*` and `F.*`, so the tool can redraw the design in another style with one tap. ```js const S = ig.useStyle({ palette: { paper: "#F4EFE6", ink: "#1B1B1B", muted: "#6B675F", accent: "#C8553D", accent2: "#2A7F7F", accent3: "#E9B872", deep: "#1F3B3B" }, fonts: { display: "Fraunces", displayWeight: 700, text: "Source Serif 4", label: "Barlow Condensed", hand: "Caveat" } }); // S also has the tool's current values: const S0 = ig.style; // the tool's ticket const C = S.palette; // colours: paper, ink, muted, accent, accent2, accent3, deep const F = S.fonts; // fonts: display, displayWeight, text, label, hand S.layout.id; S.layout.brief; // the layout to follow (see 05-styles-and-variation.md) S.texture; // "paper" | "newsprint" | "kraft" | "watercolor" | "linen" | "none" S.touches; // list of human touches to include S.seed; // a number for ig.rand(seed) S.dark; // true when the paper is dark ``` ## Page | Command | What it does | |---|---| | `ig.setPage(w, h, color)` | Page size and background. Use the size in the maker's message: 1080 × 1350 portrait (default), 1080 × 1080, 1080 × 2700, 1240 × 1754 or 1920 × 1080. | | `ig.texture(kind, {strength, seed})` | Paper grain over the whole page. `kind` = `S.texture`. Skip it when `S.texture === "none"`. `strength` 0.2–0.5 is subtle. | | `ig.background(fill)` | A full-page rectangle (rarely needed; `setPage` already sets the colour). | ## Shapes | Command | Notes | |---|---| | `ig.rect(x, y, w, h, {fill, stroke, strokeWidth, radius, dash})` | `radius` rounds the corners. `dash: [6, 4]` makes a dashed outline. | | `ig.circle(cx, cy, r, {fill, stroke, strokeWidth, dash})` | Centred at `(cx, cy)`. | | `ig.ellipse(cx, cy, rx, ry, {fill, stroke, strokeWidth})` | | | `ig.polygon([[x, y], …], {fill, stroke, strokeWidth})` | Any closed shape. | | `ig.path("M0 0 L10 10 Q…", {stroke, strokeWidth, fill, dash})` | SVG path data. Use it for curves, hand-drawn circles and wobbly lines. | | `ig.line(x1, y1, x2, y2, {color, width, start, end, dash})` | `start`/`end`: `"none"`, `"arrow"`, `"dot"`, `"bar"`. `dash`: `"solid"`, `"dashed"`, `"dotted"`. The maker can drag the ends. | `fill` can be a colour (`"#E0507A"`) or a gradient: ```js { fill: { angle: 90, stops: [[0, C.accent], [1, C.deep]] } } // linear, 90 = top to bottom { fill: { radial: true, cx: .5, cy: .5, r: .5, stops: [[0, "#fff"], [1, C.paper]] } } ``` ## Text ```js ig.text("Your words", x, y, { font: F.display, size: 72, weight: 700, color: C.ink, width: 600, // give a width to wrap long text in a box; leave it out for one line lineHeight: 1.1, spacing: 0, // spacing = letter spacing in 1/1000 em (e.g. 120 for small capitals) align: "left", // "left" | "center" | "right" (inside the box) anchor: "left", // "center" or "right" moves the x point to the middle / right edge italic: false, angle: 0 }); ``` Use `\n` for a line break. Rules for text: - **Fonts**: only `F.display`, `F.text`, `F.label` and `F.hand` (any Google Font names). At most 3 on one page. - **Sizes** (on a 1080 px page): headline 64–96, big numbers 90–260, section heads 22–30, body 18–24, labels 15–20, sources 13–15. **Never smaller than 14** (13 only for the source line). - Long text needs a `width`. Estimate the height: lines × size × lineHeight. ## Pictures Pictures are strictly limited. Read `04-pictures-and-rules.md`. ```js // a public-domain or CC0 file from Wikimedia Commons, by its exact file name const img = await ig.commons("Haeckel Diatomea.jpg", x, y, { width: 500, // displayed width in px crop: { x: .1, y: .2, w: .6, h: .4 }, // optional, fractions of the original circle: false, // true = round crop fx: { look: "duotone", duo: [C.deep, C.paper], feather: { l: .2, b: .3, t: 0, r: 0 } }, blend: "multiply" // blends the picture into the paper }); // the maker's own photo (they upload and declare it in the tool first) await ig.myPhoto("market-photo", x, y, { width: 400 }); // draw your own picture with code (Canvas 2D). w, h = pixel size of the drawing. await ig.paint(800, 600, (ctx, w, h) => { ctx.fillStyle = C.accent; ctx.beginPath(); ctx.arc(w / 2, h / 2, 200, 0, Math.PI * 2); ctx.fill(); }, { x: 140, y: 400, width: 800 }); ``` `fx` (picture look): `look` = `"none"`, `"pencil"`, `"ink"`, `"duotone"`, `"sepia"`, `"halftone"`, `"riso"`, `"posterize"`, `"bw"`. Other keys: `duo: [darkColor, lightColor]`, `dot` (halftone dot size), `levels` (posterize), `feather: {l, t, r, b}` (soft edges, 0–0.5), `radial` (round vignette, 0–1), `outline: {width, color}`, `bg: {mode: "edge"}` (remove a plain background), `adjust: {brightness, contrast, saturation, warmth, gamma, blur, sharpen, grain}` (−1…1 except gamma). ## Icons, maps, SVG ```js await ig.icon("droplet", x, y, 48, { color: C.ink }); // 5,000 Tabler icon names: heart, school, leaf, map-pin, users, … const map = ig.worldMap(x, y, w, h, { land: "#D9D2C3", border: C.paper, borderWidth: .4, ocean: null, projection: "naturalEarth" }); const [px, py] = map.project(77.2, 28.6); // longitude, latitude → page position await ig.svg("…", x, y, width); // your own SVG drawing ``` `projection`: `"naturalEarth"`, `"equalEarth"` or `"mercator"`. `detail: "50m"` gives finer coastlines. ## Shared options (any command) `opacity` (0–1), `blend` (`"multiply"`, `"screen"`, `"overlay"`), `angle` (degrees), `name` (shown in Layers), `shadow: {color, blur, offsetX, offsetY}`, `glow: {color, blur}`. ## Helpers - `ig.rand(seed)` returns a function that gives the same random numbers every run: `const R = ig.rand(S.seed); R()`. - `ig.page` → `{w, h}` (the size when the code started). - `ig.log("text")` prints a line under the code box. ## Python (optional) The tool also runs Python. The same commands exist as functions: `rect(x, y, w, h, fill=…)`, `text("Hi", x, y, size=40)`, `await commons(title, x, y, width=400)`, `await my_photo(name, x, y)`, `await icon(name, x, y, 48)`, and `style` is the ticket (`style.palette.accent`). `matplotlib` figures can be added with `await add_figure(fig, x, y, width)`. Prefer JavaScript: it is faster and has every command.