From a2e0e40caa2e6da75fc56488f53edd28f91f307d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=81=8F=E5=8F=B3?= Date: Tue, 22 May 2018 13:01:28 +0800 Subject: [PATCH] [WIP] Use raf to replace getRequestAnimationFrame (#10614) * use raf to replace getRequestAnimationFrame * remove isCssAnimationSupported --- components/_util/getRequestAnimationFrame.tsx | 46 ------------------- components/_util/isCssAnimationSupported.tsx | 24 ---------- components/_util/openAnimation.tsx | 10 ++-- components/_util/throttleByAnimationFrame.tsx | 8 ++-- components/anchor/Anchor.tsx | 7 ++- components/back-top/index.tsx | 8 ++-- components/spin/index.tsx | 14 +----- package.json | 1 + typings/custom-typings.d.ts | 2 + 9 files changed, 18 insertions(+), 102 deletions(-) delete mode 100644 components/_util/getRequestAnimationFrame.tsx delete mode 100644 components/_util/isCssAnimationSupported.tsx diff --git a/components/_util/getRequestAnimationFrame.tsx b/components/_util/getRequestAnimationFrame.tsx deleted file mode 100644 index 597426fb70..0000000000 --- a/components/_util/getRequestAnimationFrame.tsx +++ /dev/null @@ -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); -} diff --git a/components/_util/isCssAnimationSupported.tsx b/components/_util/isCssAnimationSupported.tsx deleted file mode 100644 index e6fd21d408..0000000000 --- a/components/_util/isCssAnimationSupported.tsx +++ /dev/null @@ -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; diff --git a/components/_util/openAnimation.tsx b/components/_util/openAnimation.tsx index fc171830c8..c73fda1e3e 100644 --- a/components/_util/openAnimation.tsx +++ b/components/_util/openAnimation.tsx @@ -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 = ''; diff --git a/components/_util/throttleByAnimationFrame.tsx b/components/_util/throttleByAnimationFrame.tsx index a1c9279ca1..185a186dc4 100644 --- a/components/_util/throttleByAnimationFrame.tsx +++ b/components/_util/throttleByAnimationFrame.tsx @@ -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; } diff --git a/components/anchor/Anchor.tsx b/components/anchor/Anchor.tsx index 4c885240c6..1c02ba5e78 100644 --- a/components/anchor/Anchor.tsx +++ b/components/anchor/Anchor.tsx @@ -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); } diff --git a/components/back-top/index.tsx b/components/back-top/index.tsx index fc561cd3ea..06bcb96117 100755 --- a/components/back-top/index.tsx +++ b/components/back-top/index.tsx @@ -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 { 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); } diff --git a/components/spin/index.tsx b/components/spin/index.tsx index c60d2f963c..c071cd23c7 100644 --- a/components/spin/index.tsx +++ b/components/spin/index.tsx @@ -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 { 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 { 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 diff --git a/package.json b/package.json index 0d93c6151d..9f19e8237d 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/typings/custom-typings.d.ts b/typings/custom-typings.d.ts index 6336d3311a..a760cf6a3c 100644 --- a/typings/custom-typings.d.ts +++ b/typings/custom-typings.d.ts @@ -97,3 +97,5 @@ declare module "prop-types"; declare module "lodash/debounce"; declare module "lodash/uniqBy"; + +declare module "raf";