Creative code real-time visuals in JavaScript or TypeScript.
- Designed with the aim to be user-friendly, fast, and extensible.
- Inspired by Processing, Nannou, and other creative coding frameworks.
- Rust-based engine powered by Deno Core, a secure, sandboxed JavaScript runtime.
- Is the core engine for the new version of Visor VJ (unreleased).
Visor is still very early in development. The APIs are minimal, likely to change, and documentation is sparse. Please keep this in mind if you use it!
If you think of a feature request, notice any bugs, or have any other feedback, please feel free to submit an issue on Github, or chat on Matrix.
The following illustrates a simple Visor sketch:
const draw = createDraw();
export function setup() {
console.log("Hello, world!");
}
export function update() {
draw.clear();
for (let i = -5; i <= 5; i++) {
const x = i * 50;
const y = Math.sin(time() + i) * 50;
const hue = map(x, -250, 250, 0, 1);
const color = hsv(hue, 0.8, 1);
draw.ellipse().xy(x, y).wh(25, 25).fill(color);
}
}And the corresponding visuals:
More examples can be found in the examples folder.
The recommended way to run Visor sketches is with the visor_cli command line interface. At this time, it is only available through cargo, which means you must have Rust installed. Follow the instructions here to install Rust.
With Rust installed, you can install visor_cli using cargo:
cargo install visor_cliNow, to run a sketch:
visor_cli run ~/path/to/sketch.jsIf you clone this repository onto your machine, you can run the examples directly:
visor_cli run ~/path/to/visor/examples/hello-world.jsUse the --help flag to learn more about the visor_cli options or sub-commands:
visor_cli --help
visor_cli run --helpYou can use the --watch flag with visor_cli to detect saved changes to a sketch file and hot reload it. E.g:
visor_cli run ~/path/to/sketch.js --watchTo best make use of TypeScript in your sketches you can use the the Visor type declarations. These can be generated with visor_cli by running:
visor_cli types ~/output/path/for/visor-types.d.tsYou can then reference these types in your TypeScript code. The recommended development environent for working on Visor sketches is Deno. Follow the instructions here to install Deno.
If you are using Visual Studio Code, you can also use the Deno extension to make use of the Deno language server.
With Deno installed, you can create a deno.json file in your sketch folder to configure the types correctly:
{
"compilerOptions": {
"lib": ["deno.ns"],
"types": ["./visor-types.d.ts"]
}
}Please note that none of the Deno standard libraries (such as fetch) are available with Visor by default. Specifying lib in your deno.json like above configures your type checker to understand this.
The Visor engine is powered by Deno Core, which underpins the Deno JavaScript runtime. For Visor, this means the user can sketch in JavaScript or TypeScript, depsite the engine itself being written in Rust. This makes the engine both fast and reliable, while enabling user-friendly creative coding.
Graphics rendering is enabled by using a mix of APIs from the Nannou creative coding framework and the underlying wgpu graphics API. Windowing is supported by the TAO library.
| Crate | Description |
|---|---|
visor_cli |
Command line interface for running Visor sketches. |
visor_core |
Re-exports visor_engine and all of the core plugins. |
visor_engine |
The Visor engine. |
visor_plugin_draw |
Plugin for drawing shapes. |
visor_plugin_log |
Plugin for console logging. |
visor_plugin_math |
Plugin for useful math functions. |
visor_plugin_midi |
Plugin for connecting to MIDI devices and loading mappings. |
visor_plugin_state |
Plugin for persistent sketch state when hot reloading. |
visor_plugin_time |
Plugin for time and frame related functions. |
The Visor engine can be called from a Rust program. To see how this works, check out the implementation of visor_cli in the source code. Note that you must provide your own event loop and windows using TAO.
Plugins are the best way to extend Visor with your own APIs. Plugins are written in both Rust and JavaScript or TypeScript. Check out the counter_plugin as an example, or look at the core plugins within the crates folder.
Plugins can be built statically into a Rust app that uses the Visor engine, or they can be linked at runtime after building them as dynamic libraries e.g: cdylib. The latter enables custom plugins to be loaded into the visor_cli by passing their paths to the --plugins option.
This project is still in early stages and is not ready for code contributions yet. However, hearing your feedback and support is very welcome! The best way to contribute is through feature requests, bug reports, and general feedback. Please feel free to submit an issue on Github, or chat on Matrix. You are also welcome to share anything cool you've made with Visor. ✨
This project would not be possible without the hard work and dedication of many amazing open source projects. Notable shout-outs include the creators of Nannou, Deno, and wgpu, to name a few. Thank you!