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 🙏

© 2026 – Pkg Stats / Ryan Hefner

rotoscope

v0.2.1

Published

Timeline animation framework

Downloads

15

Readme

Rotoscope

A library designed to make parallax effortless and enjoyable!

Join the community on Slack!

Slack Status

Installation

npm install rotoscope

Build and run

$ npm run build
$ npm start

Examples

http://codepen.io/turissinitechnologies/full/wGwzvm/

Why Rotoscope?

Parallax is an awesome effect that can give your website and web app that surprise and delight that users will love you for. While parallax is awesome, it is not trivial to implement beyond simple translates. For complex animations, a more robust tool is needed and that tool is Rotoscope.

Rotoscope itself is a super lightweight parallax library that works on the idea of timeline-based animations. This library specializes only in parallax and is 100% dependency free. It is also compatible with existing javascript animation frameworks like Greensock.

To make parallax drawing as performant as possible, rotoscope implements a two part render cycle: Updating and then Drawing. Separating the render cycle into updating and drawing allows your animations to becomes very complex without taking a performance hit. Your users will love the results!

Rotoscope is also based on timelines, which allow you to treat complex animations as a single unit. This will change the way you think about animation and also promote animations that are DRY, testable and really, really fun to show off.

If you are building complex animations or parallax effects, rotoscope will becomes an indispensible tool.

Features

  • Timeline based animations in your parallax
  • High performance rendering
  • Very flexible Clip interface that separates update and drawing
  • Immutable API
  • Promotes DRY parallax animations
  • Supports animation chaining in parallax
  • Compatible with most existing animation libraries.
  • Video parallax

Hello World example

To begin our parallax, we start by creating a rotoscope instance. The rotoscope object is what enables us to have super performant parallax. All methods on this object are chainable and immutable. This means that when any of the methods below are called, you are returned a different rotoscope instance. This prevents unintended side effects from creeping into other, unrelated parts of your code.

We should start by importing our createRotoscope function to create a rotoscope instance with a scroll target. A scroll target is any element that will emit scroll events. In most cases, this will probably be the window:

  import { createRotoscope } from 'rotoscope';

  const rotoscope = createRotoscope(window);

After we create a rotoscope object, we should define its bounds. bounds simply describe when scroll events should effect parallax. In the example below, we should see animation updates between scroll positions 50 and 150.

  const rotoscopeWithBounds = rotoscope.bounds({
    start: 50,
    duration: 100
  });

We should now add some animations. By default, rotoscope instances are created with a single root timeline that encompasses the entire animation. This timeline is the argument in the animation factory example below. We first create a greenBallClip, which is a custom clip function that takes time as an argument:

const rotoscopeWithAnimations = rotoscopeWithBounds.animate(function (timeline) {
  const greenBallClip = function (time) {
      var dist = 400;
      var y = -time * dist;
      var translate = 'scale3d(' + time + ', ' + time + ', 1)';

      return function () {
          greenBall.style.transform = translate;
      };
  };

  return timeline.appendChild(greenBallClip, {
    start: 0,
    duration: 100
  });

})

We can then start listening to scroll events and begin parallaxing

  rotoscopeWithAnimations.start();

Clip

In the animation factory above, we create a Clip function and append it to the timeline. Clip functions are what drives the animation and are broken down into two parts: Update and Draw. The first part, Update, is the calculation that happens before Draw. This part of the process takes a single argument, time, that is always a value between 0 and 1. You an think of time as percent.

The Update function should take the time and calculate what the next frame will look like. It should return a function that will actually draw that frame. This is a core concept in rotoscope and enables powerful and performant animations.

In the following example, we create a clip that moves an element, greenBall, anywhere between 0 and 400 pixels:

const greenBallClip = function (time) {
      var dist = 400;
      var y = time * dist;
      var translate = 'translate3d(' + y + 'px, 0, 0)';

      return function () {
          greenBall.style.transform = translate;
      };
  };

Timeline

Timelines allow us to compose animations together to truly make something special. They behave like trees (Like the DOM) and have children, which are clip functions and other timelines. They have an immutable API so appending a child will return a completely new timeline instance.

Adding our greenBallClip to a timeline:

const myTimeline = createTimeline();

myTimeline.appendChild(greenBallClip, {
  offset: 0,
  duration: 10,
  fill: 'both'
});

You can also 'glue' two clip functions together on a timeline. Say, for instance, that you wanted a red ball to move after the green ball was done. You could manually define an offset for the redball relative to the green ball, but that would be fragile. You can instead use the chainChild method on timeline to chain clip functions. This method takes three arguments: a clip function that already exists on the timeline. Another clip argument that will be chained to the end of the first argument. An offset object that defines time offsets -relative- to the first clip:

myTimeline.appendChild(greenBallClip, redBallClip, {
 offset: 0,
 duration: 10
});

In addition to offset, duration, you should also specify fill mode when appending a clip to a timeline. fill describes what happens when the timeline time is out of bounds beyond the offset and duration. It has 4 values:

  • none - Nothing happens, clip is skipped entirely.
  • backwards - When time is before clip, clip should be updated with time 0
  • forwards - When time is after clip, clip should be updated with time 1
  • both - Default. Clip will always be updated regardless of the time