Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

27 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐ŸŽจ Paxel Motion Framework

A lightweight pixel art and environment simulation framework for HTML Canvas, perfect for retroโ€‘style visuals and smooth motion design animations.

โœจ Features

  • ๐Ÿ–Œ Pixelโ€‘perfect rendering for authentic retro aesthetics
  • ๐ŸŒฆ Environment simulation: forces, collisions and physics
  • ๐Ÿงฉ Modular API for drawing, animating, and composing scenes
  • โšก Optimized for performance in modern browsers with webgl
  • ๐Ÿ“ฆ Typescript with zero runtime dependencies

๐Ÿš€ Projects

Here will be listed all the known applications using this framework in any creative way:

  • ๐ŸŽจ Paxel Motion App : a free drawing and motion graphics pixel art application, to let everyone experiment with retro visuals and imagination. Is developed and maintained by the same developer of the framework. Give it a try: Paxel Motion App.

Paxel Motion App Screenshot


๐Ÿ“ฅ Installation & Build

This library is not published on npm. You can install it in two ways:

  1. Clone and build manually
    git clone https://github.com/fpetcast/paxel-motion-framework
    cd paxel-motion-framework
    npm install
    npm run build
  2. Download the build folder directly : the build folder is updated with the latest stable release. Copy it directly into your project and import from there.

The build folder contains the index file of the library, the minified version and the .d.ts for types.


๐Ÿ’พ Usage

๐Ÿ“‹ Configuration

For an immediate start you can just import the renderer class and initialize with a canvas html

import { PaxelRenderer } from "./build";
const canvas = document.createElement("canvas");
document.body.appendChild(canvas);

const paxelRenderer = new PaxelRenderer(canvas);

For advanced configuration, you can import the type to pass optional config object as second argument to the class

import { PaxelRenderer, type PaxelRendererConfig } from "./build";

const canvas = document.createElement("canvas");
document.body.appendChild(canvas);

export const config: PaxelRendererConfig = {
  init: true, // initialize without calling the init method
  canExport: true, // let you export frames
  defaultLayer: "default" //default layer name
  canvas: {
    width: 640, // will set canvas width
    height: 640, // will set canvas height
  },
  grid: {
    rows: 16, // number of rows
    columns: 16, // number of columns
  },
};

const paxelRenderer = new PaxelRenderer(canvas, config);

๐ŸŽ‡ Rendering

Now let's begin to draw something on the screen: calling this function after initialization to display a frame border around the canvas.

function effect = (
  paxelRenderer: PaxelRenderer,
  config: PaxelRendererConfig,
  intervalDuration: number = 100,
  color: string = "#000000" //rgba or hex color
)  {
  const maxX = config.grid.rows;
  const maxY = config.grid.columns;
  let x = 0;
  let y = 0;

  const interval = setInterval(() => {
    if (x < maxX) {
      paxelRenderer.putPixel(x, 0, color);
      paxelRenderer.putPixel(maxX - x, maxY - 1, color);
      x++;
    }

    if (y < maxY) {
      paxelRenderer.putPixel(0, y, color);
      paxelRenderer.putPixel(maxX - 1, maxY - y, color);
      y++;
    }

    if (y >= maxX && x >= maxX) {
      clearInterval(interval);
    }
  }, intervalDuration);
}

Using putPixel method we can show pixels at specific positions based on the grid defined in configuration.

It's also possible to draw using the position in pixel relative to the screen, for example detecting the click and draw pixels at grid positions using drawAt method

import { PaxelRenderer } from "./build";
const canvas = document.createElement("canvas");
document.body.appendChild(canvas);

const paxelRenderer = new PaxelRenderer(canvas);
const selectedColor = "#000000";
canvas.addEventListener("click", (e) => {
  paxelRenderer.drawAt(e.offsetX, e.offsetY, selectedColor);
});

๐Ÿ“š Layers

By default all the pixels will be drawn on the same layer, but there is a stack mechanism to create overlays and complex backgrounds using layers. You can add a layer with a given name using addLayer and use it as the new active layer with setActiveLayer.

const newLayerName = "above-default-layer";
paxelRenderer.addLayer(newLayerName);
paxelRenderer.setActiveLayer(newLayerName);

The active layer will be used by default when calling the drawing pixels functions putPixel and drawAt. There are other common features relative to layers like getLayers to get the names of all registered layers or removeLayerByName to remove them by name

const removeLayerName = "remove-me";
paxelRenderer.removeLayerByName(removeLayerName);

Another important feature of layers is that they can be cleared from all the pixels rendered on them. To clear a single layer, just call clearLayer method, but as a good shortcut to completely clear the frame clearAllLayers should do the trick.

const clearLayerName = "clear-me";
paxelRenderer.clearLayer(clearLayerName);

// this should remove all pixels from the frame and layers
paxelRenderer.clearAllLayers();

The visibiltiy of layers could be managed using setLayerVisibility.

const notVisible = "not-visible";
paxelRenderer.setLayerVisibility(notVisible, false);

๐Ÿ‘พ Physics

One of the coolest things you can do is to make static objects start moving, like a magician, or nowadays like animators.

The frameworks supports an animation loop that can be controlled as you like using three methods.

paxelRenderer.start(); // start physics simulation
paxelRenderer.stop(); // stop physics simulation
paxelRenderer.reset(); // restart physics simulation from original positions

But playing a physics simulation will involve to register forces and possibly loops, to see all the pixels on the specified layers moving with a pattern.

Start simple, set a force on the renderer, this by default will only create the vector which will be added to the position of the layers. Only the layers that are subscribed to the force will be impacted when playing the simulation.

// this will create a force in the simulation with the specificed vector and a name
const force = {
  x: 1,
  y: 0
};
paxelRenderer.createForce(force.name, force);

// create a layer or register one yet created to the force
const movingLayer = "moving-layer"
paxelRenderer.applyForce(movingLayer);

paxelRenderer.start(); // to see the force in action

You can also define the target FPS (but really always depends on the web browser), and the loop time. Applying the loop on specific layers will trigger a restart for all the pixels involved, that will return to the original positions like in an animation cycle.

// maxFps set to 30
let fps = 15;
paxelRenderer.setFPS(fps);

// define the loop time in seconds
let seconds = 2;
paxelRenderer.setLoopDuration(seconds);

const loopedLayer = "looped-layer"
paxelRenderer.applyLoop(loopedLayer);

paxelRenderer.start(); // to see the layer looping cycle

About

Paxel motion framework enables drawing pixel art and create motion designs with html canvas.

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages