[WIP] Use raf to replace getRequestAnimationFrame (#10614)

* use raf to replace getRequestAnimationFrame

* remove isCssAnimationSupported
This commit is contained in:
偏右 2018-05-22 13:01:28 +08:00 committed by GitHub
parent f409df8d84
commit a2e0e40caa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 18 additions and 102 deletions

View File

@ -1,46 +0,0 @@
const availablePrefixs = ['moz', 'ms', 'webkit'];
function requestAnimationFramePolyfill() {
let lastTime = 0;
return function(callback: (n: number) => void) {
const currTime = new Date().getTime();
const timeToCall = Math.max(0, 16 - (currTime - lastTime));
const id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
}
export default function getRequestAnimationFrame() {
if (typeof window === 'undefined') {
return () => {};
}
if (window.requestAnimationFrame) {
// https://github.com/vuejs/vue/issues/4465
return window.requestAnimationFrame.bind(window);
}
const prefix = availablePrefixs.filter(key => `${key}RequestAnimationFrame` in window)[0];
return prefix
? (window as any)[`${prefix}RequestAnimationFrame`]
: requestAnimationFramePolyfill();
}
export function cancelRequestAnimationFrame(id: number) {
if (typeof window === 'undefined') {
return null;
}
if (window.cancelAnimationFrame) {
return window.cancelAnimationFrame(id);
}
const prefix = availablePrefixs.filter(key =>
`${key}CancelAnimationFrame` in window || `${key}CancelRequestAnimationFrame` in window,
)[0];
return prefix ?
(
(window as any)[`${prefix}CancelAnimationFrame`] ||
(window as any)[`${prefix}CancelRequestAnimationFrame`]
).call(this, id) : clearTimeout(id);
}

View File

@ -1,24 +0,0 @@
let animation: boolean;
function isCssAnimationSupported() {
if (animation !== undefined) {
return animation;
}
const domPrefixes = 'Webkit Moz O ms Khtml'.split(' ');
const elm = document.createElement('div');
if (elm.style.animationName !== undefined) {
animation = true;
}
if (animation !== undefined) {
for (let i = 0; i < domPrefixes.length; i++) {
if ((elm.style as any)[`${domPrefixes[i]}AnimationName`] !== undefined) {
animation = true;
break;
}
}
}
animation = animation || false;
return animation;
}
export default isCssAnimationSupported;

View File

@ -1,7 +1,5 @@
import cssAnimation from 'css-animation';
import getRequestAnimationFrame, { cancelRequestAnimationFrame } from './getRequestAnimationFrame';
const reqAnimFrame = getRequestAnimationFrame();
import raf from 'raf';
function animate(node: HTMLElement, show: boolean, done: () => void) {
let height: number;
@ -19,16 +17,16 @@ function animate(node: HTMLElement, show: boolean, done: () => void) {
},
active() {
if (requestAnimationFrameId) {
cancelRequestAnimationFrame(requestAnimationFrameId);
raf.cancel(requestAnimationFrameId);
}
requestAnimationFrameId = reqAnimFrame(() => {
requestAnimationFrameId = raf(() => {
node.style.height = `${show ? height : 0}px`;
node.style.opacity = show ? '1' : '0';
});
},
end() {
if (requestAnimationFrameId) {
cancelRequestAnimationFrame(requestAnimationFrameId);
raf.cancel(requestAnimationFrameId);
}
node.style.height = '';
node.style.opacity = '';

View File

@ -1,6 +1,4 @@
import getRequestAnimationFrame, { cancelRequestAnimationFrame } from '../_util/getRequestAnimationFrame';
const reqAnimFrame = getRequestAnimationFrame();
import raf from 'raf';
export default function throttleByAnimationFrame(fn: (...args: any[]) => void) {
let requestId: number | null;
@ -12,11 +10,11 @@ export default function throttleByAnimationFrame(fn: (...args: any[]) => void) {
const throttled = (...args: any[]) => {
if (requestId == null) {
requestId = reqAnimFrame(later(args));
requestId = raf(later(args));
}
};
(throttled as any).cancel = () => cancelRequestAnimationFrame(requestId!);
(throttled as any).cancel = () => raf.cancel(requestId!);
return throttled;
}

View File

@ -6,7 +6,7 @@ import addEventListener from 'rc-util/lib/Dom/addEventListener';
import Affix from '../affix';
import AnchorLink from './AnchorLink';
import getScroll from '../_util/getScroll';
import getRequestAnimationFrame from '../_util/getRequestAnimationFrame';
import raf from 'raf';
function getDefaultContainer() {
return window;
@ -43,7 +43,6 @@ function easeInOutCubic(t: number, b: number, c: number, d: number) {
return cc / 2 * ((t -= 2) * t * t + 2) + b;
}
const reqAnimFrame = getRequestAnimationFrame();
const sharpMatcherRegx = /#([^#]+)$/;
function scrollTo(href: string, offsetTop = 0, getContainer: () => AnchorContainer, callback = () => { }) {
const container = getContainer();
@ -67,12 +66,12 @@ function scrollTo(href: string, offsetTop = 0, getContainer: () => AnchorContain
(container as HTMLElement).scrollTop = nextScrollTop;
}
if (time < 450) {
reqAnimFrame(frameFunc);
raf(frameFunc);
} else {
callback();
}
};
reqAnimFrame(frameFunc);
raf(frameFunc);
history.pushState(null, '', href);
}

View File

@ -4,9 +4,7 @@ import addEventListener from 'rc-util/lib/Dom/addEventListener';
import classNames from 'classnames';
import omit from 'omit.js';
import getScroll from '../_util/getScroll';
import getRequestAnimationFrame from '../_util/getRequestAnimationFrame';
const reqAnimFrame = getRequestAnimationFrame();
import raf from 'raf';
const easeInOutCubic = (t: number, b: number, c: number, d: number) => {
const cc = c - b;
@ -64,10 +62,10 @@ export default class BackTop extends React.Component<BackTopProps, any> {
const time = timestamp - startTime;
this.setScrollTop(easeInOutCubic(time, scrollTop, 0, 450));
if (time < 450) {
reqAnimFrame(frameFunc);
raf(frameFunc);
}
};
reqAnimFrame(frameFunc);
raf(frameFunc);
(this.props.onClick || noop)(e);
}

View File

@ -2,7 +2,6 @@ import * as React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import Animate from 'rc-animate';
import isCssAnimationSupported from '../_util/isCssAnimationSupported';
import omit from 'omit.js';
export type SpinSize = 'small' | 'default' | 'large';
@ -57,15 +56,6 @@ export default class Spin extends React.Component<SpinProps, SpinState> {
return !!(this.props && this.props.children);
}
componentDidMount() {
if (!isCssAnimationSupported()) {
// Show text in IE9
this.setState({
notCssAnimationSupported: true,
});
}
}
componentWillUnmount() {
if (this.debounceTimeout) {
clearTimeout(this.debounceTimeout);
@ -120,13 +110,13 @@ export default class Spin extends React.Component<SpinProps, SpinState> {
render() {
const { className, size, prefixCls, tip, wrapperClassName, ...restProps } = this.props;
const { spinning, notCssAnimationSupported } = this.state;
const { spinning } = this.state;
const spinClassName = classNames(prefixCls, {
[`${prefixCls}-sm`]: size === 'small',
[`${prefixCls}-lg`]: size === 'large',
[`${prefixCls}-spinning`]: spinning,
[`${prefixCls}-show-text`]: !!tip || notCssAnimationSupported,
[`${prefixCls}-show-text`]: !!tip,
}, className);
// fix https://fb.me/react-unknown-prop

View File

@ -50,6 +50,7 @@
"moment": "^2.19.3",
"omit.js": "^1.0.0",
"prop-types": "^15.5.7",
"raf": "^3.4.0",
"rc-animate": "^2.4.1",
"rc-calendar": "~9.6.0",
"rc-cascader": "~0.13.0",

View File

@ -97,3 +97,5 @@ declare module "prop-types";
declare module "lodash/debounce";
declare module "lodash/uniqBy";
declare module "raf";