Use requestAnimationFrame for better perf