Skip to main content
edited title
Source Link

Improving efficiency of complex animation Javascript Parallax Scrolling Text

How can I optimize thismy code to getachieve better performance?

Improving efficiency of complex animation

How can I optimize this code to get better performance?

Javascript Parallax Scrolling Text

How can I optimize my code to achieve better performance?

Source Link

Improving efficiency of complex animation

I built a 404 page which involves parallax scrolling text. The program updates the position of 100-200 text nodes at each animation frame called with window.requestAnimationFrame. It runs decently well on my MacBook (although it occupies significant CPU), but on weaker computers like my phone, it runs very sluggishly.

How can I optimize this code to get better performance?

var scene;

function randint(low, high) { // Return a random integer between low and high
  return Math.floor(( Math.random()*(high-low) ))+low;
}

// Add a layer to the scene

function addLayer() {
  // Make  a "layer" in the parallax animation
  var layer = document.createElement("div");
  // Give it a random Z value (0 to 1)
  layer.setAttribute("class", "layer");
  layer.setAttribute("data-z", Math.random().toFixed(2));

  // Make a div inside that says "404"
  layer.appendChild(document.createTextNode("404"));
  // Random X position
  layer.style.left = randint(-10, window.innerWidth) + "px";
  // Below bottom of screen
  layer.style.top = window.innerHeight + "px";
  // Font size and weight based on Z value
  var z = parseFloat(layer.getAttribute("data-z"));
  layer.style.fontSize = Math.floor(z * 150) + "px";
  layer.style.fontWeight = Math.ceil(z * 4) * 100;
  // Random opacity
  layer.style.opacity = (Math.random() / 10).toFixed(2);

  // Add nodes to appropriate parents
  scene.appendChild(layer);
}

function updatePositions() {
  var layers = scene.getElementsByTagName("div");
  var layer, div, z;
  for (var i = 0; i < layers.length; i++) {
    layer = layers[i];
    z = parseFloat(layer.getAttribute("data-z"));
    y = parseInt(layer.style.top.slice(0, layer.style.top.length - 2));
    layer.style.top = (y - Math.ceil(z * 10)).toFixed(2) + "px";

    if (y < (-150)) { // Max fontsize is 150px
      scene.removeChild(layer);
    }
  }
}

function updateColor() {
  var hue = (parseFloat(document.body.getAttribute("data-hue")) + 0.25) % 360;
  document.body.setAttribute("data-hue", hue.toString());
  var hex = chroma(hue, 1, 1, "hsv").brighten().hex();
  document.body.style.color = hex;
  document.getElementsByTagName("a")[0].style.backgroundColor = hex;
}

function update() {
  addLayer();
  updatePositions();
  updateColor();
  window.requestAnimationFrame(update); // Recur
}

scene = document.getElementById("scene");
window.requestAnimationFrame(update);
body {
  background-color: #222;
  margin: 0;
  width: 100vw;
  height: 100vh;

  /* Global font settings */
  color: #fff;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}

#scene {
  position: fixed;
  top: 0;
  left: 0;
  padding: 0;
  margin: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.layer {
  position: absolute;
}

.main {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;

  text-align: center;

  opacity: 0.5;
}

h1 {
  font-size: 200px;
  margin-bottom: 0;
}

.main p {
  font-size: 150%;
  margin-top: 0;
}

.main a {

  color: #222;
  background-color: #fff;
  padding: 10px;

  text-decoration: none;
  font-size: 150%;
  font-weight: 600;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/chroma-js/1.1.1/chroma.min.js"></script>
<body data-hue="0">
  <!-- Background -->
  <div id="scene"></div>
  <!-- Foreground  -->
  <div class="main">
    <h1>404</h1>
    <p>That page couldn't be found.</p>
    <a href="http://luke.deentaylor.com/">Home</a>
  </div>

</body>

Running this snippet in full window will more accurately emulate how it will appear on my website.

Here's a JSFiddle if it's preferred.