Skip to content

Instantly share code, notes, and snippets.

@fostyfost
Created November 18, 2020 13:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fostyfost/65daac0f89dbbe842a753efb9c5b2a5a to your computer and use it in GitHub Desktop.
Save fostyfost/65daac0f89dbbe842a753efb9c5b2a5a to your computer and use it in GitHub Desktop.
Raf animate
import createStub from 'raf-stub';
import { animate, AnimateUtilParams } from '../animate';
describe('`animate` util tests', () => {
const params = {} as AnimateUtilParams;
const DEFAULT_DURATION = 300;
const FRAME_DURATION = 10;
const DEFAULT_FRAMES_COUNT = DEFAULT_DURATION / FRAME_DURATION + 1;
let stub;
let spyOnRaf;
beforeEach(() => {
stub = createStub(FRAME_DURATION);
// @ts-ignore
spyOnRaf = jest.spyOn(global, 'requestAnimationFrame');
spyOnRaf.mockImplementation(stub.add);
params.actionCallback = jest.fn();
params.onFinish = jest.fn();
params.duration = DEFAULT_DURATION;
});
afterEach(() => {
spyOnRaf.mockRestore();
});
it('returns request animation frame ID > 0', () => {
expect(animate(params) > 0).toBe(true);
});
it(`runs \`actionCallback\` callback ${DEFAULT_FRAMES_COUNT} times by default`, () => {
animate(params);
stub.flush();
// @ts-ignore
expect(params.actionCallback.mock.calls.length).toBe(params.duration / FRAME_DURATION + 1);
});
it(`runs \`actionCallback\` callback ${1000 / FRAME_DURATION + 1} times if duration is 1000`, () => {
animate({ ...params, duration: 1000 });
stub.flush();
// @ts-ignore
expect(params.actionCallback.mock.calls.length).toBe(1000 / FRAME_DURATION + 1);
});
it(`runs \`actionCallback\` callback 1 time if duration is 1`, () => {
animate({ ...params, duration: 1 });
stub.flush();
// @ts-ignore
expect(params.actionCallback.mock.calls.length).toBe(1);
});
it('runs `onFinish` callback after animation', () => {
animate(params);
expect(params.onFinish).not.toBeCalled();
stub.step();
expect(params.onFinish).not.toBeCalled();
stub.flush();
// @ts-ignore
expect(params.onFinish.mock.calls.length).toBe(1);
});
});
import _noop from 'lodash/noop';
export interface AnimateUtilParams {
actionCallback?: (timeFraction: number) => void;
onFinish?: () => void;
duration?: number;
}
export const animate = ({ actionCallback = _noop, onFinish = _noop, duration = 300 }: AnimateUtilParams): number => {
const start = performance.now();
return requestAnimationFrame(function cb(time: number): void {
// `progress` изменяется от -N до 1
let progress = (time - start) / duration;
if (progress > 1) {
progress = 1;
}
actionCallback(progress);
if (progress < 1) {
requestAnimationFrame(cb);
} else {
onFinish();
}
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment