mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 20:49:53 +08:00
site: use vanilla-tilt.js for banner motion
This commit is contained in:
parent
3233ac498f
commit
5aafe6d39a
@ -19,6 +19,7 @@ import {
|
||||
import { createStyles } from 'antd-style';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import Tilt from './Tilt';
|
||||
import useLocale from '../../../../hooks/useLocale';
|
||||
|
||||
const { _InternalPanelDoNotUseOrYouWillBeFired: ModalPanel } = Modal;
|
||||
@ -79,7 +80,7 @@ const useStyle = createStyles(({ token, css }) => {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: ${gap}px;
|
||||
opacity: 0.65;
|
||||
opacity: 0.8;
|
||||
`,
|
||||
|
||||
flex: css`
|
||||
@ -117,7 +118,11 @@ const ComponentsBlock: React.FC<ComponentsBlockProps> = (props) => {
|
||||
const { styles } = useStyle();
|
||||
|
||||
return (
|
||||
<div className={classNames(className, styles.holder)} style={style}>
|
||||
<Tilt
|
||||
options={{ max: 20, glare: true, scale: 1 }}
|
||||
className={classNames(className, styles.holder)}
|
||||
style={style}
|
||||
>
|
||||
<ModalPanel title="Ant Design 5.0" width="100%">
|
||||
{locale.text}
|
||||
</ModalPanel>
|
||||
@ -252,7 +257,7 @@ const ComponentsBlock: React.FC<ComponentsBlockProps> = (props) => {
|
||||
<InternalTooltip title={locale.hello} placement="topLeft" className={styles.noMargin} />
|
||||
|
||||
<Alert message="Ant Design love you!" type="success" />
|
||||
</div>
|
||||
</Tilt>
|
||||
);
|
||||
};
|
||||
|
||||
|
33
.dumi/pages/index/components/PreviewBanner/Tilt.tsx
Normal file
33
.dumi/pages/index/components/PreviewBanner/Tilt.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import VanillaTilt, { type TiltOptions } from 'vanilla-tilt';
|
||||
|
||||
interface TiltProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
options?: TiltOptions;
|
||||
}
|
||||
|
||||
// https://micku7zu.github.io/vanilla-tilt.js/index.html
|
||||
const defaultTiltOptions = {
|
||||
scale: 1.02,
|
||||
max: 8,
|
||||
speed: 1500,
|
||||
glare: true,
|
||||
'max-glare': 0.8,
|
||||
};
|
||||
|
||||
const Tilt: React.FC<TiltProps> = ({ options, ...props }) => {
|
||||
const node = useRef<HTMLDivElement>(null);
|
||||
useEffect(() => {
|
||||
if (node.current) {
|
||||
VanillaTilt.init(node.current, {
|
||||
...defaultTiltOptions,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
return () => {
|
||||
(node.current as any)?.vanillaTilt.destroy();
|
||||
};
|
||||
}, []);
|
||||
return <div ref={node} {...props} />;
|
||||
};
|
||||
|
||||
export default Tilt;
|
@ -7,7 +7,6 @@ import useLocale from '../../../../hooks/useLocale';
|
||||
import SiteContext from '../../../../theme/slots/SiteContext';
|
||||
import * as utils from '../../../../theme/utils';
|
||||
import { GroupMask } from '../Group';
|
||||
import useMouseTransform from './useMouseTransform';
|
||||
|
||||
const ComponentsBlock = React.lazy(() => import('./ComponentsBlock'));
|
||||
|
||||
@ -28,7 +27,6 @@ const locales = {
|
||||
const useStyle = () => {
|
||||
const { direction } = React.useContext(ConfigProvider.ConfigContext);
|
||||
const isRTL = direction === 'rtl';
|
||||
|
||||
return createStyles(({ token, css, cx }) => {
|
||||
const textShadow = `0 0 3px ${token.colorBgContainer}`;
|
||||
|
||||
@ -37,7 +35,9 @@ const useStyle = () => {
|
||||
inset: 0;
|
||||
backdrop-filter: blur(4px);
|
||||
opacity: 1;
|
||||
transition: opacity 1s ease;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
transition: all 1s ease;
|
||||
pointer-events: none;
|
||||
`);
|
||||
|
||||
return {
|
||||
@ -114,10 +114,8 @@ const PreviewBanner: React.FC<PreviewBannerProps> = (props) => {
|
||||
const { pathname, search } = useLocation();
|
||||
const isZhCN = utils.isZhCN(pathname);
|
||||
|
||||
const [componentsBlockStyle, mouseEvents] = useMouseTransform();
|
||||
|
||||
return (
|
||||
<GroupMask {...mouseEvents}>
|
||||
<GroupMask>
|
||||
{/* Image Left Top */}
|
||||
<img
|
||||
style={{ position: 'absolute', left: isMobile ? -120 : 0, top: 0, width: 240 }}
|
||||
@ -134,7 +132,11 @@ const PreviewBanner: React.FC<PreviewBannerProps> = (props) => {
|
||||
<div className={styles.holder}>
|
||||
{/* Mobile not show the component preview */}
|
||||
<Suspense fallback={null}>
|
||||
{!isMobile && <ComponentsBlock className={styles.block} style={componentsBlockStyle} />}
|
||||
{isMobile ? null : (
|
||||
<div className={styles.block}>
|
||||
<ComponentsBlock />
|
||||
</div>
|
||||
)}
|
||||
</Suspense>
|
||||
<div className={styles.mask} />
|
||||
|
||||
|
@ -1,73 +0,0 @@
|
||||
import React, { startTransition } from 'react';
|
||||
import { ConfigProvider } from 'antd';
|
||||
|
||||
const getTransformRotateStyle = (
|
||||
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
|
||||
currentTarget: EventTarget & HTMLDivElement,
|
||||
multiple: number,
|
||||
isRTL: boolean,
|
||||
): string => {
|
||||
const box = currentTarget?.getBoundingClientRect();
|
||||
const calcX = -(event.clientY - box.y - box.height / 2) / multiple;
|
||||
const calcY = (event.clientX - box.x - box.width / 2) / multiple;
|
||||
return isRTL
|
||||
? `rotate3d(${24 + calcX}, ${83 + calcY}, -45, 57deg)`
|
||||
: `rotate3d(${24 + calcX}, ${-83 + calcY}, 45, 57deg)`;
|
||||
};
|
||||
|
||||
const useMouseTransform = ({ transitionDuration = 500, multiple = 36 } = {}) => {
|
||||
const [componentsBlockStyle, setComponentsBlockStyle] = React.useState<React.CSSProperties>({});
|
||||
|
||||
const { direction } = React.useContext(ConfigProvider.ConfigContext);
|
||||
|
||||
const isRTL = direction === 'rtl';
|
||||
|
||||
const onMouseMove: React.MouseEventHandler<HTMLDivElement> = (event) => {
|
||||
const { currentTarget } = event;
|
||||
startTransition(() => {
|
||||
setComponentsBlockStyle((style) => ({
|
||||
...style,
|
||||
transform: getTransformRotateStyle(event, currentTarget, multiple, isRTL),
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
const onMouseEnter: React.MouseEventHandler<HTMLDivElement> = () => {
|
||||
startTransition(() => {
|
||||
setComponentsBlockStyle((style) => ({
|
||||
...style,
|
||||
transition: `transform ${transitionDuration / 1000}s`,
|
||||
}));
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
startTransition(() => {
|
||||
setComponentsBlockStyle((style) => ({
|
||||
...style,
|
||||
transition: '',
|
||||
}));
|
||||
});
|
||||
}, transitionDuration);
|
||||
};
|
||||
|
||||
const onMouseLeave: React.MouseEventHandler<HTMLDivElement> = () => {
|
||||
startTransition(() => {
|
||||
setComponentsBlockStyle((style) => ({
|
||||
...style,
|
||||
transition: `transform ${transitionDuration / 1000}s`,
|
||||
transform: '',
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
return [
|
||||
componentsBlockStyle,
|
||||
{
|
||||
onMouseMove,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
},
|
||||
] as const;
|
||||
};
|
||||
|
||||
export default useMouseTransform;
|
@ -310,6 +310,7 @@
|
||||
"typedoc": "^0.25.0",
|
||||
"typescript": "~5.2.2",
|
||||
"vanilla-jsoneditor": "^0.18.0",
|
||||
"vanilla-tilt": "^1.8.1",
|
||||
"webpack-bundle-analyzer": "^4.1.0",
|
||||
"xhr-mock": "^2.4.1"
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user