use requestAnimationFrame for animation