react实现与小熊互动的checkbox动画效果

代码语言:html

所属分类:动画

代码描述:react实现与小熊互动的checkbox动画效果

代码标签: 小熊 互动 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