• Stars
    star
    541
  • Rank 82,114 (Top 2 %)
  • Language
    JavaScript
  • License
    The Unlicense
  • Created about 4 years ago
  • Updated 7 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A small and fast alternative (experimental) implementation of p5.js

q5.js

q5.js is a small and fast alternative (experimental) implementation of p5.js, the client-side JS platform for creative expression on the web. q5.js is mostly code-compatible with p5.js, meaning you can simply swap out the library link in an existing sketch and expect it to work with minimal modification. It inherits most of its good stuff from p5.js, though it puts more emphasis on following aspects:

  • lightweight: 33KB minified (p5.min.js 1.1.9 is 800+KB). (Smaller libraries have smaller carbon footprint!)
  • fast: It does so by being a thinner wrapper on Canvas/Web API, skipping parameter validation, and using faster algorithms wherever possible.

Currently, q5.js supports almost all of p5.js's 2D drawing API's, most of its math functionality, and other utilities. It does not support 3D yet; 3D support will likely come as an extension to keep the main library lightweight. It excludes DOM and sound functionalities, though it is mostly compatible with p5.sound.js and p5.dom.js.

To explore supported functionalities, check out these q5 renditions of the standard p5 examples on this page.

q5.js can also be used with the p5 online Web Editor (editor.p5js.org). Example.

Here's a quick sampling of q5.js usage (in case you're not familiar with p5):

new Q5("global"); //initialize q5
// alternatively use `const q=new Q5()` to contain all q5 functions inside a namespace.

// the rest just looks like a regular p5.js sketch:

function draw() {
  background(237, 34, 93);
  fill(0);

  if (mouseIsPressed) {
    ellipse(50, 50, 50, 50);
  } else {
    rect(25, 25, 50, 50);
  }
};

q5.js is currently experimental; Feel free to point out any issues.

Download

⬇︎
    q5.js    
65KB
⬇︎
q5.min.js
33KB

To use, put this line in your HTML:

<script src="q5.min.js"></script>

or via CDN:

<script src="https://cdn.jsdelivr.net/gh/LingDong-/q5xjs/q5.min.js"></script>

Table of Contents

Motivation

After having used many graphics libraries across many different languages, I have found that the Processing/p5.js/Openframeworks system has one huge advantage over others:

It gets stuff drawn onto the screen quick and easy!

This might sound silly, but it actually means a lot for people concerned with creative expression. The easier it is to try different things, the more possibilities you can try (before time and/or patience run out), and the greater the chance that you'll get something nice in the end. Therefore, although you can theoretically achieve the exact same result in any decent graphics system, the tool does matter in practice: You want more time to spend actually working on how your piece looks, instead of spending it on wondering why the computer doesn't work as you intend.

Where I studied computational art, p5.js is taught as "the" framework for the web, and it's been a great introduction. However, due to some of the ways in which p5.js is implemented, I find myself using it less and less as I make more and more projects. Instead I reach directly for the JavaScript/Web API's (which are also well designed enough). I sometimes think of this as shedding the "baby" wheels on the bicycle. But then I miss the artist-centered logic of the p5 interface! I'm now thinking: is there a better way?

To clarify: I think the official p5.js implementation is perfectly justified for its philosophy and suitability for its intended purpose, but my own needs are different enough that I think they justify another implementation instead of pull requests to the official one.

In fact, it is not uncommon for successful software systems to have multiple implementations under one spec (think: compilers of C, implementations of SQL, and engines of JavaScript): The user can choose a backend that best suits their goals or needs. The distinction between the "spec" and the "implementation" is a good idea: when one is using p5.js (or Processing or OpenFrameworks), what one is really using is the same set of commands, the intuitive way of describing drawings, that empowers creative expression. The actual way these commands are implemented internally is incidental; it should be possible to swap internal implementations as necessary.

q5.js aims to:

  • be mostly code-compatible with p5.js.
  • keep being very simple and lightweight.
  • be a very thin wrapper around Canvas/Web API: think of it as a collection of syntactic sugars.
  • be fast.

