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

spriteling

v1.1.5

Published

Spritesheet Animation Engine

Downloads

23

Readme

Spriteling

A scriptable spritesheet animation engine that works directly on DOM elements (no canvas). It's built as ES5 compatible JavaScript, has no external dependencies and a tiny footprint (~6KB minified/gzipped).

Install using node

npm install --save spriteling

Then either import, require or use directly as <script> tag:

import Spriteling from 'spriteling'

const Spriteling = require('spriteling')

<script type="text/javascript" src="spriteling.min.js"></script>

Example 1: Basic looping animation

Create a DOM element on the page and give it an id. Pass it to a new instance of Spriteling, giving it some information about the spritesheet and where to put it on the page. Finally call .play() on it with some optional parameters.

<div id="sprite"></div>
<script>
     const sprite = new Spriteling({
        url: '/spritesheets/arcade.png',
        top: 200,
        left: 100,
        cols: 3,
        rows: 9
    }, '#sprite')
    
    sprite.play({
        run: -1,
        delay: 100
    })
</script>

You can see it in action at "Arcade" animation

Example 2: Scripted animation

Looping sure is nice! But when we have a non-linear animation to build, we need to have fine-grained control over the individual steps. Like the sequencing of the sprites and timing them correctly. Take this spritesheet of a reading character for example:

For this animation, simply looping the images won't do. We need to add an animation script to get the desired result:

<div id="sprite"></div>
<script>
  const sprite = new Spriteling({
    url: '/spritesheets/reading.png',
    top: 200,
    left: 100,
    cols: 5,
    rows: 3
  }, '#sprite', true)

  sprite.addScript('read', [
    // read lines
    {sprite: 1, delay: 1000},
    {sprite: 2, delay: 800},
    {sprite: 1},
    {sprite: 3, delay: 400},
    {sprite: 1},

    // read lines
    {sprite: 2, delay: 800},
    {sprite: 1},
    {sprite: 3, delay: 400},
    {sprite: 1},

    // read lines
    {sprite: 2, delay: 400},
    {sprite: 1},
    {sprite: 3, delay: 800},
    {sprite: 1},

    // blink
    {sprite: 4},
    {sprite: 1},

    // turn page
    {sprite: 5},
    {sprite: 6},
    {sprite: 7},
    {sprite: 8},
    {sprite: 9},
    {sprite: 10},
    {sprite: 11},
    {sprite: 12}
  ])

  sprite.play('read', {
    run: -1,
    delay: 200
  })
</script>

You can see it in action at "Reading" demo. Another scripted animation can be seen at "Dog training" demo.

Example 3: Multiple instances

Spriteling is not hardware-accelerated, there is no need for a clunky WebGL canvas element or CSS properties that need GPU support. In fact, under the hood there is nothing more then a background positioning trick doing the hard work, which is as fast as it can get. Even under stress it performs quite well, as you can see in the "Multiple instances" demo

More advanced examples

But we shouldn't stop there! When adding positioning to the animation script, we can easily create a walking character. And the character truly comes alive when we add user interaction, like mouse events.

Feel free to check out these "Spriteling included" websites:

Now it's up to you. Please keep me posted on what you've created!

API

constructor(options, element, debug): Spriteling

Create a new Spriteling instance, example usage:

const sprite = new Spriteling({
  url: '/spritesheets/walking-character.png',
  top: 200,
  left: 100,
  cols: 5,
  rows: 3
}, '#sprite')

options: SpriteSheetOptions

Property | Type | Required | Default value | Explanation :------------- |:------------- |:-------------:| :-------------:| :------------- url | string | no | null | url to spritesheet, if not set the css background-image will be used cols | number | yes | null | Number of columns in the spritesheet rows | number | yes | null | Number of rows in the spritesheet cutOffFrames | number | no | 0 | Number of sprites not used in the spritesheet, for example the last sprite in a sheet might be blank top bottom left right | number | no | | Initial position of the placeholder element, will use current if not provided startSprite | number | no | 1 | Sprite number to show when done loading downsizeRatio | number | no | 1 | For HiDPI or Retina support, you can supply a higher resolution spritesheet (x2) and downsize it back to regular size with this property onLoaded | function | no | null | Callback function that will be called when loading has finished

element: HTMLElement | string (optional)

Can be a CSS selector or existing DOM element or null, in which case a new div element will be created

debug: boolean (optional)

Can be used to enable debug logging in console, useful when fine-tuning the animation scripts

