JSFiddle - React, Tailwind, and code Playground

by Steven Lambert

HTML

<div style="display:none" id="template" class="bubble-wrapper">
  <div class="bubble">
    <strong class="name"></strong> <span class="message"></span>  
  </div>
</div>

CSS

body {
  background: #333;
}

.bubble-wrapper {
  position: relative;
}

.bubble {
  border-radius: 4px;
  padding: 5px;
  margin: 1px;
  text-align: center;
  display: inline-block;
  background: #fdfdfd;
  color: #333;
}

JavaScript

var maxBubbles = 10;
var bubbles = [];

var messages = ['Hello', 'World', 'foo', 'bar', 'lorium', 'ipsum', 'dolor sit amet', 'ea legere persequeris mel', 'has dictas ancillae incorrupte ei', 'fin'];
var template = document.querySelector('#template');

var player = {
  x: 150,
  y: 300
};

var interval = setInterval(function() {
	if (bubbles.length < maxBubbles) {
    // set up the bubble based on the tempplate
  	var bubble = template.cloneNode(true);
    bubble.removeAttribute('style');
    bubble.removeAttribute('id');
   	bubble.querySelector('.name').textContent = 'John:';
    bubble.querySelector('.message').textContent = messages[bubbles.length];
    
		document.body.appendChild(bubble);
    
    // bubble position based on the players position
    var rect = bubble.querySelector('.bubble').getBoundingClientRect();
    bubble.style.top = (player.y - rect.top) + 'px';
    bubble.style.left = (player.x - rect.width / 2) + 'px';
    
    bubbles.push(bubble);
  }
  else {
    clearInterval(interval);
  }
}, 500)

function frame() {
	requestAnimationFrame(frame);
  
  // move bubbles up the screen, stopping at the top
  bubbles.forEach(function(bubble) {
    var top = parseInt(bubble.style.top, 10);
    if (top > 0) {
      bubble.style.top = (top - 2) + 'px';
    }
  });
}

frame();