q5.js does NOT not aim to:

  • replace p5.js.
  • be beginner friendly.
  • simulate completely identical behavior for current and future versions of p5.js.

Key Differences with p5

I. "Namespaced Mode" 🏷️

p5

In p5.js, all p5 functions are in the global namespace, unless you use "instance" mode, like this:

let sketch = function(p) {
  p.setup = function() {
    p.createCanvas(100,100);
  };
  p.draw = function(){
    p.background(0);
  }
};

let myp5 = new p5(sketch);

This does solve the problem of global namespace pollution, but there're still some inconveniences:

  • The extra wrapping of the sketch function makes code look complex. (Flat is better than nested!)
  • Variables inside sketch can no longer be accessed via browser console, which makes it less convenient for debugging.

q5

q5 introduces "namespace" mode in place of global/instance mode:

let q5 = new Q5();

q5.setup = function(){
  q5.createCanvas(100,100);
}

q5.draw = function(){
  q5.background(0);
}

You can call the namespace whatever you like. You can even get multiple instances of q5 running on the same page easily.

let q5 = new Q5();
let q6 = new Q5();

q5.setup = function(){
  q5.background(255);
}

q6.setup = function(){
  q6.background(0);
}

Of course, you can still have the good old global namespacing via Q5("global"), making q5.js mostly code-compatible with existing p5 sketches:

new Q5("global");

function setup(){
  background(0);
}

function draw(){
  
}

II. q5 Functions Anywhere 🌏

p5

In p5.js, most functions can only be used inside setup(), draw() etc. Otherwise, you might see something like this:

Did you just try to use p5.js's stroke() function? If so, you may want to move it 
into your sketch's setup() function.

q5

q5.js functions can be used anywhere, it doesn't really matter!

In fact, you can do away with the setup function all together. Just write your initialization routines at the top level.

For example, you can now directly run examples on p5js.org/reference without wrapping them in setup manually:

new Q5("global");

noStroke();
let c = color(0, 126, 255, 102);
fill(c);
rect(15, 15, 35, 70);

You can even roll out your own animation loop in place of draw(). Good for mixing with other libraries too.

new Q5("global");

fill(255,0,0);

function myLoop(){
  requestAnimationFrame(myLoop);
  rect(15, 15, 35, 70);
}
myLoop();

Though of course the setup() and draw() functions are still there if you need them.

III. HES 🐞

p5

p5.js has a nice feature called Friendly Error System (FES). It makes guesses about what you might have done wrong and put it to you via friendly language.

q5

q5.js does not help with your bad code. It WILL break and/or crash if you feed it the wrong stuff.

IV. No Magic 🎩

p5

p5.js has some pretty smart features. For example, it can parse out a color from your strings like color('hsl(160, 100%, 50%)') or color("lightblue"). Functions behave sightly differently when under different "modes" (e.g. hue), and some have secret default settings. (e.g. arc and text)

q5

q5.js is pretty dumb. It will only do things when you communicate the command to it in the simplest way, and executes them in the most unimaginative way. This means that functions mainly just take numeric inputs (except text() of course), and any behavior needs to be explicitly triggered. You can expect q5 to have almost no overhead between digesting your parameters and putting them into use.

Extra Features

q5.js provides following features that are not in p5.js:

  • randomExponential() in addition to randomGaussian(): a random distribution that resembles exponential decay.
  • curveAlpha(): manipulate the α parameter of Catmull-Rom curves.
  • relRotationX, relRotationY and relRotationZ: Similar to rotationX/Y/Z, but are relative to the orientation of the mobile device.

Using p5 Addons

q5.js is mostly compatible with p5 addons. The only issue is that the addons usually expect a global object called p5 for them to append methods to (among a couple other things), which q5 naturally does not provide.

As a solution, q5 provides a special file called q5.p5acl.js (p5 addon compatibility layer) which you can link to in your HTML before any p5 addons. For example:

