react实现与小熊互动的checkbox动画效果
代码语言:html
所属分类:动画
代码描述:react实现与小熊互动的checkbox动画效果
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <style> * { box-sizing: border-box; background: #947cb0; } body { -webkit-box-align: center; align-items: center; display: -webkit-box; display: flex; -webkit-box-pack: center; justify-content: center; font-family: 'Arial', sans-serif; min-height: 100vh; padding: 0; margin: 0; overflow: hidden; } .mask { position: fixed; top: 50%; left: 0; right: 0; bottom: 0; background: #947cb0; } .bear { width: 100%; background: transparent; -webkit-transform: translate(0, 100%); transform: translate(0, 100%); } .bear__swear { display: none; position: absolute; left: 105%; top: 0; background: #fff; font-weight: bolder; padding: 10px; border-radius: 8px; } .bear__swear:before { content: ''; background: #fff; position: absolute; top: 90%; right: 70%; height: 30px; width: 30px; clip-path: polygon(0 100%, 100% 0, 50% 0); -webkit-clip-path: polygon(0 100%, 100% 0, 50% 0); } .bear__wrap { width: 100px; left: 50%; position: absolute; top: 50%; -webkit-transform: translate(-15%, -50%) rotate(5deg) translate(0, -75%); transform: translate(-15%, -50%) rotate(5deg) translate(0, -75%); background: transparent; } .bear__arm-wrap { background: transparent; position: fixed; height: 30px; width: 90px; z-index: 4; top: 50%; left: 50%; -webkit-transform: translate(0, -50%) rotate(0deg); transform: translate(0, -50%) rotate(0deg); } .bear__arm { background: transparent; -webkit-transform-origin: left; transform-origin: left; position: absolute; height: 100%; width: 100%; top: 50%; left: 50%; -webkit-transform: translate(-35%, -50%) scaleX(1); transform: translate(-35%, -50%) scaleX(1); } .bear__paw { background: #784421; border-radius: 100%; position: fixed; height: 30px; width: 30px; z-index: 10; top: 50%; left: 50%; -webkit-transform-origin: right; transform-origin: right; -webkit-transform: translate(80px, -15px) scaleX(0); transform: translate(80px, -15px) scaleX(0); } .checkbox { border-radius: 50px; height: 100px; position: fixed; width: 200px; z-index: 5; top: 50%; left: 50%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); } .checkbox [type='checkbox'] { cursor: pointer; border-radius: 50px; position: absolute; outline: 0; top: 0; right: 0; bottom: 0; left: 0; opacity: 0; z-index: 10; height: 100%; width: 100%; margin: 0; } .checkbox__bg { background: #aaa; border-radius: 50px; height: 100%; width: 100%; z-index: 10; } .checkbox__indicator { background: transparent; height: 100%; width: 50%; border-radius: 100%; position: absolute; top: 0; left: 0; } .checkbox__indicator:after { content: ''; border-radius: 100%; height: 85%; width: 85%; background: #fff; position: absolute; top: 50%; left: 50%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); } </style> </head> <body translate="no"> <div id="app"></div> <script type="text/javascript" src="http://repo.bfw.wiki/bfwrepo/js/react.dev.js"></script> <script type="text/javascript" src="http://repo.bfw.wiki/bfwrepo/js/react-dom.dev.js"></script> <script type="text/javascript" src="http://repo.bfw.wiki/bfwrepo/js/gsap.3.3.1.js"></script> <script> const { React: { useState, useRef, useEffect, Fragment }, ReactDOM: { render }, gsap: { set, to, timeline, utils: { random } } } = window; const rootNode = document.getElementById('app'); const armLimit = random(0, 3); const headLimit = random(armLimit + 1, armLimit + 3); const angerLimit = random(headLimit + 1, headLimit + 3); const armDuration = 0.2; const bearDuration = 0.25; const checkboxDuration = 0.25; const pawDuration = 0.1; const SOUNDS = { ON: new Audio('http://repo.bfw.wiki/bfwrepo/sound/5f3e2258e5862.mp3'), OFF: new Audio('http://repo.bfw.wiki/bfwrepo/sound/5f3e224e3b305.mp3'), GROAN: new Audio('http://repo.bfw.wiki/bfwrepo/sound/5f3e226f9cacf.mp3') }; SOUNDS.GROAN.playbackRate = 2; const App = () => { const [checked, setChecked] = useState(false); const [count, setCount] = useState(1); const bearRef = useRef(null); const swearRef = useRef(null); const armWrapRef = useRef(null); const pawRef = useRef(null); const armRef = useRef(null); const bgRef = useRef(null); const indicatorRef = useRef(null); const onHover = () => { if (Math.random() > 0.5 && count > armLimit) { to(bearRef.current, bearDuration / 2, { y: '40%' }); } }; const offHover = () => { if (!checked) { to(bearRef.current, bearDuration / 2, { y: '100%' }); } }; const onChange = () => { if (checked) return; setChecked(true); }; useEffect(() => { const grabBearTL = () => { /** * Different height translations for the bear elements * * Paw will go to scaleX 0.8 * Arm scaleX goes down to 0.7 * Arm wrap translates to 50% or 50px * Bear goes 100% -> 40% -> 0 */ let bearTranslation; if (count > armLimit && count < headLimit) { bearTranslation = '40%'; } else if (count >= headLimit) { bearTranslation = '0%'; } const onComplete = () => { setChecked(false); setCount(count + 1); }; let onBearComplete = () => {}; if (Math.random() > 0.5 && count > angerLimit) onBearComplete = () => { SOUNDS.GROAN.play(); set(swearRef.current, { display: 'block' }); }; const base = armDuration + armDuration + pawDuration; const preDelay = Math.random(); const delay = count > armLimit ? base + bearDuration + preDelay : base; const bearTL = timeline({ delay: Math.random(), onComplete }); bearTL. add( count > armLimit ? to(bearRef.current, { duration: bearDuration, onComplete: onBearComplete, y: bearTranslation }) : () => {}). to( armWrapRef.current, { x: 50, duration: armDuration }, count > armLimit ? preDelay : 0). to(armRef.current, { scaleX: 0.7, duration: armDuration }). to(pawRef.current, { duration: pawDuration, scaleX: 0.8, onComplete: () => set(swearRef.current, { display: 'none' }) }). to( bgRef.current, { onStart: () => { SOUNDS.OFF.play(); }, duration: checkboxDuration, backgroundColor: '#aaa' }, delay). to( indicatorRef.current, { duration: checkboxDuration, x: '0%' }, delay). to(pawRef.current, { duration: pawDuration, scaleX: 0 }, delay). to( armRef.current, { duration: pawDuration, scaleX: 1 }, delay + pawDuration). to( armWrapRef.current, { duration: armDuration, x: 0 }, delay + pawDuration). to( bearRef.current, { duration: bearDuration, y: '100%' }, .........完整代码请登录后点击上方下载按钮下载查看
网友评论0