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

lenti

v0.2.1

Published

Lenticular image viewer

Downloads

7

Readme

lenti NPM version Build Status Dependency Status Coverage percentage

Lenticular image viewer

Lenti is an image viewer that mimicks the effect of lenticular printing. It displays images in a canvas element and binds events for mouse and accelerometer events, so just as you would rotate a card or print with lenticular lenses on it, you can tilt your phone to transition between images.

Demo

Installation

$ npm install --save lenti

Basic Usage

Lenti will accomodate any number of images in the container (be good to your RAM and don’t go wild, though).

<div data-lenticular-list="true" >
  <img src="assets/images/1.jpg" alt="Blue Image" width="1280" height="720" />
  <img src="assets/images/2.jpg" alt="Blue Image" width="1280" height="720" />
  <img src="assets/images/3.jpg" alt="Blue Image" width="1280" height="720" />
  <img src="assets/images/4.jpg" alt="Blue Image" width="1280" height="720" />
</div>
import Lenti from 'lenti'

let lenticulars = document.querySelectorAll('[data-lenticular-list]')
let instances = []
// convert → array & loop through
;[...lenticulars].map((el, i) => {
  // store instance in array for further manipulation
  instances[i] = new Lenti({container: el, width: 1280, height: 720})
  // initialize instance
  instances[i].init()
})

Options

container

Required

Specifies the HTMLElement (not selector) that contains the images.

accelerometerEvents

default: true

Turns tilt interaction on or off.

mouseEvents

default: true

Turns mouse hover interaction on or off.

stripWidth

default: 16

The horizontal width (in pixels) of each lens strip.

height & width

default: 50

The height and width of the canvas (in pixels). You definitely should match this to the value of your images (which should all be the same size)

tiltMax

default: 45

tiltMin

default: -45

For the accelerometer event listener, define the max and min tiltable angle for interaction.

Instance Methods

Lenti.init()

Runs setup functions.

Lenti.bindEvents()

Lenti.destroy()

Binds (bindEvents) or unbinds (destroy) events.

Lenti.handleSizing()

Measures the sizing of the box for further calculations. By default the event bindings will call this on resize. If you are resizing a container manually, you should probably fire this.

Lenti.getBoxPosition()

Lenti.checkVisibility()

This

Lenti.redraw(balance)

Refreshes the viewer for the given balance, where balance is a float from 0–1 that represents the position in the image sequence. A value of 0 will show the first image, and a value of 1 will show the last. See custom events for an example of this.

Lenti.remap(value, inLow, inHigh, outLow, outHigh)

Helper function to map values from one range to another. You'll likely use this to map values to the range 0–1 for Lenti.redraw().

Custom events

Lenti doesn't make too many assumptions about your environment. You may turn off the default event handlers (see accelerometerEvents and mouseEvents) and make your own interaction system. Just send a value between 0–1 to your instance at Lenti.redraw().

In the following example, we show how a spring physics library (rebound) can be used as a sort of middleware in Lenti:

import Lenti from 'lenti'
import rebound from 'rebound'

let lenticulars = document.querySelectorAll('[data-lenticular-list]')
let instances = []
// convert → array & loop through
;[...lenticulars].map((el, i) => {
	const image = el.querySelector('img')
	// store instance in array for further manipulation
	instances[i] = new Lenti({
		container: el,
		width: image.width,
		height: image.height,
		stripWidth: el.getAttribute('data-strip-width'),
		mouseEvents: false // this is the key
	})
	let _this = instances[i]

	// set up spring
	const springSystem = new rebound.SpringSystem();
	const springConfig = [40, 9] // tension, friction
	const balanceSpring = springSystem.createSpring(...springConfig);
	balanceSpring.addListener({ onSpringUpdate: (balanceSpring) => {
		_this.redraw(balanceSpring.getCurrentValue())
	}})
	// initialize instance
	_this.init()

	// set initial value
	balanceSpring.setEndValue(1)

	// bind mouse events
	_this.canvas.addEventListener('mousemove', (e) => {
		const balance = _this.remap(e.offsetX / _this.canvasWidth, 0, 1, 1, 0)
		balanceSpring.setEndValue(balance)
	})
})

After disabling the default mouse event handler, we set up a new event listener (mousemove), map the value of e.offsetX / _this.canvasWidth to the range 1–0 (just inverting the range here), and send the value to balanceSpring, which interpolates the value. We tell balanceSpring to send the spring value to our instance method at Lenti.redraw() as it updates. Check the demo page to see this example in use.

You can imagine that this example does not demonstrate the full flexibility you have here, and that you could, for instance, replace the default gamma-rotation accelerometer event with events for a different axis, use ambient light sensors to change the value, have timed animations driven by any arbitrary event, and so on.

Cross-origin images

Because Lenti uses canvas to produce this effect, most browsers will be upset if you fetch an image from another origin. Be sure to set crossorigin="anonymous" on your images:

<img src="https://flickr.com/images/x/1280/720/1.jpg" alt="Blue Image" crossorigin="anonymous" width="1280" height="720" />

License

Apache-2.0 © Daniel Gamage