<script src="q5.min.js"></script>
<script src="q5.p5acl.js"></script>

<!-- followed by p5 addons -->
<script src="p5.sound.js"></script>
<script src="p5.xyz.js"></script>

After which you'll be able to access functionalities from p5 addons under a global addons object, for example:

let sfx = addons.loadSound("music.mp3");

Benchmarks

q5.js has significant speed advantage in imaging operations because it uses hardware accelerated Canvas API directly whenever possible, instead of going over pixel by pixel. Most other functionalities have very marginal speed improvements (or none at all when parameter validation overhead is negligible). The operations with important performance differences are listed below.

The following benchmarks are generated with Google Chrome 84, on an old-ish Macbook Pro 2015 (with lots of apps and tabs running); Performance varies depending on software and hardware.

p5.js version used is 1.1.9.

Operation on 1024x1024 image p5.js q5.js
tinting 20FPS 35FPS
blurring(11px) 0FPS 40FPS *
thresholding 10FPS 40FPS *
grayscaling 10FPS 50FPS *
inverting 10FPS 50FPS *
opaque 20FPS 60FPS
erode/dilate 5FPS 9FPS
Misc p5.js q5.js
Generating 10,000 randomGaussian() sample 10FPS 20FPS
Calling noiseSeed() 1,000 times 10FPS 60FPS
Generate 10,000 (random) colors with color(r,g,b) 5FPS 60FPS
Rotate a Vector 1,000,000 times 13FPS 60FPS

* Only for browsers that support CanvasRenderingContext2D.filter (75% of all as of Aug 2020, including Chrome, Firefox and Edge). For those that don't, performance is similar to p5.js, as identical implementations are usually used as fallbacks.

Speed is a goal for q5.js, and we would very much like to see the above list grow. If you know how to make something faster, advice/pull requests are very welcome.

More Repositories

1

shan-shui-inf

Procedurally generated Chinese landscape painting.
HTML
5,488
star
2

fishdraw

procedurally generated fish drawings
JavaScript
2,200
star
3

qiji-font

齊伋體 - typeface from Ming Dynasty woodblock printed books
Python
1,296
star
4

rrpl

Describing Chinese Characters with Recursive Radical Packing Language (RRPL)
JavaScript
884
star
5

wax

A tiny programming language that transpiles to C, C++, Java, TypeScript, Python, C#, Swift, Lua and WebAssembly 🚀
C
770
star
6

linedraw

Convert images to vectorized line drawings for plotters.
Python
755
star
7

nonflowers

Procedurally generated paintings of nonexistent flowers.
JavaScript
509
star
8

skeleton-tracing

A new algorithm for retrieving topological skeleton as a set of polylines from binary images
C
497
star
9

cope

A modern IDE for writing classical Chinese poetry 格律诗编辑程序
JavaScript
455
star
10

ndwfc

🌊💥 N-dimensional Wave Function Collapse with infinite canvas
JavaScript
311
star
11

psvg

Programmable Scalable Vector Graphics -- drawings that draw themselves
TypeScript
297
star
12

legumes

🎼 A sheet music to polylines renderer
TypeScript
230
star
13

magic-square-poems

Discovering magic squares in Tang Dynasty poems
C
188
star
14

handpose-facemesh-demos

🎥🤟 8 minimalistic templates for tfjs mediapipe handpose and facemesh
JavaScript
187
star
15

Hermit

A man. A horse. A nature.
Python
168
star
16

chinese-hershey-font

Convert Chinese Characters to Single-Line Fonts using Computer Vision
Python
129
star
17

Processing-Demos-for-The-Pocket-Handbook-of-Image-Processing-Algorithms

Processing Demos made when reading the book *The Pocket Handbook for Image Processing Algorithms in C*
Processing
127
star
18

edges2calligraphy

Using pix2pix to convert scribbles to Chinese calligraphy
JavaScript
115
star
19

tk-fangsong-font

