Taylor Lopez
Taylor Lopez

Reputation: 863

Animating array of divs; only the final element is modified

This is baffling me slightly at the moment.

I'm a fairly experienced programmer who is looking to throw a bit of a surprise for my fiancee on the countdown page for our wedding. The desired effect essentially simulated confetti falling behind the main page. My setup is as follows:

I have an array of divs in javascript. Each div is absolutely positioned on the page. I have an interval set that updates every 50 or so milliseconds. On each tick, I run a for loop over my array of divs, and do calculations and update their positions.

Problem The problem I am having, however, is that even though I can clearly see that all divs are created, stored into the array, and modified (in this case, each has a slight randomized rotation) during the initialization phase, once the tick to update their position starts, only the div stored in whatever the last slot of the array is gets its position updated. I even tried hard-coding each div by index for testing purposes, but it is strictly the last element that will actually update its position. Even upon printing the current "left" and "top" style values for each div before and after the calculations shows that the value has been changed, but no visible change is noticeable. Here's my basic code:

Javascript

var container;            // the div that will have all the other divs attached to it
var conf = new Array();   // the array of divs to modify
var rots = new Array();   // the rotation of each div
var vels = new Array();   // the velocity of each div
var xPos = new Array();   // the current x value of position in pixels
var yPos = new Array();   // the current y value of position in pixels
var xVels = new Array();  // the x portion of that velocity
var yVels = new Array();  // the y portion of that velocity

function initialize()     // this is attached to the onload event on my <body> tag
{
    container = document.getElementById("conf_container");
    confettiInit();       // creates, initializes, and displays each div

    setInterval(updateConfetti, 42);
}

function confettiInit()
{
    screenHeight = window.innerHeight;
    screenWidth = window.innerWidth;

    for (var i = 0; i < 25; i ++)   // create 25 confetti flakes
    {
        // append a div in the container with a unique ID
        container.innerHTML += "<div class='conf' id='conf_" + i + "'></div>";
        // store the element in an array
        conf[i] = document.getElementById("conf_" + i);
        // ensure confetti is in the background, and each z index is unique
        conf[i].style.zIndex = -i - 1;

        xPos[i] = window.innerWidth * Math.random();  // calculate random x position
        conf[i].style.left = xPos[i] + "px";          // set x position of div
        yPos[i] =  -40;                               // y position above screen
        conf[i].style.top = yPos[i] + "px";           // set y position of div

        // calculate the random amount of rotation (-30 to 30 degrees)
        rots[i] = Math.random() * 60*(Math.PI/180) - 30*(Math.PI/180);
        // set rotation of div
        conf[i].style.webkitTransform = "rotate(" + -rots[i] + "rad)";

        vels[i] = Math.random() * 3 + 2;         // calculate random velocity (2-5)
        xVels[i] = vels[i] * Math.sin(rots[i]);  // get x portion of velocity
        yVels[i] = vels[i] * Math.cos(rots[i]);  // get y portion of velocity
    }
}

function updateConfetti()
{
    for (var i = 0; i < 25; i ++)
    {
        xPos[i] += xVels[i];   // calculate new x position
        yPos[i] += yVels[i];   // calculate new y position
        conf[i].style.left = xPos[i] + "px";   // set div's x position
        conf[i].style.top = yPos[i] + "px";    // set div's y position

        // if the confetti piece leaves the viewing area...
        if (xPos[i] < -50 ||
            xPos[i] > window.screenWidth + 10 ||
            yPos[i] > window.screenHeight + 10)
        {
            // send it back to the top and reinitialize it
            xPos[i] = window.innerWidth * Math.random();

            conf[i].style.left = xPos[i] + "px";

            yPos[i] = -40;
            conf[i].style.top = yPos[i] + "px";

            rots[i] = Math.random() * 60*(Math.PI/180) - 30*(Math.PI/180);
            conf[i].style.webkitTransform = "rotate(" + -rots[i] + "rad)";

            vels[i] = Math.random() * 3 + 2;
            xVels[i] = vels[i] * Math.sin(rots[i]);
            yVels[i] = vels[i] * Math.cos(rots[i]);
        }
    }
}

CSS

div.conf
{
    height: 29px;
    width: 50px;
    background-image: url("images/ConfettiYellow.gif");
    position: absolute;
}

#conf_container
{
    left: 0px;
    top: 0px;
    width: 100%;
    height: 100%;
    position: absolute;
    overflow: hidden;
}

Upvotes: 0

Views: 162

Answers (1)

Ivan Chernykh
Ivan Chernykh

Reputation: 42176

It's something wrong with your divs creation. It start works if you do it in conventional way, like this:

var d = document.createElement("div");
d.className = "conf";
container.appendChild(d);
conf[i] = d;

Upvotes: 1

Related Questions