JS: Raining Hearts

By Xah Lee. Date: . Last updated: .

This page shows you how to use JavaScript to create a “raining hearts” or “falling snow” effect.

Here's the JavaScript code:

// 2014-08-18
// 2019-05-31
// copyright 2014 Xah Lee
// feel free to use, but must give credit, link back to this page
// from http://xahlee.info/js/js_raining_hearts.html

{

    const num_of_hearts = 30;
    const driftX = 50;
    const gravity = 100;
    const update_speed = 900; // millisecond

    // const heartTypes= [... "♥💕💓💔💖💗💘💝💞💟💙💚💛💜" ];
    const heartTypes= [... "💔♥" ];

    const viewportWidth = document.documentElement.clientWidth;
    const viewportHeight = document.documentElement.clientHeight;

    const viewSpaceWidth = viewportWidth+50;
    const viewSpaceHeight = viewportHeight+50;

    const randomInt = ((xmin,xmax) => (Math.floor( Math.random() * (xmax + 1 - xmin) + xmin )));

    const randomReal = ((xmin,xmax) => ( Math.random() * (xmax - xmin) + xmin ));

    const randomColor = (() => ("hsla" + "(" + randomInt(0,360) + "," +
                                randomInt(70,100) + "%," +
                                randomInt(40,60) + "%," +
                                randomReal(.8,1) + ")" ) );

    const f_restart_heart = ((xx) => {
        xx["xxleft"]=randomInt(0, viewSpaceWidth);
        xx.style.left= xx["xxleft"] + "px";
        xx["xxtop"]=randomInt(0, viewSpaceHeight) - viewSpaceHeight;
        xx.style.top= xx["xxtop"] + "px";
        xx["xrotate"] = randomInt(-150, 150);
        xx.style.transform = "rotate(" + xx["xrotate"] + "deg)";
    });

    const heart_box = document.createElement("div");
    heart_box.setAttribute("id","heart_box");

    const f_new_heart = (() => {
        const xx = document.createElement("div");
        xx. textContent= heartTypes[Math.floor( Math.random() * heartTypes.length )];
        xx["xxleft"]=randomInt(0, viewSpaceWidth);
        xx.style.left= xx["xxleft"] + "px";
        xx["xxtop"]= -90;
        xx.style.top= xx["xxtop"] + "px";
        xx["xrotate"] = randomInt(-150, 150);
        xx.style.transform = "rotate(" + xx["xrotate"] + "deg)";
        xx.style.color = randomColor();
        xx["xsize"]= 10 + randomInt(0,30);
        xx.style.fontSize = xx["xsize"] + "px";

        xx.style.position="fixed";
        xx.style.zIndex= randomInt(100,9999) .toString ( );
        xx.style.transition= "top linear 1.5s, left linear 1.5s, transform linear 1.5s";
        // f_restart_heart(xx);
        return xx;
    });

    { for (let i=0; i < num_of_hearts; i++) { heart_box.appendChild( f_new_heart()) } } ;

    document.body.appendChild(heart_box);

    const heartNodes = Array.from (heart_box.children);

    const f_update_positions = (() => {

        heartNodes.forEach (((xx: HTMLElement) => {
            xx["xxleft"] +=
                (() => {
                    const rnd = Math.random();
                    if ( rnd < 0.3333 ) {
                        return 0;
                    } else if ( rnd < 0.6666) {
                        return driftX;}
                    else {
                        return - driftX;
                    }
                }) ();

            xx["xxtop"] = xx["xxtop"] + ( (xx["xsize"]/20) * (gravity) );

            if ( xx["xxtop"] > (viewSpaceHeight) + viewSpaceHeight/10 ) {
                f_restart_heart(xx);
            } else {
                xx["xxtop"] = xx["xxtop"] + gravity /10 * randomInt(0,10); };

            if ( xx["xrotate"] !== 0 ) {
                xx["xrotate"] = xx["xrotate"] + randomInt(-30,60);
                xx.style.transform = "rotate(" + xx["xrotate"] + "deg)";
            };

            xx.style.left = xx["xxleft"] + "px";
            xx.style.top = xx["xxtop"] + "px";
        }))

    });

    setInterval( f_update_positions , update_speed);
}
;

How Does it Work?

The main thing is to create HTML elements with CSS that's fixed position with respect to window. Each element is a “heart” in its own layer. Then, just create a loop to update the element's positions.

Web Scripting Overview

  1. Browser Window Object, DOM
  2. Intro to Event-Based Programing
  3. JavaScript Load Order

DOM How-To

  1. Basic DOM Methods
  2. Get Element by ID, Tag, Name, Class, CSS
  3. Change CSS
  4. Change Node Content
  5. Create/Insert Node
  6. Remove Node
  7. Get Attribute Value
  8. Set Attribute Value
  9. Remove Attribute
  10. List/Add/Remove Class Attribute
  11. Add/Remove Event Handler
  12. Navigate DOM Tree
  13. Node Type, Name, Value

HTML Input

  1. Button
  2. Text Field
  3. Password Field
  4. Textarea
  5. Email 📧
  6. Number Field
  7. Radio Button 🔘
  8. Checkbox 🗹
  9. Popup Menu
  10. Slider 🎚
  11. Color Picker 🌈

Web Scripting Examples

  1. Disable Right Click
  2. document.write
  3. Image Rollover
  4. Pop-up New Window
  5. Digital Clock
  6. Stopwatch
  7. Fade a Element
  8. How to Create Tooltip
  9. Falling Snow Effect
  10. Box Following Scroll

Web Scripting Misc

  1. Web Cookies
  2. Web Storage
  3. DOM: Open URL window.open
  4. Encode URL, Escape String
  5. Browser Info, Navigator Object
  6. Get URL (window.location)
  7. Find Window Width
  8. Find Element Width
  9. WebSocket
  10. Value of “this” in Event Handler
  11. Event Delegation
  12. Get Current Script Tag
  13. insertAfter Element
  14. Randomize List
  15. create Document Fragment
  16. innerHTML, nodeValue, textContent, innerText?
  17. What is Live Object
  18. NodeList vs HTMLCollection
  19. Whitespace Nodes

jQuery

  1. jQuery Basics
  2. jQuery() vs querySelectorAll()
  3. Write JQuery Plugin

node.js

Like it? Help me by telling your friends. Or, Put $5 at patreon.

Or, Buy JavaScript in Depth

If you have a question, put $5 at patreon and message me.

Web Dev Tutorials

  1. HTML
  2. CSS
  3. JavaScript
  4. JS Obj Ref
  5. DOM
  6. SVG
  7. Blog