q5 2.18.1 → 2.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  ## Visit [q5js.org](https://q5js.org)! 🌟
4
4
 
5
- [q5.js](https://q5js.org) is a spiritual successor to the [p5.js][] and [Processing Java][] graphics libraries.
5
+ [q5.js](https://q5js.org) is a sequel to the [p5.js][] and [Processing Java][] graphics libraries.
6
6
 
7
7
  - performance optimized for interactive art 🚀
8
8
  - includes a brand new renderer powered by WebGPU 💪
9
9
  - up to 32x faster than p5.js 🏎️
10
- - HDR color support 🌈
10
+ - beginner friendly API and documentation 📚
11
11
  - compatible with popular addons, including [p5.sound][] and [p5play][] 🎮
12
- - no dependencies, less than 100kb minified 📦
12
+ - no dependencies, ~100kb minified 📦
13
13
  - LGPL licensed (just like p5.js) 🆓
14
14
 
15
15
  q5.js was designed to make creative coding fun and accessible for a new generation of artists, designers, educators, and beginners. 🤝
package/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@q5/q5",
3
- "version": "2.18.1",
3
+ "version": "2.19.0",
4
4
  "license": "LGPL-3.0",
5
5
  "description": "A sequel to p5.js that's optimized for interactive art",
6
6
  "author": "quinton-ashley",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "q5",
3
- "version": "2.18.1",
3
+ "version": "2.19.0",
4
4
  "description": "A sequel to p5.js that's optimized for interactive art",
5
5
  "author": "quinton-ashley",
6
6
  "contributors": [
package/q5.d.ts CHANGED
@@ -293,18 +293,19 @@ function draw() {
293
293
  /** ⭐️
294
294
  * Creates an instance of Q5.
295
295
  *
296
- * Running `new Q5()` enables the use of q5 functions and variables
297
- * anywhere in your code. You can also start Q5 in global mode by
298
- * running [`createCanvas`](https://q5js.org/learn/#createCanvas).
296
+ * Running `new Q5()` enables use of q5 functions and variables
297
+ * anywhere in your sketch. You can also start Q5 in global
298
+ * mode by running [`createCanvas`](https://q5js.org/learn/#createCanvas).
299
299
  *
300
- * By default q5 uses the CanvasRenderingContext2D based c2d renderer.
300
+ * By default q5 uses the CanvasRenderingContext2D (aka Canvas2D)
301
+ * based c2d renderer.
301
302
  *
302
- * To use the q5 WebGPU renderer, run `Q5.webgpu()` after the creation of file level variables. For more information read the [q5-webgpu modules documentation](https://github.com/q5js/q5.js/blob/main/src/readme.md#webgpu-canvas).
303
+ * To use the [q5 WebGPU renderer](https://github.com/q5js/q5.js/wiki/q5-WebGPU-renderer), run `Q5.webgpu()` after the creation of file level variables.
303
304
  * @param {string | Function} [scope]
304
305
  * - "global": (default) top-level global mode, adds q5 functions
305
306
  * and variables to the global scope
306
307
  * - "auto": if users don't create a new instance of Q5 themselves, an instance will be created automatically with this scope, which replicates p5's global mode
307
- * - "instance": enables users to [assign a Q5 instance to a variable](https://github.com/q5js/q5.js/wiki/Instance-Mode), not to the global scope
308
+ * - "instance": enables users to [assign a Q5 instance to a variable](https://github.com/q5js/q5.js/wiki/Instance-Mode)
308
309
  * @param {HTMLElement} [parent] element that the canvas will be placed inside
309
310
  * @example
310
311
  new Q5();
@@ -823,12 +824,12 @@ rect(20, 20, 60, 60);
823
824
  /** 💻
824
825
  * Customize how your canvas is presented.
825
826
  * @param {string} mode
826
- * - "normal": (default) no styling to canvas or its parent element
827
- * - "centered": canvas will be centered horizontally and vertically within its parent and if the window is smaller than the canvas, the canvas will be resized to avoid clipping
828
- * - "maxed": canvas will fill the parent element, with letterboxing if necessary to preserve its aspect ratio
827
+ * - "normal": (default) canvas is not repositioned
828
+ * - "centered": canvas is moved to the center of its parent
829
+ * - "maxed": canvas will be scaled to fill the parent element, with letterboxing if necessary to preserve its aspect ratio
829
830
  * @param {string} renderQuality
830
- * - "smooth": (default) no change to the default render quality
831
- * - "pixelated": runs `pixelDensity(1)` and `noSmooth()` then sets the canvas CSS styles `image-rendering: pixelated` and `font-smooth: never`
831
+ * - "smooth": (default) smooth upscaling if the canvas is scaled
832
+ * - "pixelated": pixels rendered as sharp squares
832
833
  * @param {number} scale can also be given as a string (for example "x2")
833
834
  * @example
834
835
  createCanvas(50, 25);
@@ -1019,17 +1020,22 @@ point(125, 50);
1019
1020
  function curveTightness(val: number): void;
1020
1021
 
1021
1022
  /** 🧑‍🎨
1022
- * Starts recording vertices for a shape.
1023
+ * Starts storing vertices for a convex shape.
1023
1024
  */
1024
1025
  function beginShape(): void;
1025
1026
 
1026
1027
  /** 🧑‍🎨
1027
- * Starts recording vertices for a shape to be used as a contour.
1028
+ * Ends storing vertices for a convex shape.
1029
+ */
1030
+ function endShape(): void;
1031
+
1032
+ /** 🧑‍🎨
1033
+ * Starts storing vertices for a contour.
1028
1034
  */
1029
1035
  function beginContour(): void;
1030
1036
 
1031
1037
  /** 🧑‍🎨
1032
- * Ends recording vertices for a shape.
1038
+ * Ends storing vertices for a contour.
1033
1039
  */
1034
1040
  function endContour(): void;
1035
1041
 
@@ -1131,13 +1137,15 @@ point(125, 50);
1131
1137
 
1132
1138
  // 📑 dom
1133
1139
 
1140
+ /** 📑
1141
+ * The Document Object Model (DOM) is an interface for
1142
+ * creating and editing web pages with JavaScript.
1143
+ */
1144
+
1134
1145
  /** 📑
1135
1146
  * Creates a new HTML element and adds it to the page. `createEl` is
1136
1147
  * an alias.
1137
1148
  *
1138
- * The element is part of the DOM (Document Object Model), an interface for
1139
- * creating and editing web pages with JavaScript.
1140
- *
1141
1149
  * Modify the element's CSS [`style`](https://developer.mozilla.org/docs/Web/API/HTMLElement/style) to change its appearance.
1142
1150
  *
1143
1151
  * Use [`addEventListener`](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) to respond to events such as:
@@ -1255,6 +1263,9 @@ let img = createImg('/assets/p5play_logo.webp')
1255
1263
  *
1256
1264
  * Use the `value` property to get or set the input's value.
1257
1265
  *
1266
+ * Use the `placeholder` property to set label text that appears
1267
+ * inside the input when it's empty.
1268
+ *
1258
1269
  * See MDN's [input documentation](https://developer.mozilla.org/docs/Web/HTML/Element/input#input_types) for the full list of input types.
1259
1270
  * @param {string} [value] initial value
1260
1271
  * @param {string} [type] text input type, can be 'text', 'password', 'email', 'number', 'range', 'search', 'tel', 'url'
@@ -1552,14 +1563,6 @@ function setup() {
1552
1563
  */
1553
1564
  function mask(img: Image): void;
1554
1565
 
1555
- /** 🌆
1556
- * Saves the image.
1557
- * @param {string} filename filename or url
1558
- * @param {string} extension file extension
1559
- * @param {number} [quality] quality of the saved image
1560
- */
1561
- function save(filename: string, extension: string, quality?: number): void;
1562
-
1563
1566
  /** 🌆
1564
1567
  * Retrieves a subsection of an image or canvas, as a q5 Image.
1565
1568
  * Or if width and height are both 1, returns the color of the pixel at the given coordinates in `[R, G, B, A]` array format.
@@ -1595,7 +1598,7 @@ createCanvas(200);
1595
1598
  let c = color('lime');
1596
1599
 
1597
1600
  function draw() {
1598
- set(random(width), random(height), c);
1601
+ set(randomX(), randomY(), c);
1599
1602
  updatePixels();
1600
1603
  }
1601
1604
  */
@@ -1781,9 +1784,9 @@ text(info, 12, 30, 20, 6);
1781
1784
  *
1782
1785
  * In q5 WebGPU, fonts must be in MSDF format with the file ending
1783
1786
  * "-msdf.json". If no font is loaded before `text` is run, then
1784
- * the default font, Microsoft YaHei, is loaded:
1785
- * https://q5js.org/fonts/YaHei-msdf.json
1786
- * https://q5js.org/fonts/YaHei.png
1787
+ * the default sans serif font, Microsoft YaHei, is loaded:
1788
+ * https://q5js.org/fonts/sans-serif-msdf.json
1789
+ * https://q5js.org/fonts/sans-serif.png
1787
1790
  * @param {string} url uRL of the font to load
1788
1791
  * @param {(font: FontFace) => void} [cb] optional callback function that receives the font name as an argument once the font is loaded
1789
1792
  * @returns {FontFace} font
@@ -1929,16 +1932,40 @@ createCanvas(200);
1929
1932
  * @param {number} [wrapWidth] maximum line width in characters
1930
1933
  * @param {number} [lineLimit] maximum number of lines
1931
1934
  * @returns {Q5.Image} an image object representing the rendered text
1935
+ * @example
1936
+ createCanvas(200, 200);
1937
+ textSize(80);
1938
+ let img = createTextImage('🐶');
1939
+ img.filter(INVERT);
1940
+
1941
+ function draw() {
1942
+ background(200);
1943
+ text('🐶', 10, 75);
1944
+ image(img, 110, 75);
1945
+ }
1932
1946
  */
1933
1947
  function createTextImage(str: string, wrapWidth: number, lineLimit: number): Q5.Image;
1934
1948
 
1935
1949
  /** ✍️
1936
- * Renders an image generated from text onto the canvas. The
1937
- * positioning of the image is affected by the current text
1950
+ * Renders an image generated from text onto the canvas.
1951
+ *
1952
+ * The positioning of the image is affected by the current text
1938
1953
  * alignment and baseline settings.
1939
- * @param {HTMLImageElement} img image object to render, typically generated from text
1954
+ *
1955
+ * If the first parameter is a string, an image of the text is
1956
+ * created automatically, then drawn.
1957
+ * @param {Q5.Image} img image object or text
1940
1958
  * @param {number} x x-coordinate where the image should be placed
1941
1959
  * @param {number} y y-coordinate where the image should be placed
1960
+ * @example
1961
+ createCanvas(200, 200);
1962
+ textSize(80);
1963
+ textAlign(CENTER, CENTER);
1964
+
1965
+ function draw() {
1966
+ background(200);
1967
+ textImage('🐶', 100, 100);
1968
+ }
1942
1969
  */
1943
1970
  function textImage(img: HTMLImageElement, x: number, y: number): void;
1944
1971
 
@@ -1950,6 +1977,12 @@ createCanvas(200);
1950
1977
  * @param {number} l minimum number of digits to appear before the decimal point; the number is padded with zeros if necessary
1951
1978
  * @param {number} r number of digits to appear after the decimal point
1952
1979
  * @returns {string} a string representation of the number, formatted accordingly
1980
+ * @example
1981
+ createCanvas(200, 100);
1982
+ background(200);
1983
+
1984
+ textSize(32);
1985
+ text(nf(PI, 4, 2), 10, 60);
1953
1986
  */
1954
1987
  function nf(n: number, l: number, r: number): string;
1955
1988
 
@@ -2104,17 +2137,15 @@ rect(100, 0, 100, 200);
2104
2137
  * RGB colors have components `r`/`red`, `g`/`green`, `b`/`blue`,
2105
2138
  * and `a`/`alpha`.
2106
2139
  *
2107
- * RGB is the default color mode.
2108
- *
2109
- * By default when a canvas is using the `display-p3` color space,
2140
+ * By default when a canvas is using the HDR `display-p3` color space,
2110
2141
  * rgb colors are mapped to the full P3 gamut, even when they use the
2111
- * legacy integer format.
2142
+ * legacy integer 0-255 format.
2112
2143
  * @example
2113
- createCanvas(200);
2144
+ createCanvas(200, 100);
2114
2145
 
2115
- function setup() {
2116
- background(255, 0, 0);
2117
- }
2146
+ colorMode(RGB, 255);
2147
+
2148
+ background(255, 0, 0);
2118
2149
  */
2119
2150
  const RGB: 'rgb';
2120
2151
 
@@ -2125,13 +2156,11 @@ function setup() {
2125
2156
  * example, note that full red appears less saturated, as it would
2126
2157
  * on an SDR display.
2127
2158
  * @example
2128
- createCanvas(200);
2159
+ createCanvas(200, 100);
2129
2160
 
2130
2161
  colorMode(SRGB, 255);
2131
2162
 
2132
- function setup() {
2133
- background(255, 0, 0);
2134
- }
2163
+ background(255, 0, 0);
2135
2164
  */
2136
2165
  const SRGB: 'srgb';
2137
2166
 
@@ -2224,6 +2253,24 @@ function draw() {
2224
2253
  */
2225
2254
  let mouseIsPressed: boolean;
2226
2255
 
2256
+ /** 🖲️
2257
+ * Define this function to respond to mouse events immediately.
2258
+ *
2259
+ * There can be a delay of up to one frame between a mouse event
2260
+ * and the next time the `draw` function is run.
2261
+ *
2262
+ * Useful for playing sounds.
2263
+ * @example
2264
+ createCanvas(200, 100);
2265
+
2266
+ let gray = 100;
2267
+ function mousePressed() {
2268
+ background(gray);
2269
+ gray += 10;
2270
+ }
2271
+ */
2272
+ function mousePressed(): void;
2273
+
2227
2274
  /** 🖲️
2228
2275
  * The name of the last key pressed.
2229
2276
  * @example
@@ -2260,6 +2307,24 @@ function draw() {
2260
2307
  */
2261
2308
  function keyIsDown(key: string): boolean;
2262
2309
 
2310
+ /** 🖲️
2311
+ * Define this function to respond to key press events immediately.
2312
+ *
2313
+ * There can be a delay of up to one frame between a key press event
2314
+ * and the next time the `draw` function is run.
2315
+ *
2316
+ * Useful for playing sounds.
2317
+ * @example
2318
+ createCanvas(200, 100);
2319
+
2320
+ let gray = 100;
2321
+ function keyPressed() {
2322
+ background(gray);
2323
+ gray += 10;
2324
+ }
2325
+ */
2326
+ function keyPressed(): void;
2327
+
2263
2328
  /** 🖲️
2264
2329
  * Array of current touches, each touch being an object with
2265
2330
  * id, x, and y properties.
@@ -2271,19 +2336,53 @@ function draw() {
2271
2336
  * If an image is provided, optional x and y coordinates can
2272
2337
  * specify the active point of the cursor.
2273
2338
  * @param {string} name name of the cursor or the url to an image
2274
- * @param {number} [x] x-coordinate of the cursor's hot spot
2275
- * @param {number} [y] y-coordinate of the cursor's hot spot
2339
+ * @param {number} [x] x-coordinate of the cursor's point
2340
+ * @param {number} [y] y-coordinate of the cursor's point
2341
+ * @example
2342
+ createCanvas(200, 100);
2343
+ cursor('pointer');
2276
2344
  */
2277
2345
  function cursor(name: string, x?: number, y?: number): void;
2278
2346
 
2279
2347
  /** 🖲️
2280
2348
  * Hides the cursor within the bounds of the canvas.
2281
2349
  * @example
2282
- createCanvas(200);
2350
+ createCanvas(200, 100);
2283
2351
  noCursor();
2284
2352
  */
2285
2353
  function noCursor(): void;
2286
2354
 
2355
+ /** 🖲️
2356
+ * Prevents mouse wheel events from propagating and causing
2357
+ * the page to scroll when the mouse is inside the canvas.
2358
+ *
2359
+ * Useful for games and interactive art that fill the screen.
2360
+ * @example
2361
+ createCanvas(200, 100);
2362
+ noScroll();
2363
+ */
2364
+ function noScroll(): void;
2365
+
2366
+ /** 🖲️
2367
+ * Define this function to respond to mouse wheel events.
2368
+ *
2369
+ * `event.deltaX` and `event.deltaY` are the horizontal and vertical
2370
+ * scroll amounts, respectively.
2371
+ *
2372
+ * Return false to prevent the default behavior of scrolling the page.
2373
+ * @example
2374
+ let x = y = 100;
2375
+ function draw() {
2376
+ circle(x, y, 10);
2377
+ }
2378
+ function mouseWheel(e) {
2379
+ x += e.deltaX;
2380
+ y += e.deltaY;
2381
+ return false;
2382
+ }
2383
+ */
2384
+ function mouseWheel(event: any): void;
2385
+
2287
2386
  /** 🖲️
2288
2387
  * Requests that the pointer be locked to the document body, hiding the cursor and allowing for unlimited movement.
2289
2388
  */
@@ -2296,6 +2395,60 @@ noCursor();
2296
2395
 
2297
2396
  // 🧮 math
2298
2397
 
2398
+ /** 🧮
2399
+ * Generates random numbers. If no arguments are provided, returns a random number between 0 and 1.
2400
+ * If one number argument is provided, returns a random number between 0 and the provided value.
2401
+ * If two number arguments are provided, returns a random number between the two values.
2402
+ * If an array is provided, returns a random element from the array.
2403
+ * @param {number | any[]} [low] lower bound (inclusive) or an array
2404
+ * @param {number} [high] upper bound (exclusive)
2405
+ * @returns {number | any} a random number or element
2406
+ * @example
2407
+ createCanvas(200);
2408
+ background(200);
2409
+ frameRate(5);
2410
+
2411
+ function draw() {
2412
+ circle(100, 100, random(200));
2413
+ }
2414
+ */
2415
+ function random(low?: number | any[], high?: number): number | any;
2416
+
2417
+ /** 🧮
2418
+ * Generates a random number within the range of the canvas width.
2419
+ * @param {number} [margin] distance to extend (positive) or contract (negative) the range from canvas edges
2420
+ * @returns {number} random x value
2421
+ * @example
2422
+ createCanvas(200, 100);
2423
+ background(200);
2424
+
2425
+ function draw() {
2426
+ circle(randomX(), 50, random(50));
2427
+ }
2428
+ */
2429
+ function randomX(margin?: number): number;
2430
+
2431
+ /** 🧮
2432
+ * Generates a random number within the range of the canvas height.
2433
+ * @param {number} [margin] distance to extend (positive) or contract (negative) the range from canvas edges
2434
+ * @returns {number} random y value
2435
+ * @example
2436
+ createCanvas(200);
2437
+ background(200);
2438
+
2439
+ function draw() {
2440
+ circle(100, randomY(), random(50));
2441
+ }
2442
+ * @example
2443
+ createCanvas(200);
2444
+ background(200);
2445
+
2446
+ function draw() {
2447
+ circle(randomX(), randomY(-60), 10);
2448
+ }
2449
+ */
2450
+ function randomY(margin?: number): number;
2451
+
2299
2452
  /** 🧮
2300
2453
  * Calculates the distance between two points.
2301
2454
  *
@@ -2305,6 +2458,15 @@ noCursor();
2305
2458
  * @param {number} x2 x-coordinate of the second point
2306
2459
  * @param {number} y2 y-coordinate of the second point
2307
2460
  * @returns {number} distance between the points
2461
+ * @example
2462
+ function draw() {
2463
+ background(200);
2464
+ circle(100, 100, 20);
2465
+ circle(mouseX, mouseY, 20);
2466
+
2467
+ let d = dist(100, 100, mouseX, mouseY);
2468
+ text(round(d), 20, 20);
2469
+ }
2308
2470
  */
2309
2471
  function dist(x1: number, y1: number, x2: number, y2: number): number;
2310
2472
 
@@ -2386,17 +2548,6 @@ noCursor();
2386
2548
  */
2387
2549
  function randomSeed(seed: number): void;
2388
2550
 
2389
- /** 🧮
2390
- * Generates random numbers. If no arguments are provided, returns a random number between 0 and 1.
2391
- * If one number argument is provided, returns a random number between 0 and the provided value.
2392
- * If two number arguments are provided, returns a random number between the two values.
2393
- * If an array is provided, returns a random element from the array.
2394
- * @param {number | any[]} [a] lower bound (inclusive) or an array
2395
- * @param {number} [b] upper bound (exclusive)
2396
- * @returns {number | any} a random number or element
2397
- */
2398
- function random(a?: number | any[], b?: number): number | any;
2399
-
2400
2551
  /** 🧮
2401
2552
  * Sets the random number generation method.
2402
2553
  * @param {any} method method to use for random number generation
@@ -2419,25 +2570,34 @@ noCursor();
2419
2570
 
2420
2571
  /** 🧮
2421
2572
  * Sets the noise generation mode.
2573
+ *
2574
+ * Only the default mode, "perlin", is included in q5.js. Use of the
2575
+ * other modes requires the q5-noiser module.
2422
2576
  * @param {'perlin' | 'simplex' | 'blocky'} mode noise generation mode
2423
2577
  */
2424
2578
  function noiseMode(mode: 'perlin' | 'simplex' | 'blocky'): void;
2425
2579
 
2426
- /** 🧮
2427
- * Sets the seed value for noise generation.
2428
- * @param {number} seed seed value
2429
- */
2430
- function noiseSeed(seed: number): void;
2431
-
2432
2580
  /** 🧮
2433
2581
  * Generates a noise value based on the x, y, and z inputs.
2434
2582
  * @param {number} [x] x-coordinate input
2435
2583
  * @param {number} [y] y-coordinate input
2436
2584
  * @param {number} [z] z-coordinate input
2437
2585
  * @returns {number} a noise value
2586
+ * @example
2587
+ function draw() {
2588
+ background(200);
2589
+ let n = noise(frameCount * 0.01);
2590
+ square(n * 200, n * 200, 10);
2591
+ }
2438
2592
  */
2439
2593
  function noise(x?: number, y?: number, z?: number): number;
2440
2594
 
2595
+ /** 🧮
2596
+ * Sets the seed value for noise generation.
2597
+ * @param {number} seed seed value
2598
+ */
2599
+ function noiseSeed(seed: number): void;
2600
+
2441
2601
  /** 🧮
2442
2602
  * Sets the level of detail for noise generation.
2443
2603
  * @param {number} lod level of detail (number of octaves)
@@ -2466,23 +2626,29 @@ noCursor();
2466
2626
  // 🎞️ record
2467
2627
 
2468
2628
  /** 🎞️
2469
- * Creates a recorder. Simply hit record to start recording!
2629
+ * q5.js has a built-in canvas recorder powered by
2630
+ * [`MediaRecorder`](https://developer.mozilla.org/docs/Web/API/MediaRecorder/MediaRecorder). It provides a good balance between
2631
+ * video encoding speed, quality, and file size.
2470
2632
  *
2471
2633
  * Recording large canvases is an intensive process, so your
2472
2634
  * computer may not be able to do it in real time. That's okay,
2473
2635
  * the resulting video will playback at your sketch's target
2474
- * frame rate.
2636
+ * frame rate. But if real time interaction while recording is a
2637
+ * priority, consider reducing the canvas' size, frame rate, and/or
2638
+ * recording quality.
2639
+ *
2640
+ * HDR video encoding is not yet supported by any web browser.
2641
+ * For that and other advanced features, consider using
2642
+ * a screen capture tool like [OBS Studio](https://obsproject.com).
2643
+ */
2644
+
2645
+ /** 🎞️
2646
+ * Creates a recorder. Simply hit record to start recording!
2475
2647
  *
2476
- * In cases where real time interaction is a priority, consider
2477
- * reducing the canvas' size, frame rate, and/or recording
2478
- * quality.
2648
+ * `quality` is set to "high" by default.
2479
2649
  *
2480
- * `format` and `quality` properties are set
2481
- * automatically based on the height of the canvas. They can be
2482
- * changed via the UI or programmatically.
2650
+ * `format` is set automatically based on the height of the canvas.
2483
2651
  *
2484
- * The recorder uses the [`MediaRecorder`](https://developer.mozilla.org/docs/Web/API/MediaRecorder/MediaRecorder) API, which
2485
- * unfortunately can't encode HDR video.
2486
2652
  * @returns {HTMLElement} a recorder, q5 DOM element
2487
2653
  * @example
2488
2654
  createCanvas(200);
@@ -2490,7 +2656,7 @@ createCanvas(200);
2490
2656
  createRecorder();
2491
2657
 
2492
2658
  function draw() {
2493
- circle(mouseX, random(canvas.h), 10);
2659
+ circle(mouseX, randomY(), 10);
2494
2660
  }
2495
2661
  */
2496
2662
  function createRecorder(): HTMLElement;
@@ -2517,7 +2683,7 @@ function draw() {
2517
2683
  * @param {string} fileName
2518
2684
  * @example
2519
2685
  function draw() {
2520
- square(mouseX, random(canvas.h), 10);
2686
+ square(mouseX, randomY(), 10);
2521
2687
  }
2522
2688
 
2523
2689
  function mousePressed() {
@@ -2535,8 +2701,15 @@ function mousePressed() {
2535
2701
  // 🔊 sound
2536
2702
 
2537
2703
  /** 🔊
2538
- * Loads audio data from a file and returns a `Q5.Sound` object that
2539
- * provides low latency sound mixing powered by WebAudio.
2704
+ * q5.js includes low latency sound playback and basic mixing powered
2705
+ * by WebAudio.
2706
+ *
2707
+ * For audio filtering, synthesis, and analysis, consider using
2708
+ * [p5.sound](https://p5js.org/reference/p5.sound/).
2709
+ */
2710
+
2711
+ /** 🔊
2712
+ * Loads audio data from a file and returns a `Q5.Sound` object.
2540
2713
  *
2541
2714
  * Use functions like `play`, `pause`, and `stop` to
2542
2715
  * control playback. Note that sounds can only be played after the
@@ -2705,6 +2878,37 @@ q.mousePressed = () => {
2705
2878
  */
2706
2879
  function load(...urls: string[]): Promise<any[]>;
2707
2880
 
2881
+ /** 🛠️
2882
+ * Saves data to a file.
2883
+ *
2884
+ * If data is not specified, the canvas will be saved.
2885
+ *
2886
+ * If no arguments are provided, the canvas will be saved as
2887
+ * an image file named "untitled.png".
2888
+ * @param {object} [data] canvas, image, or JS object
2889
+ * @param {string} [filename] filename or url
2890
+ * @param {string} [extension] file extension
2891
+ * @example
2892
+ createCanvas(200);
2893
+ background(200);
2894
+ circle(100, 100, 50);
2895
+
2896
+ function mousePressed() {
2897
+ save('circle.png');
2898
+ }
2899
+ * @example
2900
+ createCanvas(200);
2901
+
2902
+ textSize(180);
2903
+ let bolt = createTextImage('⚡️');
2904
+ image(bolt, 16, -56);
2905
+
2906
+ function mousePressed() {
2907
+ save(bolt, 'bolt.png');
2908
+ }
2909
+ */
2910
+ function save(data: object, filename?: string, extension?: string): void;
2911
+
2708
2912
  /** 🛠️
2709
2913
  * Loads a text file from the specified url. Result is one string.
2710
2914
  * @param {string} url text file