Giter Site home page Giter Site logo

rudxain / rgb-digital-rain Goto Github PK

View Code? Open in Web Editor NEW
14.0 1.0 3.0 3.4 MB

The Matrix "falling code/letter rain" animation but RGB. No more monochromatic green!

Home Page: https://rudxain.github.io/RGB-digital-rain/

License: GNU Affero General Public License v3.0

JavaScript 88.12% HTML 9.81% CSS 2.07%
animation the-matrix digital-rain falling-code rgb canvas-api code-rain matrix-rain pwa rygcbm jsdoc interactive ts-check html

rgb-digital-rain's Introduction

RGB-DR

RYGCBM colored vertical stripes

▶️Demo

⚙️Features

  • ⚡️Real-time auto 🔆light/🌙dark theme switching, with transitioning ✨️
  • 👆Interactive: droplet spawning on 🖱click/touch
  • 💻Responsive: efficient resizing, and native full-screen resolution

ℹUsage

You can go to the website (minified), or ⬇download this branch (cutting-edge). If you downloaded the branch, then extract it, then open src/index.html on any 🌐browser.

Naming?

If you don't believe me, the "official" name is "Digital Rain", even though the standard-de-facto is "falling code".

Why I did this

Everything started when a family member (I haven't asked permission to reveal their identity, yet) sent me a link to this article, and I was interested in learning how it worked, because the code was so simple yet the result was so cool and complete! I also wanted to learn because I always wanted to make a canvas/image processing in some programming lang, specially if it involved animations.

I downloaded the source, started editing in VS-Code to make some minor improvements, and realized I could update the font color for each individual char being displayed, so I decided to implement the feature using a color table sorted like a 🌈rainbow (like those RGB gaming PC setups, lol). I searched on the web to see if someone has done the exact same thing and only found this video, which is similar but not the same idea, because it has a limited color palette (update: found this app). So I decided to post my little project on GH for anyone to see and give me feedback.

Later I realized GH allowed anyone to create web{page/site}s, so I started setting everything up, while also breaking my head trying to understand exactly what I had to do, lol. Some parts of the docs said I had to install 3 different packages, other parts told me to do other things. But in the end I realized it was much simpler than I thought.

⭐Credits

  1. Original source code by 👤Ganesh Prasad: https://codepen.io/gnsp/pen/vYBQZJm
  2. My family member for sending me the article.
  3. Inspiration by RGB PC setups like this one which looks similar to my animation.

rgb-digital-rain's People

Contributors

rudxain avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

rgb-digital-rain's Issues

Use event listener to auto-resize canvas when window is resized

Problem

Currently, resizing the window or switching in-and-out of full-screen mode causes the default black background to show instead of the animation. This is awkward because it requires the user to reload the site in order to update the canvas size.

Solutions

  1. Naive synchronous: Repeatedly check window size each frame, and update the canvas dimensions accordingly. This approach seems bad for performance.
  2. Real-time event-oriented: A better approach is to use addEventListener to do this in an asynchronous manner. This is still not good for performance because it calls the callback function for each pixel size change which means it will be called hundreds of times per second while the user is resizing the window.
  3. Damped/debounced event-oriented: This approach still waits for the size to change, but only updates the canvas size if the changes are not frequent. This is the most energy-efficient approach but it would force users to wait for the changes to be applied

Layering (distance) system?

I was considering to add a dist property (#40), which encodes the distance from the screen. Farther droplets would be smaller, fainter, and appear (because the y limit would be longer) slower.

But this poses several problems. The main one being having to optimize draw-order, which would require a stripped-down 3D-engine

add settings GUI

Provide users a way to input their customization preferences, and use localStorage for persistence.
These settings would include:

  • Speed
  • Colors
  • Character set
  • Size
  • Dimming factor
  • Resizing delay (for debouncing)
  • Play & pause functionality

low-FPS on mobile (even hi-end)

It seems devicePixelRatio scaling has the downside that some browsers for Android can't handle the full resolution Canvas. I've noticed this on Firefox and Chrome. Is this throttling for the sake of battery-saving?

Add a "debug mode"

Add a developer/debug mode that "unlocks" constants, such that the code can be modified in the browser dev console while the code is running. This would allow users to modify the animation while the settings feature isn't implemented, and would make testing and debugging easier and more fun. I'll implement it by conditionally executing code based on the content of location.href, so the mode only activates at page-load-time if the user knows the "special URL" or clicks a link containing it

parallelization

Right now, the main thread isn't the bottleneck, it's the API. But when users are allowed to set droplet speed, we'll need WebWorkers.

I'll have to benchmark before doing so, as the context API calls may be I/O bound rather than CPU-bound. Especially considering that droplets are rendered by repeatedly drawing individual chars, rather than drawing batches of chars

Make it interactive

But how? I have no idea how such a feature would be implemented. Maybe touching a falling stream blocks it? Or maybe it creates a new stream? If someone sees this, please give me suggestions here

Live Wallpaper

Since I'm too lazy to rewrite this thing in Kotlin as an Android app, I tried searching for apps that displayed websites as live wallpapers (for Android).

I found WebLiveWallpaper, but it's no longer available in the G Play Store, and when I downloaded it from APK Pure it didn't seem to work with my website (maybe it's because I didn't understand the instructions, lol)

For Windows there's no problem, since there are at least 2 apps that seem to do the job (I haven't tested them yet)

For GNU-Linux distros, I have no idea if there's such a thing.

I don't care about iOS and MacOS, lol

Add easter eggs

This is technically impossible because the entire website is open-source, but users who don't want to be spoiled can ignore looking at the repo or the website's source files, so anyone who wants a hint or a full-blown spoiler just needs to look at the source (unless I obfuscate it). Any suggestion is appreciated. The 1st approved easter egg will make me close this issue, so any subsequent easter eggs should be requested in Discussions (to make sure the majority agrees)

add `onClick` feedback

Why not make a sound each time the user spawns a droplet? What if each touch drew a circular-outline centered at click coords?

These little details would improve accessibility, and may make the app more fun!

Frame drawing is bad

The animation has a max FPS locked at 30, and if requestAnimationFrame is called at a lower frequency, both the FPS and the speed of animation get lower.

I should find a way to let the FPS be independent of the animation speed

Use `requestAnimationFrame` instead of `setInterval`

This would improve energy efficiency, and it would allow browsers to use V-sync easily. However, I have no idea how to "convert" the code to work exactly the same without breaking it. I know I should make use of the hi-res timestamp provided by requestAnimationFrame, but the animation is hard-coded in such a way that the frame-rate is directly linked to the speed

Switch to TS and use a minifier

Replace the source code of anim.js by TypeScript, and make a minified copy that will be referenced by the <script> tag. Also make a minified copy of index.html itself. Only the minified files should be deployed to the GH Pages Site, while the source files stay in the repo. This will make the code better, and the website faster. The downsides is that I would have to install and use the TS compiler, and a minifier such as Google Closure Compiler

More variation

Instead of 2 arrays, there should be 1 array of "droplets", where each droplet is an object that remembers coords and color.

This way, we can break free from the terminal-like grid, and bring a little more charm to the anim

Which way of deriving size is better?

Assuming this:

// viewport
let W=width, H=height

const { min, max, hypot: diagonal } = Math

/** Geometric Mean */
const geomean = (a,b) => Math.sqrt(a * b)

Given an arbitrary relative (ratio) size, which of these values should be multiplied by it to get the final Droplet absolute font size?

[ W, H, max(W,H), min(W,H), diagonal(W,H), geomean(W,H) ]

Each of those has many pros and cons. I have no idea which is more desirable.

Actual code:

droplet_abs_size = anim.settings.droplet_rel_size * Math.min(w, h) * 2

color blending rounding errors?!

If dimDepth is low enough, instead of darkening everything until it is black, it darkens chars until they have a minimum brightness inversely proportional to dimDepth. I have no idea why TF this happens, it seems to be related to gamma

Replace PNG favicon by SVG

All modern browsers support SVG favicons, even the Web App Manifest allows SVG app icons. The icon only contains colored squares, which are very easy to replicate using vector graphics. Using SVG would allow 1 icon to be resized by the browser which makes it suitable for more devices with different display sizes and resolutions, without the need to manually maintain and hard-code many duplicate icons with different resolutions

Make both branches independent

I realized that using a single branch to deploy to GHP was a bad idea, but using a secondary branch that's just a duplicate of main is also a bad idea. So I decided to make each branch different and stop committing PRs to the 2nd from main

Use vector graphics instead of bitmap

The only way I know of that would allow me to do this, is by rewriting the code to animate an SVG instead of a Canvas. Using vector graphics would allow users to zoom-in without the canvas looking blurry.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.