use request animation frame instead of tick