Checkbox Gấu với Javascript



Chia sẻ code làm Checkbox sử dụng Javascript với kiểu Gấu cực ngầu

1. HTML

							

2. CSS

							* {
  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%;
}
.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%);
}						

3. JAVASCRIPT

							const { PropTypes, React, ReactDOM, TimelineMax, TweenMax } = window
const { Component, Fragment } = React
const { render } = ReactDOM
const rootNode = document.getElementById('app')
const randomInRange = (max, min = 1) => Math.random() * (max - min) + min
const armLimit = randomInRange(2, 0)
const headLimit = randomInRange(armLimit + 3, armLimit + 1)
const angerLimit = randomInRange(headLimit + 3, headLimit + 1)

class App extends Component {
  static defaultProps = {
    armLimit,
    angerLimit,
    headLimit,
    armDuration: 0.2,
    bearDuration: 0.25,
    checkboxDuration: 0.25,
    pawDuration: 0.1,
  }
  static propTypes = {
    armLimit: PropTypes.number,
    angerLimit: PropTypes.number,
    headLimit: PropTypes.number,
    armDuration: PropTypes.number,
    bearDuration: PropTypes.number,
    checkboxDuration: PropTypes.number,
    pawDuration: PropTypes.number,
  }
  state = {
    checked: false,
    count: 0,
  }
  /**
   * Generate a random timeline for the bear based on the count
   */
  grabBearTL = () => {
    const { ARM, ARM_WRAP, BEAR, PAW, SWEAR, props, state } = this
    const { count } = state
    const {
      armLimit,
      armDuration,
      bearDuration,
      checkboxDuration,
      pawDuration,
    } = props
    /**
     * 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 = () => {
      this.setState({
        checked: false,
        count: count + 1,
      })
    }
    let onBearComplete = () => {}
    if (Math.random() > 0.5 && count > angerLimit)
      onBearComplete = () => (SWEAR.style.display = 'block')
    const base = armDuration + armDuration + pawDuration
    const preDelay = randomInRange(1, 0)
    const delay = count > armLimit ? base + bearDuration + preDelay : base
    const bearTL = new TimelineMax({ delay: Math.random(), onComplete })
    bearTL
      .add(
        count > armLimit
          ? TweenMax.to(BEAR, bearDuration, {
              onComplete: onBearComplete,
              y: bearTranslation,
            })
          : () => {}
      )
      .to(ARM_WRAP, armDuration, { x: 50 }, count > armLimit ? preDelay : 0)
      .to(ARM, armDuration, { scaleX: 0.7 })
      .to(PAW, pawDuration, {
        scaleX: 0.8,
        onComplete: () => (SWEAR.style.display = 'none'),
      })
      .to(this.BG, checkboxDuration, { backgroundColor: '#aaa' }, delay)
      .to(this.INDICATOR, checkboxDuration, { x: '0%' }, delay)
      .to(PAW, pawDuration, { scaleX: 0 }, delay)
      .to(ARM, pawDuration, { scaleX: 1 }, delay + pawDuration)
      .to(ARM_WRAP, armDuration, { x: 0 }, delay + pawDuration)
      .to(BEAR, bearDuration, { y: '100%' }, delay + pawDuration)
    return bearTL
  }
  showTimeline = () => {
    const { BG, INDICATOR, grabBearTL } = this
    const { checkboxDuration } = this.props
    const checkTL = new TimelineMax({})
    checkTL
      .add(TweenMax.to(BG, checkboxDuration, { backgroundColor: '#2eec71' }))
      .add(TweenMax.to(INDICATOR, checkboxDuration, { x: '100%' }), 0)
      .add(grabBearTL(), checkboxDuration)
  }
  onChange = () => {
    if (this.state.checked) return
    this.setState(
      {
        checked: true,
      },
      this.showTimeline
    )
  }
  onHover = () => {
    if (Math.random() > 0.5 && this.state.count > armLimit) {
      TweenMax.to(this.BEAR, this.props.bearDuration / 2, { y: '40%' })
    }
  }
  offHover = () => {
    if (!this.state.checked) {
      TweenMax.to(this.BEAR, this.props.bearDuration / 2, { y: '100%' })
    }
  }
  render = () => {
    const { onChange, offHover, onHover, props, state } = this
    const { angerLimit } = props
    const { checked, count } = state
    return (
      
        
(this.SWEAR = s)} className="bear__swear"> #@$%*!
(this.BEAR = b)} className="bear" viewBox="0 0 284.94574 359.73706" preserveAspectRatio="xMinYMin"> {count >= angerLimit && ( )}
(this.ARM_WRAP = w)} className="bear__arm-wrap"> (this.ARM = a)} className="bear__arm" viewBox="0 0 250.00001 99.999997" preserveAspectRatio="xMinYMin">
(this.PAW = p)} className="bear__paw" />
(this.BG = b)} className="checkbox__bg" />
(this.INDICATOR = i)} className="checkbox__indicator" />
) } } render(, rootNode)

Mong bài viết giúp ích được các bạn phần nào trong thiết kế Web. Hãy nhấn nút để mọi người cùng học hỏi kiến thức mới nhé. Cảm ơn các bạn đã quan tâm Forum.