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

react-digital-rain

v10.0.10

Published

This component renders beautiful neon digital rain on a black background. It fits its container. OnClick toggling into and out of fullscreen can be enabled.

Downloads

63

Readme

react-digital-rain 💊 🔴 🔵 ⚡ 🟢 🌧️

➡️ npmjs

This component renders neon digital rain on a black background. It fits its container. It can be enabled to go fullscreen when clicked on. This is probably best used as a screensaver, in fullscreen mode.

npm install react-digital-rain

This component uses one gif to fit any screen with no loss of resolution or stretching.

Problem:

/* styles.css */
body {
  background-image: url("/images/digital_rain.gif");
  background-size: cover;
  background-repeat: no-repeat;
  background-attachment: fixed;
}

This results in stretching for most screens and a blurry experience.

Solution:

This component uses a single gif, appending it over and over to fill the screen and timing it so that the rain looks continuous. This is possible with rain.

Positioning: We use one outer div and one inner. The inner is going to calculate the gifs for a little larger than the height/width of the container. The outer is the dimensions of the container. Turns out the browser has eccentricities when it comes to gifs. We will talk about that later. Gifs are positioned statically in columns and rows. Each row gets a 2450ms delay, which is the speed of the rain over 400 css pixels. The animation travels downward at roughly 166 css pixels per second. This achieves a seemless transition from tile to tile that fits on all screen sizes.

Browser Eccentricities - Caching: A word on caching and timing - A 500x400 gif "tile" is served to the browser with the <img> tag. If we simply use the <img> tag with src, all instances are given the same gif start time by the browser. We cannot start sequentially, even if they are appended to the DOM at a later point in time. We can break this behavior by adding a random query string to the end of the <img src> attribute. The downside is that this breaks the native browser caching and forces the browser to request the <img> on each render. We now have timing but are left with multiple expensive and slow operations. The solution is the blob (binary large object). With the blob we have control over <img> timing AND we have control over caching. The blob is our manual override to cache this gif ourselves.

Browser Eccentricities - gifs: the browser pauses gifs when they are out of view to conserve computing resources. When switching between tabs, resizing the window or resizing the parent element container, this component will simply restart the animation to regain synchronicity within the browser.

fullScreen?: boolean // enters fullscreen when clicked. Defaults to false.

animationSeconds?: number // the animation duration in seconds. If not provided, the animation duration will be calculated based on screen height
<DigitalRain />

//no animation and fullscreen

<DigitalRain fullScreen animationSeconds={0} />
//static import is discouraged (8mb will be included in the main bundle)
import DigitalRain from "react-digital-rain";

//code splitting is encouraged

const DigitalRain = React.lazy(() => import("react-digital-rain"));

const App = (props) => {
  return (
    <React.Suspense fallback={<div>Loading...</div>}>
      <DigitalRain />
    </React.Suspense>
  );
};

export default App;
//For added control of full screen feature
//I've exposed a hook called useFullScreen to know when to show/hide stuff,
//such a hiding a navbar when fullscreen.

/**
 * copy/paste or use similar
 * the following is a HOC to dynamically load everyting in one component
 * this is to satisfy the React rule of hooks
 * hook will be present on every render
 */
const withLazy = (
  WrappedComponent,
  importModule,
  propsExtractor,
  fallback = null
) => {
  return (props) => {
    const [loadedModule, setLoadedModule] = React.useState(null);

    React.useEffect(() => {
      importModule().then((module) => setLoadedModule(propsExtractor(module)));
    }, []);

    return loadedModule ? (
      <WrappedComponent {...loadedModule} {...props} />
    ) : (
      fallback
    );
  };
};

const LazyDigitalRain = withLazy(
  (props) => {
    const { DigitalRain, useFullScreen, setShow, ...rest } = props;
    const { isFullScreen, screenfull } = useFullScreen();

    React.useEffect(() => {
      setShow(!isFullScreen);
    }, [isFullScreen]);

    return <DigitalRain {...rest} />;
  },
  () => import("react-digital-rain"),
  (module) => ({
    DigitalRain: module.DigitalRain, //DigitalRain is both named and default, FYI
    useFullScreen: module.useFullScreen,
  }),
  <div>...Loading</div>
);

import NavBar from "@someNavBarPackage";

const App = () => {
  const [show, setShow] = React.UseState(true);

  return (
    <>
      {show && <NavBar />}
      <LazyDigitalRain fullScreen setShow={setShow} />
    </>
  );
};

export default App;