js神秘的表单提交动画效果

js 神秘的表单提交动画效果,即输入的详细信息和表单提交会消失在天空中。

最终实现的效果:

js 神秘的表单提交动画效果

HTML 代码:

<div class="wrapper flex_box">
    <form>
        <div class="input">
            <label>
          name
        </label>
            <input class="name" placeholder="your name..." type="text">
        </div>
        <div class="input">
            <label>
          comment
        </label>
            <input class="comment" placeholder="enter whatever you feel like.." type="text">
        </div>
        <div class="button_wrapper">
            <button>
          submit
        </button>
        </div>
    </form>
</div>

<div class="cover"></div>

CSS 代码:

 @import url('https://fonts.googleapis.com/css2?family=Nunito:wght@300&display=swap');

* {
  box-sizing: border-box;
}

body {
  padding: 0;
  margin: 0;
  font-family: 'Nunito', sans-serif;
  background-color: #262527;
  overflow:hidden;
}

input, textarea, button {
  font-family: 'Nunito', sans-serif;
}

.wrapper {
  width: 100%;
  height: 100vh;
  color: #fae881;
  overflow:hidden;
}

.flex_box {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}

.box {
  position: absolute;
  background-color: black;
  width: 50px;
  height: 50px;
  transition: 0.2s;
}

form {
  position: absolute;
  padding: 30px 20px;
  width: 320px;
  border-radius: 7px;
  background-color: white;
  backdrop-filter: blur(5px);
  background-color: rgba(158, 189, 199, 0.288);
  overflow: hidden;
}

.input {
  display: flex;
  flex-direction: column;
}

input, textarea {
  padding: 8px 10px;
  margin: 3px 8px 16px 8px;
  background-color: rgba(222, 239, 248, 0.877);
  border: 0px transparent;
  border-radius: 5px;
  color:rgb(97, 4, 184);
  font-size: 16px;
  word-break: break-all; /* haven't found the best solution here yet, paragraphs are difficult to deal with */
  hyphens: auto;
  z-index: 1;
}

label {
  margin: 0 8px;
  font-size: 14px;
  color: white;
}

.button_wrapper {
  display: flex;
  justify-content: flex-end;
}

button {
  padding: 8px 14px;
  margin: 20px 8px 0 0;
  border-width: 0px;
  border-radius: 5px;
  color: white;
  background-color: #b69269;
  transition: 0.3s;
  z-index: 1;
}

button:hover {
  color: rgb(60, 35, 153);
  background-color: white;
}

.star {
  position: absolute;
  transition: 1s;
  overflow: hidden;
  opacity: 1;
  height: 15px;
  width: 15px;
  border-radius: 50%;
  z-index: -90;
}

.star svg {
  height: 100%;
  width: auto;
}

.star_inner {
  height: 15px;
}

.cover {
  position: fixed;
  top: 0px;
  left: 0px;
  pointer-events: none;
  height: 100vh;
  width: 100%;
  z-index: 999;
  overflow: hidden;
}

.ghost {
  position: absolute;
  padding: 8px 10px;
  border: 0px transparent;
  border-radius: 5px;
  z-index: 1;
  color:rgb(97, 4, 184);
  font-size: 16px;
  display: flex;
  flex-wrap: wrap;
}

.ghost > div {
  margin: 0;
  padding: 0;
  transition: 5s;
}

.blank {
  width: 4px;
}

form.fade {
  animation: fade forwards ease 5s;
}

@keyframes fade {
  0% {
    opacity: 1;
    transform: translate(0vw, 0) skew(0);
  }
  20% {
    opacity: 0.8;
    transform: translate(0vw, 0) skew(0);
  }

  100% {
    opacity: 0;
    transform: translate(50vw, -50vh) skew(-45deg);
  }
}

form.fade_in {
  animation: fade_in forwards ease 6s;
}