剔骨仿宋: Experimental Fang Song style Chinese font
Python
112
star
20

grand-timeline

Interactive grand unified timeline of 30,800 ancient Chinese people / 古人全表
JavaScript
111
star
21

hfmath

Render LaTeX math with Hershey Fonts
TypeScript
94
star
22

VisionOSC

PoseOSC + FaceOSC + HandOSC + OcrOSC + CatOSC + DogOSC
Objective-C++
88
star
23

wechit

WeChat in Terminal (微信终端版)
Python
88
star
24

wasm-fun

Non-trivial programs in hand-written WebAssembly
WebAssembly
78
star
25

PoseOSC

📹🤸‍♂️🤾‍♀️🤺 PoseNet + OSC: send realtime human pose estimation data to your apps
JavaScript
77
star
26

ci-ren

Generative Chinese poetry
Python
75
star
27

r1b

A thermal-printer-oriented, 1-bit graphics rasterizer for 2D and 3D
C
73
star
28

squiggy

vector brushstroke library
TypeScript
65
star
29

asciimare

3D engine powered by ASCII art
Python
63
star
30

Okb.js

Procedural generation toolkit for Javascript - noises, randomness, curves, and more
HTML
60
star
31

ofxPoissonFill

Poisson filling shader for OpenFrameworks
C++
56
star
32

p5-hershey-js

p5.js Hershey Vector Font Library
JavaScript
53
star
33

pmst

🎨 Poor Man's Style Transfer - Painting an image with the style of another, without machine learning
C++
48
star
34

Loshu.js

A linear algebra library for JavaScript 🔢
JavaScript
47
star
35

zdic-cli

An offline command-line interface to zdic.net dictionary (漢典)
JavaScript
47
star
36

interesting-polygon-archive

Collection of polygon data in various formats for testing computational geometry algorithms.
Processing
46
star
37

ttf2hershey

Convert True Type Fonts (.ttf) to Hershey vector fonts
Python
43
star
38

skeletonization-js

Javascript implementation of image skeletonization
JavaScript
42
star
39

t43

A tiny 3D slicer written from scratch
C
32
star
40

fv

An experimental approach to expressing vector math in js (tagged template literals)
JavaScript
31
star
41

LingDong-

Automatically keep my Github profile README updated with a python script and Github Actions
Python
28
star
42

PContour

Processing/Java library for finding contours in binary images
HTML
28
star
43

srcsnap

screenshot-driven version tracking
JavaScript
22
star
44

dbn.js

Recreation of John Maeda's "Design By Numbers" programming environment in JavaScript
JavaScript
18
star
45

wax4vscode

Extension for the wax programming language in VS Code (highlight + transpile + run)
TypeScript
17
star
46

TrackpadOSC

💻👋✌️👉Send mac's multitouch trackpad read-out through OSC
Objective-C
17
star
47

xcessing

Friendly Processing-like interface to X11/Xlib in C
C
16
star
48

svg2pl

convert svg to polylines
C
15
star
49

lbll

tiny experimental language for limited environments
C
14
star
50

fast-many-face-detection-with-cpp-or-openframeworks-on-mac-using-neural-networks

Fast Many Face Detection with C++/OpenFrameworks on macOS using Neural Networks
C++
14
star
51

galiano-drawing

A procedurally generated drawing
JavaScript
11
star
52

machining-projection-map

JavaScript
8
star
53

avrlass

AVR Lightweight Assembler (and disassembler)
JavaScript
6
star
54

60-212

JavaScript
5
star
55

teapot.lua

1 path tracer written in pure lua, 1 file, 0 dependencies.
Lua
5
star
56

Hello-World

Lorem Ipsum
3
star
57

cvDictUI

opencv-python tool for generating interactive GUI from any python dictionary
Python
3
star
58

lingdong

LingDong's project links
JavaScript
2
star
59

galiano-lidar-render

Semi-realistic rendering of LiDAR data from the entire Galiano Island, BC
C
1
star