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

alpinejs-spring

v0.0.5

Published

a simple plugin that provides a utility for calculating spring animations

Downloads

845

Readme

alpinejs-spring

A simple plugin that provides a utility for calculating spring-like motion. This was created by yoinking svelte's built-in motion library, and hooking it up to work with Alpine.

All contributions are welcome. To maintain this project one needs a certain level of understanding Alpine's inner workings and an understanding of spring animations, both of which I currently lack. 🤷

Try it out here!

Install

With a CDN

<script
  defer
  src="https://unpkg.com/alpinejs-spring@latest/dist/spring.min.js"
></script>

<script defer src="https://unpkg.com/[email protected]/dist/cdn.min.js"></script>

With a Package Manager

yarn add -D alpinejs-spring

npm install -D alpinejs-spring
import Alpine from "alpinejs";
import spring from "alpinejs-spring";

Alpine.plugin(spring);

Alpine.start();

Usage

The plugin gives you a magic function $spring, this function would give you an object in which you can get and set the current values of the spring as well as it's configuration. To use this function simply pass it an initial value:

<div x-data="{ width: $spring(0) }"></div>

The initial value can be a number, an object, or an array, as long as all the object properties or array values are numbers:

<div x-data="{ ball: $spring({ x: 0, y: 0 }) }"></div>

You can access the current value of the spring by using [key].value:

<div x-data="{ width: $spring(0) }">
  <div :style="{ width: Math.abs(width.value) + 'px' }"></div>
</div>

<div x-data="{ ball: $spring({ x: 0, y: 0 }) }">
  <div :style="{ left: ball.value.x + 'px', top: ball.value.y + 'px' }"></div>
</div>

Setting the value

To set the value, just call [key].set() and pass it the target value the spring should animate towards:

<div
  x-data="{ width: $spring(0) }"
  @mousemove="width.set($event.clientX - $el.getBoundingClientRect().x)"
>
  <div :style="{ width: Math.abs(width.value) + 'px' }"></div>
</div>

You can also pass a second argument to tell the spring how you want it animated:

<button @click="width.set(0, { hard: true })">reset</button>
<button @click="width.set(0, { soft: true })">reset</button>
<button @click="width.set(0, { soft: 0.5 })">reset</button>

if you want to set the value immediately then you can pass { hard: true }. If you want the spring to preserve existing momentum before making the change you can pass { soft: n }, where n is the number of seconds it preserves existing momentum, if this value is true it will default to 0.5 seconds.

using the update() function

You can also use the [key].update() function to set the values, but instead of passing a value, you pass a callback. This callback will be passed two arguments, the current target value and the current value, this is helpful when you want to know what the spring is currently animating towards:

// this updates `width.value` to half of the target value instantly.
this.width.update((target, value) => target / 50, { hard: true });

Updating non-primitives

To update objects or arrays, always pass the full object with all the expected keys:

<button @click="ball.set({ x: 0, y: 0 })">reset</button>

<!-- will not work -->
<button @click="ball.set({ x: 0 })">reset</button>

💡 Currently thinking of allowing partial updates, I'm leaning on just doing it shallowly, so nested objects still have to be given the full object. But in the meantime I don't see it as much of a nuisance, feel free to put up an issue if you'd like this feature.

Customizing the "springiness"

You can pass a second argument to $spring which will dictate the "springiness" of the values:

<div
  x-data="{ width: $spring(0, { stiffness: 0.5, damping: 0.3, precision: 0.01 }) }"
></div>

Each property expects a number between 0 to 1, you don't have to provide all the values, just the ones you want changed. Each property has a default value assigned.

  • stiffness: determines the "tightness" of the spring, where higher is tighter. Defaults to 0.15
  • damping: determines how springy the spring is, the lower the value, the springier. Defaults to 0.8
  • precision: determines how precise the spring will animate towards the target value, the lower the more precise. Defaults to 0.01

You can also edit these properties after initialization. These properties are accessible through [key].[property]:

<!-- 0 is exclusive, unless you want it to infinitely slide or never move! -->
<input type="range" min="0.01" max="1" step="0.01" x-model="width.stiffness" >
<input type="range" min="0.01" max="1" step="0.01" x-model="width.damping" >
<input type="range" min="0.01" max="1" step="0.01" x-model="width.precision" >

Pitfalls

Values can go to the negatives

While animating, a spring value can go into negative values even when the target value is not. This might cause a problem when you're trying to animate a value you expect to be positive, for example the width of an element cannot be negative.

Usage with Alpine.data()

You can get access to the $spring magic by using a normal function instead of an arrow function:

Alpine.data("collapsable", function () {
  return {
    height: this.$spring(0);
  }
});

Stats