diff --git a/.husky/pre-commit b/.husky/pre-commit index 689d6da8..2312dc58 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1 @@ -# npm test +npx lint-staged diff --git a/package-lock.json b/package-lock.json index 7cf84635..0474dcff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,6 @@ "echarts": "^5.4.3", "echarts-for-react": "^3.0.2", "fetch-intercept": "^2.4.0", - "framer-motion": "^11.13.5", "helmet": "^8.0.0", "html-to-image": "^1.11.11", "html2canvas": "^1.4.1", @@ -56,6 +55,7 @@ "markmap-lib": "^0.17.2", "markmap-view": "^0.17.2", "mermaid": "^11.4.1", + "motion": "^11.15.0", "nanoid": "^5.0.9", "node-polyfill-webpack-plugin": "^4.1.0", "number-flow": "^0.4.1", @@ -25712,6 +25712,32 @@ "node": ">=0.10.0" } }, + "node_modules/motion": { + "version": "11.15.0", + "resolved": "https://registry.npmmirror.com/motion/-/motion-11.15.0.tgz", + "integrity": "sha512-iZ7dwADQJWGsqsSkBhNHdI2LyYWU+hA1Nhy357wCLZq1yHxGImgt3l7Yv0HT/WOskcYDq9nxdedyl4zUv7UFFw==", + "license": "MIT", + "dependencies": { + "framer-motion": "^11.15.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/motion-dom": { "version": "11.14.3", "resolved": "https://registry.npmmirror.com/motion-dom/-/motion-dom-11.14.3.tgz", diff --git a/package.json b/package.json index ca60738c..e337b094 100644 --- a/package.json +++ b/package.json @@ -239,7 +239,6 @@ "echarts": "^5.4.3", "echarts-for-react": "^3.0.2", "fetch-intercept": "^2.4.0", - "framer-motion": "^11.13.5", "helmet": "^8.0.0", "html-to-image": "^1.11.11", "html2canvas": "^1.4.1", @@ -259,6 +258,7 @@ "markmap-lib": "^0.17.2", "markmap-view": "^0.17.2", "mermaid": "^11.4.1", + "motion": "^11.15.0", "nanoid": "^5.0.9", "node-polyfill-webpack-plugin": "^4.1.0", "number-flow": "^0.4.1", diff --git a/src/pages/layout/proSecNav/index.jsx b/src/pages/layout/proSecNav/index.jsx index 70c238b5..6963434c 100644 --- a/src/pages/layout/proSecNav/index.jsx +++ b/src/pages/layout/proSecNav/index.jsx @@ -67,6 +67,7 @@ const ProSecNav = () => { { label: t('home'), key: '/', icon: }, { label: t('demo'), key: '/demo', icon: }, { label: 'Parallax', key: '/parallax', icon: }, + { label: 'Motion', key: '/motion', icon: }, { label: 'Qr Generate', key: '/qrcode', icon: }, { label: 'Prism Render', key: '/prism', icon: }, { label: 'React Tilt', key: '/tilt', icon: }, diff --git a/src/pages/motion/index.jsx b/src/pages/motion/index.jsx new file mode 100644 index 00000000..27ecfa6c --- /dev/null +++ b/src/pages/motion/index.jsx @@ -0,0 +1,768 @@ +import React, { useState, useRef } from 'react' +import { motion, useAnimationControls, LayoutGroup } from 'motion/react' +import FixTabPanel from '@stateless/FixTabPanel' +import { is } from '@react-spring/shared' + +const animations = { + show: { + opacity: 1, + }, + hidden: { + opacity: 0, + }, +} + +const list = { + visible: { opacity: 1 }, + hidden: { opacity: 0 }, +} + +const item = { + visible: { opacity: 1, x: 0 }, + hidden: { opacity: 0, x: -100 }, +} + +const variantsText = { + visible: (i) => ({ + opacity: i * 0.3, + transition: { + delay: i * 0.3, + }, + }), + hidden: { opacity: 0 }, +} + +const btnStyle = { + color: 'white', + fontFamily: 'system-ui', + backgroundColor: 'black', + padding: 10, + paddingLeft: 32, + paddingRight: 32, + letterSpacing: 1, + borderRadius: 20, + cursor: 'pointer', + whiteSpace: 'nowrap', +} +const easeNames = [ + 'linear', + 'easeIn', + 'easeOut', + 'easeInOut', + 'circIn', + 'circOut', + 'circInOut', + 'backIn', + 'backOut', + 'backInOut', + 'anticipate', +] + +const randomSort = (arr) => { + let newArr = [] + const len = arr.length + for (let i = 0; i < len; i++) { + const random = Math.floor(Math.random() * arr.length) + newArr.push(arr[random]) + arr.splice(random, 1) + } + return newArr +} + +const ParallaxVert = () => { + const controller = useAnimationControls() + const controller2 = useAnimationControls() + + const controls = useAnimationControls() + + const constraintsRef = useRef(null) + + const template = ({ rotate, x }) => { + return `rotate(${rotate}) translateX(${x})` + } + + const [isRotated, setRotate] = useState(false) + + const [isAnimation, setIsAnimation] = useState(false) + + const [buttonRight, setButtonState] = useState(false) + + const [listLabel, setListLabel] = useState(['JavaScript', 'html', 'css', 'webAssembly']) + const [isBig, setBigState] = useState(false) + const [leftState, setLeftState] = useState(false) + + return ( + +

