Browse Source

motion it

happy
二货机器人 2 years ago
parent
commit
966ba02bf9
  1. 227
      components/theme/themesToken/happy/style/wave.ts
  2. 91
      components/theme/themesToken/happy/wave.tsx

227
components/theme/themesToken/happy/style/wave.ts

@ -1,29 +1,234 @@
import { useStyleRegister } from '@ant-design/cssinjs';
import { Keyframes, useStyleRegister } from '@ant-design/cssinjs';
import type { UseTokenType } from '../wave';
const antCheckboxEffect = new Keyframes('antCheckboxEffect', {
'0%': {
transform: 'scale(1)',
},
'10%': {
transform: 'scale(1.1)',
},
'35%': {
transform: 'scale(0.94)',
},
'60%': {
transform: 'scale(1.05)',
},
'85%': {
transform: 'scale(0.97)',
},
'100%': {
transform: 'scale(1)',
},
});
export default function useStyle(tokenConfig: UseTokenType) {
const [theme, token, hashId] = tokenConfig;
useStyleRegister({ theme, token, hashId, path: ['Customize', 'Wave', 'Effect'] }, () => {
const prefixCls = '.happy-wave';
const { colorPrimary, colorPrimaryBgHover, motionDurationFast, motionDurationSlow } = token;
const activeCls = '&.happy-in-out-leave-active';
return [
{
// ======================== Target ========================
[`${prefixCls}-target`]: {
animationName: antCheckboxEffect,
animationDuration: `0.45s`,
animationTimingFunction: 'ease-in-out',
animationFillMode: 'backwards',
},
// ========================= Dots =========================
[prefixCls]: {
position: 'fixed',
left: 0,
top: 0,
width: 20,
height: 20,
background: 'green',
pointerEvents: 'none',
[`${prefixCls}-dot`]: {
boxSizing: 'border-box',
position: 'absolute',
left: 0,
top: 0,
width: 10,
height: 10,
background: 'red',
width: 8,
height: 8,
borderRadius: '100%',
opacity: 0,
transform: 'translate(-50%, -50%)',
display: 'none',
// =================== Basic Motion ===================
'&.happy-in-out': {
transition: `all ${motionDurationSlow}`,
display: 'block',
'&-leave': {
opacity: 1,
'&-active': {
opacity: 0,
},
},
},
// Dot 1
'&-1': {
left: 0,
top: 0,
border: `1px solid ${colorPrimary}`,
[activeCls]: {
left: -30,
top: -10,
},
},
// Dot 2
'&-2': {
left: '10%',
top: 0,
width: 4,
height: 4,
background: colorPrimaryBgHover,
[activeCls]: {
left: 'calc(10% - 10px)',
top: -20,
width: 1,
height: 1,
},
},
// Dot 3
'&-3': {
left: '35%',
top: -5,
width: 4,
height: 4,
background: colorPrimary,
opacity: 0.8,
[activeCls]: {
left: 'calc(35% - 3px)',
top: -15,
width: 1,
height: 1,
},
},
// -----------------------
// Dot 4
'&-4': {
left: '80%',
top: 0,
width: 6,
height: 6,
background: colorPrimaryBgHover,
[activeCls]: {
left: 'calc(80% + 10px)',
top: -20,
width: 1,
height: 1,
},
},
// -----------------------
// Dot 5
'&-5': {
left: '100%',
top: '45%',
width: 10,
height: 10,
background: colorPrimary,
[activeCls]: {
left: 'calc(100% + 20px)',
top: 'calc(45% - 3px)',
width: 1,
height: 1,
},
},
// Dot 6
'&-6': {
left: '100%',
top: '90%',
width: 4,
height: 4,
background: colorPrimary,
[activeCls]: {
left: 'calc(100% + 30px)',
top: 'calc(90% + 15px)',
width: 1,
height: 1,
},
},
// -----------------------
// Dot 7
'&-7': {
left: '80%',
top: '100%',
width: 10,
height: 10,
background: colorPrimary,
[activeCls]: {
left: 'calc(80% + 10px)',
top: 'calc(100% + 10px)',
width: 1,
height: 1,
},
},
// Dot 8
'&-8': {
left: '55%',
top: '100%',
width: 4,
height: 4,
background: colorPrimaryBgHover,
[activeCls]: {
left: 'calc(55% + 2px)',
top: 'calc(100% + 20px)',
width: 1,
height: 1,
},
},
// Dot 9
'&-9': {
left: 0,
top: '100%',
width: 10,
height: 10,
background: colorPrimaryBgHover,
[activeCls]: {
left: -15,
top: 'calc(100% + 15px)',
width: 1,
height: 1,
},
},
// -----------------------
// Dot 10
'&-10': {
left: 0,
top: '50%',
width: 10,
height: 10,
background: colorPrimary,
[activeCls]: {
left: -50,
top: '50%',
width: 1,
height: 1,
},
},
},
},
},

91
components/theme/themesToken/happy/wave.tsx

@ -1,5 +1,6 @@
import classNames from 'classnames';
import CSSMotion from 'rc-motion';
import CSSMotion, { CSSMotionList } from 'rc-motion';
import raf from 'rc-util/lib/raf';
import * as React from 'react';
import type { ConfigProviderProps } from '../../../config-provider';
import useWaveStyle from './style/wave';
@ -12,40 +13,112 @@ interface HappyWaveProps {
token: UseTokenType;
}
const DOT_COUNT = 10;
function HappyWave({ target, token }: HappyWaveProps) {
const prefixCls = 'happy-wave';
const dotPrefixCls = `${prefixCls}-dot`;
const targetPrefixCls = `${prefixCls}-target`;
const [keys, setKeys] = React.useState<number[] | null>(null);
const [hiddenCount, setHiddenCount] = React.useState(0);
const [left, setLeft] = React.useState(0);
const [top, setTop] = React.useState(0);
const [width, setWidth] = React.useState(0);
const [height, setHeight] = React.useState(0);
const [, , hashId] = token;
useWaveStyle(token);
// ========================= Dots =========================
React.useEffect(() => {
if (keys && keys.length) {
setKeys([]);
}
}, [keys]);
React.useEffect(() => {
const rect = target.getBoundingClientRect();
const id = raf(() => {
const rect = target.getBoundingClientRect();
setLeft(rect.left);
setTop(rect.top);
setWidth(rect.width);
setHeight(rect.height);
setLeft(rect.left + rect.width / 2);
setTop(rect.top + rect.height / 2);
// Delay to start dot motion
setTimeout(() => {
setKeys(new Array(DOT_COUNT).fill(null).map((_, index) => index + 1));
}, 50);
target.className += ` ${targetPrefixCls}`;
});
return () => {
raf.cancel(id);
};
}, []);
const onDotVisibleChange = (visible: boolean) => {
if (!visible) {
setHiddenCount((cnt) => cnt + 1);
}
};
// ======================== Clean =========================
React.useEffect(() => {
const id = setTimeout(() => {
target.className = target.className.replace(` ${targetPrefixCls}`, '');
}, 600);
return () => {
clearTimeout(id);
};
}, []);
// ======================== Render ========================
if (!keys) {
return null;
}
return (
<div
className={classNames(prefixCls, hashId)}
style={{
left,
top,
width,
height,
}}
>
{new Array(7).fill(null).map((_, index) => {
const name = `${dotPrefixCls}-${index}`;
<CSSMotionList keys={keys} motionAppear={false} motionLeave motionName="happy-in-out">
{({ className: motionCls, key }) => {
const name = `${dotPrefixCls}-${key}`;
const dotCls = classNames(dotPrefixCls, motionCls, name);
return <div className={dotCls} />;
}}
</CSSMotionList>
{/* {keys.map((key) => {
const name = `${dotPrefixCls}-${key}`;
return (
<CSSMotion key={name}>
{() => <div className={classNames(dotPrefixCls, name)} />}
<CSSMotion
key={name}
motionAppear={false}
motionLeave
motionName="happy-in-out"
onVisibleChanged={onDotVisibleChange}
>
{({ className: motionCls }) => {
const dotCls = classNames(dotPrefixCls, motionCls, name);
return <div className={dotCls} />;
}}
</CSSMotion>
);
})}
})} */}
</div>
);
}

Loading…
Cancel
Save