npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@sschepis/canvas-animator

v0.1.4

Published

Animate canvases with ease

Downloads

20

Readme

Canvas Animator

A small library for creating 3D animations in the browser using the canvas element.

Install

npm install @sschepis/canvas-animator

Usage

import {
  Vector3,
  Vector2,
  Animator,
  Bounds,
  animationFunc,
  renderFunc,
  animationStartFunc
} from "./animator";

const bounds = new Bounds(new Vector3(-200, -200, -200), new Vector3(200, 200, 200));

const animation: animationStartFunc = () => {
  const animations: animationFunc[] = [];
  const animation1: animationFunc = (x, y, z) => {
    return Math.sin(x / 100) * Math.sin(y / 100) * Math.sin(z / 100) * 100;
  };
  animations.push(animation1);
  return animations;
};

const render: renderFunc = (context, position, camera, direction, value, time) => {
  const render = false;
  const breakLoop = false;
  const cameraPosition = camera;
  const cameraDirection = direction;
  const cameraDistance = cameraPosition.distance(position);
  const cameraAngle = cameraDirection.angle(position);
  if (cameraDistance < value) {
    const x = position.x - cameraPosition.x;
    const y = position.y - cameraPosition.y;
    const z = position.z - cameraPosition.z;
    const x2 = x * Math.cos(cameraAngle.x) - z * Math.sin(cameraAngle.x);
    const z2 = x * Math.sin(cameraAngle.x) + z * Math.cos(cameraAngle.x);
    const y2 = y * Math.cos(cameraAngle.y) - z2 * Math.sin(cameraAngle.y);
    const z3 = y * Math.sin(cameraAngle.y) + z2 * Math.cos(cameraAngle.y);
    const x3 = x2 * Math.cos(cameraAngle.z) - y2 * Math.sin(cameraAngle.z);
    const y3 = x2 * Math.sin(cameraAngle.z) + y2 * Math.cos(cameraAngle.z);
    const x4 = x3 + cameraPosition.x;
    const y4 = y3 + cameraPosition.y;
    const z4 = z3 + cameraPosition.z;
    const distance = Math.sqrt(x4 * x4 + y4 * y4 + z4 * z4);
    const angle = Math.atan2(y4, x4);
    const size = 1 / distance;
    context.beginPath();
    context.arc(
      Math.cos(angle) * distance,
      Math.sin(angle) * distance,
      size,
      0,
      2 * Math.PI
    );
    context.fillStyle = `rgba(255,255,255,${size})`;
    context.fill();
  }
  return breakLoop;
};

const animator = new Animator(
  bounds,
  animation,
  render,
  document.getElementById("canvas") as HTMLCanvasElement
);

animator.animate(new Vector3(0, 0, 0), new Vector3(0, 0, 0), 1000, true);

Diagrams

Class Diagram

(omitting Vector2 and Vector3's methods)

classDiagram
    class Animator {
    _stop: boolean
    _canvas: any
    _context: any
    _time: number
    _cameraPosition: Vector3
    _cameraDirection: Vector3
    constructor(document: any, canvas: string, bounds: Bounds, animation: animationStartFunc, renderFunc: renderFunc, randomCoords: boolean, step: number)
    iterate(bounds: Bounds, iteratorFunc: any, renderFunc: any, framesCount: number, step: number)
    iterateRandom(bounds: Bounds, iteratorFunc: any, renderFunc: any, framesCount: number)
    animate(caneraPosition: Vector3, caneraDirection: Vector3, framesCount: number, loop: boolean)
    stop()
    }
    class Vector3 {
    x: number
    y: number
    z: number
    }
    class Vector2 {
    x: number
    y: number
    }
    class Bounds {
    min: Vector3
    max: Vector3
    constructor(min: Vector3, max: Vector3)
    }
    class animationFunc {
    x: number
    y: number
    z: number
    }
    class renderFunc {
    context: any
    position: Vector3
    cameraPosition: Vector3
    cameraDirection: Vector3
    result: any
    time: number
    }
    class animationStartFunc {
    context: any
    bounds: Bounds
    cameraPosition: Vector3
    cameraDirection: Vector3
    time: number
    }

    Animator --|> Vector3
    Animator --|> Vector2
    Animator --|> Bounds
    Animator --|> animationFunc
    Animator --|> renderFunc
    Animator --|> animationStartFunc
    Vector3 --|> Vector2
    Bounds --|> Vector3
    Bounds --|> Vector2
    animationFunc --|> Vector3
    renderFunc --|> Vector3
    renderFunc --|> Vector2
    animationStartFunc --|> Vector3
    animationStartFunc --|> Vector2
    animationStartFunc --|> Bounds

Sequence Diagram

sequenceDiagram
    participant A as Animator
    participant C as Canvas
    participant D as Document

    A->>D: document.getElementById
    Note right of A: if the canvas is not found, the animation will not start
    A->>A: _canvas
    A->>A: _context
    Note right of A: if the context is not found, the animation will not start
    A->>C: translate

    activate A
    A->>A: animate
    Note right of A: if the stop flag is set, the animation will stop
    A->>A: _time
    A->>A: _cameraPosition
    A->>A: _cameraDirection
    A->>A: animation
    A->>A: renderFunc
    A->>A: randomCoords
    A->>A: step
    A->>A: iterate
    A->>A: iterateRandom
    A->>A: random
    deactivate A
    Note right of A: if the renderVal is true, the animation will stop
    Note right of A: if the framesCount is set, the animation will stop
    Note right of A: if the loop is set, the animation will stop
    Note right of A: if the stop flag is set, the animation will stop
    Note right of A: if the renderVal is true, the animation will stop

API

Vector3

...

Vector2

...

Bounds

class Bounds {
  min: Vector3;
  max: Vector3;
  constructor(min: Vector3, max: Vector3);
}

animationFunc

type animationFunc = (x: number, y: number, z: number) => number;

renderFunc

type renderFunc = (
  context: CanvasRenderingContext2D,
  position: Vector3,
  camera: Vector3,
  direction: Vector3,
  value: number,
  time: number
) => boolean;

animationStartFunc

type animationStartFunc = () => animationFunc[];

Animator

class Animator {

  constructor(
    bounds: Bounds,
    animation: animationStartFunc,
    renderFunc: renderFunc,
    context: CanvasRenderingContext2D
  );

  animate(
    caneraPosition: Vector3,
    caneraDirection: Vector3,
    framesCount: number = 0,
    loop: boolean = true
  ): void;

  stop(): void;
}

License

MIT