Hi, Motion

+ + + + + + + item1 + item2 + item3 + + {['vue', 'react', 'angular'].map((item, i) => ( + + {item} + + ))} + +
+ { + setRotate(!isRotated) + }} + > +
{ + setRotate(!isRotated) + }} + > + 点击切换 +
+
+ + + console.log(info.point.x, info.point.y)} + onDragEnd={(event, info) => console.log(info.point.x, info.point.y)} + onDirectionLock={(axis) => console.log('axis', axis)} + dragSnapToOrigin={true} + // dragConstraints={{ left: 0, right: 300 }} + dragConstraints={constraintsRef} + // dragElastic={false} + // dragElastic={0.8} + // dragPropagation={false} + > +
+ { + controller.start({ scale: 1.2 }) + }} + > + 大 + + { + controller.start({ rotate: 45 }) + }} + > + 旋转 + + { + controller.start({ opacity: 0.2 }) + }} + > + 透明度 + + { + controller.start({ opacity: 1, rotate: 0, scale: 1.0 }) + }} + > + 还原 + +
+
+ +
+ { + console.log(latest.x, latest.y) + }} + onAnimationStart={() => { + console.log('Animation started') + setIsAnimation(true) + }} + onAnimationComplete={(definition) => { + setIsAnimation(false) + console.log('Completed animating', definition) + }} + > +
+ { + await controller2.start({ x: 100 }) + await controller2.start({ y: -200 }) + await controller2.start({ x: -100 }) + controller2.start({ y: 0 }) + }} + > + 开始 + +
+
+ +
+
+ {easeNames.map((item, i) => { + return ( +
+ + {item} + + {item} +
+ ) + })} +
+
+
{ + controls.start({ y: -200 }) + }} + > + 开始 +
+
{ + controls.set({ y: 0 }) + }} + > + 还原 +
+
+
+ +
+ +
+ + { + setButtonState(!buttonRight) + }} + > + + + +
+ + {listLabel.map((item) => { + return ( + + {item} + + ) + })} + { + setListLabel(randomSort(listLabel)) + }} + > + 点击改变顺序 + + +
+
+ { + setButtonState(!buttonRight) + }} + > + + { + setButtonState(!buttonRight) + }} + > + + 点击任意一个 + +
+
+ + + { + setBigState(!isBig) + }} + > + click + + + + + +
+
+
+ { + setLeftState(!leftState) + }} + > + + + 黑点和文字都设置了layout +
+
+ { + setLeftState(!leftState) + }} + > + + + 黑点和文字都未设置layout +
+
+
+ ) +} + +export default ParallaxVert diff --git a/src/routers/index.jsx b/src/routers/index.jsx index c77cf68f..1f6683f8 100644 --- a/src/routers/index.jsx +++ b/src/routers/index.jsx @@ -43,6 +43,7 @@ const Barcode = lazy(() => import('@pages/barcode')) const Print = lazy(() => import('@pages/print')) const PostMessage = lazy(() => import('@pages/postmessage')) const GeoChart = lazy(() => import('@pages/geoChart')) +const Motion = lazy(() => import('@pages/motion')) // const ReactPdf = lazy(() => import('@pages/reactPdf')) const MyIframe = lazy(() => import('@pages/postmessage/myIframe')) const Exception403 = lazy(() => import('@stateless/Exception/exception403')) @@ -83,6 +84,14 @@ const rootRouter = [ auth: true, element: lazyLoad(ParallaxVert), }, + { + index: false, + path: 'motion', + name: 'Motion', + key: '/motion', + auth: false, + element: lazyLoad(Motion), + }, { index: false, path: 'gantt',