@keyframes fade_in {
  0% {
    opacity: 0;
    transform: translate(-50vw, 150vh) skew(-45deg);
  }
  50% {
    opacity: 0;
  }
  100% {
    opacity: 1;
    transform: translate(0) skew(0);
  }
}

::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
  color: rgb(140, 145, 216);
}

:-ms-input-placeholder { /* Internet Explorer 10-11 */
  color: rgb(140, 145, 216);
}

::-ms-input-placeholder { /* Microsoft Edge */
  color: rgb(140, 145, 216);
}

.sign {
  position: absolute;
  color: white;
  bottom: 10px;
  right: 10px;
  font-size: 10px;
}

a {
  color: white;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

JS 代码:

function init() {
  //animating form
  const button = document.querySelector('button')
  const name = document.querySelector('.name')
  const comment = document.querySelector('.comment')
  const cover = document.querySelector('.cover')
  const form = document.querySelector('form')
  let letterCount = 0

  const createGhostLetters = (text, className) =>{
    return text.split('').map( letter =>{
      return `
        <div class="${className} ${letter === ' ' ? ' blank' : ''}" >
          ${letter}
        </div>
      `
    }).join('')
  }

  const createGhostDiv = (target, className) =>{
    if (!target.value) return
    target.placeholder = ''
    const ghostDiv = document.createElement('div')
    const targetSpec = target.getBoundingClientRect()
    ghostDiv.classList.add('ghost')
    ghostDiv.innerHTML = createGhostLetters(target.value, className)

    ghostDiv.style.top = `${targetSpec.y}px`
    ghostDiv.style.left = `${targetSpec.x}px`
    ghostDiv.style.height = `${targetSpec.height}px`
    ghostDiv.style.width = `${targetSpec.width}px`

    cover.appendChild(ghostDiv)
    target.value = ''
  }

  const setupGhostLetterMotion = (target, className)=>{
    createGhostDiv(target, className)

    const letters = document.querySelectorAll(`.${className}`)
    letters.forEach((letter,i)=>{
      const letterSpec = letter.getBoundingClientRect()
      
      letter.style.top = `${letterSpec.y}px`
      letter.style.left = `${letterSpec.x}px`
      letter.style.color = 'white'
      letter.style.transition = '1s'

      setTimeout(()=>{   
        letter.style.position = 'fixed'
        letter.style.transition = '5s'
        letter.style.top = `-${window.innerHeight / 2}px`
        letter.style.left = `${letterSpec.x + window.innerWidth / 2}px`   
      },(letters.length - i) * 150)
    })
    letterCount = letterCount < letters.length ? letters.length : letterCount
  }


  const handleSubmit = e =>{
    e.preventDefault()
    form.classList.remove('fade_in')
    form.classList.add('fade')
    setupGhostLetterMotion(name,'name_letter')
    setupGhostLetterMotion(comment,'comment_letter')
  
    setTimeout(()=>{
      form.classList.remove('fade')
      form.classList.add('fade_in')
      name.placeholder = 'your name...?'
      comment.placeholder = 'enter whatever you feel like...'
      letterCount = 0
    },3000 + (letterCount * 100))
  }

  button.addEventListener('click', (e)=>handleSubmit(e))

  const starSvg = `
  <svg x="0px" y="0px" width="565.4px" height="51.4px" viewBox="0 0 565.4 51.4" >
    <style type="text/css">
    .st0{fill:#91a7b4;}
    .st1{fill:#b69269;}
    .st2{fill:#FFFFFF;}
    </style>
    <path class="st0" d="M559.7,28.5h-11.5v5.7h-5.7v0.1v17.1h-5.7V34.3v-0.1h-5.7v-5.7h-11.4v-5.7h11.4v-5.7h5.7V0h5.7v17.1h5.7v5.7
    h11.5V28.5z"/>
    <path class="st0" d="M445.5,28.7h-5.7v5.7h-5.7v-5.7h-5.7V23h5.7v-5.7h5.7V23h5.7V28.7z"/>
    <path class="st0" d="M496.9,28.6h-5.7V40h-5.7V28.6h-5.7v-5.7h5.7V11.5h5.7v11.4h5.7V28.6z"/>
    <path class="st1" d="M405.5,28.6H394v5.7h-5.7v0.1v17.1h-5.7V34.4v-0.1h-5.7v-5.7h-11.4v-5.7h11.4v-5.7h5.7V0.1h5.7v17.1h5.7v5.7
    h11.5V28.6z"/>
    <path class="st2" d="M148.5,28.5H137v5.7h-5.7v0.1v17.1h-5.7V34.3v-0.1h-5.7v-5.7h-11.4v-5.7h11.4v-5.7h5.7V0h5.7v17.1h5.7v5.7h11.5
    V28.5z"/>
    <path class="st2" d="M34.3,28.7h-5.7v5.7h-5.7v-5.7h-5.7V23h5.7v-5.7h5.7V23h5.7V28.7z"/>
    <path class="st2" d="M85.7,28.6H80V40h-5.7V28.6h-5.7v-5.7h5.7V11.5H80v11.4h5.7V28.6z"/>
    <path class="st1" d="M291.2,28.7h-5.7v11.4h-5.7V28.7h-5.7V23h5.7V11.6h5.7V23h5.7V28.7z"/>
    <path class="st1" d="M348.4,28.6h-5.7v5.7H337v11.5h-5.7V34.3h-5.7v-5.7h-5.7v-5.7h5.7v-5.7h5.7V5.8h5.7v11.4h5.7v5.7h5.7
    L348.4,28.6L348.4,28.6z"/>
    <g>
    <g id="XMLID_7_">
      <g>
        <rect x="177.1" y="22.9" class="st1" width="5.7" height="5.7"/>
      </g>
    </g>
    </g>
    <g>
    <g id="XMLID_6_">
      <g>
        <rect x="225.6" y="20" class="st1" width="11.5" height="11.4"/>
      </g>
    </g>
    </g>
  </svg>
  `

  const animationPatterns = [
    ['0','1'],['0','1'],['0','1'],['0','1'],['0','1'],
    ['1','1'],['1','1'],['1','1'],['1','1'],
    ['2','2'],['2','2'],
    ['0','2'],['0','2'],
    ['3','5'],['3','5'],
    ['8','9'],['8','9'],
    ['3','6'],['3','6'],
    ['9','10'],['9','10'],
    ['10','10'],['10','10'],
    ['3','7'],
    ['6','7']
  ]

  const wrapper = document.querySelector('.wrapper')
  const frameSize = 15


  //star blinking animation
  const animateStar = (target, start, end, speed) => {
    let i = start   
    setInterval(function () {
      target.style.margin = `0px ${-(i * frameSize)}px`
      if (i >= end) {
        i = start
      } else {
        i++
      }
    }, speed)
  }


  //position stars
  const stars = new Array(70).fill('')
  stars.forEach(()=>{
    const animationPattern = animationPatterns[Math.floor(Math.random() * animationPatterns.length)]
    const speed = Math.random() < 0.1 ?
      140
      :
      300
  
    const starDiv = document.createElement('div')
    starDiv.classList.add('star')
      
    const starInside = document.createElement('div')
    starInside.classList.add('star_inner')
    starInside.innerHTML = starSvg
    starInside.style.width = `${frameSize * 11}px`
  
    starDiv.appendChild(starInside)
    starDiv.style.top = `${Math.ceil(Math.random() * 100)}%`
    starDiv.style.left = `${Math.ceil(Math.random() * 100)}%`
    wrapper.appendChild(starDiv)
  
    animateStar(starInside, animationPattern[0], animationPattern[1], speed)
  })

}

window.addEventListener('DOMContentLoaded', init)

更多前端特效代码,请关注码云笔记技术博客,每日为你整理分享最好的前端知识。

「点点赞赏,手留余香」

0

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » js神秘的表单提交动画效果

发表回复