using requestAnimationFrame instead of setInterval/setTimeout for rendering