.showSprite( sprite: number)

Stop the current animation and show the specified sprite

spriteling.showSprite(4)

.currentSprite(): number

Get the current spriteNumber that is shown

const currentSprite = spriteling.currentSprite()

.addScript(name: string, script: Array<Frame>)

Add a named animation sequence, for example:

spriteling.addScript('walk', [
    { sprite: 22, delay: 100 },
    { sprite: 23, delay: 100, left: 10 },
    { sprite: 24, delay: 150, left: 5 },
    { sprite: 23, delay: 100, left: 10 }
])

name: string

Can be any string value

script: Array<Frame>

The script parameter should be an array consisting of frame objects. These frame objects can have the following properties:

Property | Type | Required | Default value | Explanation :------------- |:------------- |:-------------:| :-------------:| :------------- sprite | number | yes | | Which sprite from spritesheet to show (counted from top-left to bottom-right) delay | number | no | delay defined with .play() | Time in ms to wait after this frame has been rendered top bottom left right | number | no | 0 | Move the position of the placeholder to any direction after frame has been rendered

.play(scriptName: string, options: AnimationOptions)

Resume/play current or given animation. Method can be called in four ways:

sprite.play() // resume current animation sequence (if not set - loops over all sprites once)
sprite.play(scriptName) // play given animation script
sprite.play(scriptName, { options }) // play given animation script with given options
sprite.play({ options }) // play current animation with given options

scriptName: string

loads a previously added animation with .addScript()

options: AnimationOptions

Property | Type | Required | Default value | Explanation :------------- |:-------------: |:-------------:| :-------------:| :------------- play | boolean | no | true | Start playing the animation right away run | number | no | -1 | The number of times the animation should run, -1 = infinite delay | number | no | 50 | Default delay for all frames that don't have a delay set tempo | number | no | 1 | Timescale for all delays, double-speed = 2, half-speed = .5 reversed | boolean | no | false | Direction of the animation head, true == backwards script | Array<Frame> | no | all frames | New unnamed animation sequence onPlay() | function | no | | Callback called when animator starts playing onStop() | function | no | null | Callback called when animator stops playing onFrame() | function | no | null | Callback called when the new frame is rendered onOutOfView() | function | no | null | Callback called when the placeholder is no longer in view. Could be used to stop the animation when it moved out of the document boundary.

The callbacks allow for interactions between sprites to take place. In the following example sprite1 will trigger play() on sprite2 after it's animation has been completed:


const sprite1 = Spriteling({
  url: '/spritesheets/ping.png',
  cols: 3,
  rows: 9
}, '#sprite1')

const sprite2 = Spriteling({
  url: '/spritesheets/pong.png',
  cols: 3,
  rows: 9
}, '#sprite2')

sprite1.play({
  run: 3,
  script: [
    { sprite:1 },
    { sprite:2 },
    { sprite:3, delay:350},
    { sprite:4 }
  ],
  onStop: () => {
    sprite2.play()
  }
})

.isPlaying()

Get the current play state

const isPlaying = spriteling.isPlaying()

.setTempo( tempo: number)

Set playback tempo, double-speed = 2, half-speed = .5 (default:1)

spriteling.setTempo(2)

.getTempo(): number

Get playback tempo, double-speed = 2, half-speed = .5 (default:1)

const tempo = spriteling.getTempo()

.next()

Step the animation ahead one frame

spriteling.next()

.previous()

Step the animation backwards one frame

spriteling.previous()

.goTo(frame: number): boolean

Jump to certain frame within current animation sequence. Returns true if succeeded.

spriteling.goTo(10)

.reverse()

Reverse direction of play

spriteling.reverse()

.isReversed()

Get the current direction of play

const isReversed = spriteling.isReversed()

.stop()

Stop the animation

spriteling.stop()

.reset()

Reset playhead to first frame

spriteling.reset()

.destroy()

Removes the element and kills the animation loop

spriteling.destroy()

Compatibility

Spriteling should work on almost anything. From IE7 to phones and tablets. Let me know if you find it doesn't work on a particular device and I'll see if I can fix that.

License

The artwork in this repository has been created by Arthur van 't Hoog and is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0) license.

Meaning you are free to:

  • Share — copy and redistribute the material in any medium or format

Under the following terms:

  • Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
  • NonCommercial — You may not use the material for commercial purposes.
  • NoDerivatives — If you remix, transform, or build upon the material, you may not distribute the modified material.