>首页> IT >

手把手教你使用Vue3实现图片散落效果

时间:2022-04-27 10:56:41       来源:转载
基于Vue3怎么实现图片散落效果?下面本篇文章给大家介绍一下使用Vue3实现图片散落效果的方法,希望对大家有所帮助!

今天又是美好的摸鱼一天,刚刚进入职场,觉得一切都很新鲜,导师给的任务也不多(要是每天都是这样就好了),于是开始带薪学习。(学习视频分享:vuejs教程)

做啥好呢

没事在网上乱逛的时候,偶然间看到一个动画效果不错,就决定上手做一些,简单的说就是一个完整的图片,在一段时间之后回突然破裂开来,觉得很有意思,就新建了一个文件夹。

出现问题

一下午的摸鱼时光,间公司熙熙攘攘,我在其中却格格不入(太闲了),不知多少人投来质疑的眼光(这家伙不工作吗),但我只沉浸在我的代码里。终于勉强完成了一个不怎么丑的版本。

原理

图片破裂效果说白了就是搞了100个div,每个div都有自己的背景图片,通过backgroundPosition属性来控制每个div的背景图片方位,最后拼在一起,就像一张完整的图片一样,给每个div都加上动画效果,每个div的旋转角度不同,移动距离不同,移动方位不同来让整个图片像玻璃一样散开来。

HTML结构

这里用到了两个div,#break是用作为100个div的容器,#InBox是用来绑定下一张的背景图片

准备5张图片

import bgImg5 from "../../assets/img/1/y1.png"import bgImg4 from "../../assets/img/1/y2.png"import bgImg3 from "../../assets/img/1/y3.png"import bgImg2 from "../../assets/img/1/y4.png"import bgImg6 from "../../assets/img/1/y5.png"import { ref, onMounted, onUnmounted } from "vue"let index = 0onMounted(() => {  let imageSrcArr = [bgImg2, bgImg3, bgImg4, bgImg5, bgImg6]  let imgloadPromiseArr: Array> = []  let imageArr: Array = []  for (let i = 0; i < imageSrcArr.length; i++) {    imgloadPromiseArr[i] = new Promise((resolve, reject) => {      let img = new Image()      img.src = imageSrcArr[i]      img.onload = () => {        resolve(img)      }    })  }  imgloadPromiseArr.forEach(item => {    item.then(res => {      imageArr.push(`url(${(res).currentSrc})`)      index = imageArr.length    })  })  })

创建div

通过createElement创建200个div,每个div绑定长宽,给div添加背景图片,使用backgroundPosition来让整个div变得像一张图片,给div绑定动画效果。

for (let i = 0; i < 100; i++) {      let div = document.createElement("div")      let div1 = document.createElement("div")      div.style.width = "76px"      div.style.height = "41px" // 这里为什么是41px后面会提到      div1.style.width = "76px"      div1.style.height = "40px"      div1.style.overflow = "hidden"      div.style.boxSizing = "border-box"      div.style.backgroundImage = imageArr[0]      let positionX = -(i % 10) * 76 + "px"      let positionY = -Math.floor(i / 10) * 40 + "px"      div.style.backgroundPosition = positionX + " " + positionY      div.style.backgroundSize = "760px 400px"      let style = document.styleSheets[0]      style.insertRule(`@keyframes secondrotate${i}        {            0%,30%{                transform:scale(1)            }            70%            {transform: rotateX(${180 + Math.random() * 720}deg) rotateY(${180 + Math.random() * 720}deg)}            100%            {transform: rotateX(${180 + Math.random() * 720}deg) rotateY(${180 + Math.random() * 720}deg)}        }`)      style.insertRule(`@keyframes secondrotateS${i}        {            0%,32%{                transform:scale(1);opacity:1;            }70%            {transform: translateZ(${300 + Math.random() * 1500}px) translate(${(0.5 - Math.random()) * 500}px,${        (0.5 - Math.random()) * 500      }px);opacity:0}            100%            {transform: translateZ(${300 + Math.random() * 1500}px) translate(${(0.5 - Math.random()) * 500}px,${        (0.5 - Math.random()) * 500      }px);opacity:0}        }`)      div1.style.animation = `secondrotateS${i} 4.5s ease-out infinite`      div.style.animation = `secondrotate${i} 4.5s ease-out infinite`      div.style.transformOrigin = `center center`      div1.appendChild(div)      dom.appendChild(div1)}

切换背景图片

通过zIndex来让当前展示的div是哪一个

前面说过,InBox是展示的下一张图片,在breakBox散落完成之后,让breakBox的zIndex降低,展示出下一张图片,随后带有100个div的breakBox完成下一张图片的渲染,zIndex提高,展示出来

let count = 0 let repeat = true let breakBox: HTMLDivElement = document.querySelector("#break")! let InBox: HTMLDivElement = document.querySelector("#InBox")!  function changeImage(InBox: HTMLDivElement) {    if (repeat) {      breakBox.style.zIndex = "-10"      count++      count = count === index ? 0 : count      repeat = false      setTimeout(() => {        repeat = true        breakBox.style.zIndex = "100"        let currentImageLength = count === index - 1 ? 0 : count + 1        InBox.style.backgroundImage = imageArr[currentImageLength]      }, 1000)    }  }

每次动画完成之后会去调上面这个方法,为了能在div碎片破碎完毕,展示下一张图片,使用定时器将该方法进行延迟处理 4s是因为div碎片在4s后完全消失。(动画在运行70%的时候,透明度为0)

const timer1 = ref()const timer2 = ref()for (let i = 0; i < 100; i++) {      let div = document.createElement("div")      let div1 = document.createElement("div")      div.style.width = "76px"      div.style.height = "41px"      div1.style.width = "76px"      div1.style.height = "40px"      div1.style.overflow = "hidden"      div.style.boxSizing = "border-box"      div.style.backgroundImage = imageArr[0]      let positionX = -(i % 10) * 76 + "px"      let positionY = -Math.floor(i / 10) * 40 + "px"      div.style.backgroundPosition = positionX + " " + positionY      div.style.backgroundSize = "760px 400px"      let style = document.styleSheets[0]      style.insertRule(`@keyframes secondrotate${i}        {            0%,30%{                transform:scale(1)            }            70%            {transform: rotateX(${180 + Math.random() * 720}deg) rotateY(${180 + Math.random() * 720}deg)}            100%            {transform: rotateX(${180 + Math.random() * 720}deg) rotateY(${180 + Math.random() * 720}deg)}        }`)      style.insertRule(`@keyframes secondrotateS${i}        {            0%,32%{                transform:scale(1);opacity:1;            }70%            {transform: translateZ(${300 + Math.random() * 1500}px) translate(${(0.5 - Math.random()) * 500}px,${        (0.5 - Math.random()) * 500      }px);opacity:0}            100%            {transform: translateZ(${300 + Math.random() * 1500}px) translate(${(0.5 - Math.random()) * 500}px,${        (0.5 - Math.random()) * 500      }px);opacity:0}        }`)      div1.style.animation = `secondrotateS${i} 4.5s ease-out infinite`      div.style.animation = `secondrotate${i} 4.5s ease-out infinite`      div.style.transformOrigin = `center center`      div.addEventListener("animationstart", () => {        timer1.value = setTimeout(() => {          changeImage(InBox)          div.style.backgroundImage = imageArr[count]        }, 4000)      })      div.addEventListener("animationiteration", () => {        timer2.value = setTimeout(() => {          changeImage(InBox)          div.style.backgroundImage = imageArr[count]        }, 4000)      })      div1.appendChild(div)      dom.appendChild(div1)    }

div存在间隙的问题

在100个div展示之后会出现这样的线,在经过多次尝试之后,找到了方法,将div的高度变大,div1设置overflow:hidden; 线回消失

代码详情

<script setup>import bgImg5 from "../../assets/img/1/y1.png"import bgImg4 from "../../assets/img/1/y2.png"import bgImg3 from "../../assets/img/1/y3.png"import bgImg2 from "../../assets/img/1/y4.png"import bgImg6 from "../../assets/img/1/y5.png"import { ref, onMounted, onUnmounted } from "vue"const timer1 = ref()const timer2 = ref()const showImg = ref(false)onMounted(() => {  let imageSrcArr = [bgImg2, bgImg3, bgImg4, bgImg5, bgImg6]  let imgloadPromiseArr: Array> = []  let imageArr: Array = []  for (let i = 0; i < imageSrcArr.length; i++) {    imgloadPromiseArr[i] = new Promise((resolve, reject) => {      let img = new Image()      img.src = imageSrcArr[i]      img.onload = () => {        resolve(img)      }    })  }  imgloadPromiseArr.forEach(item => {    item.then(res => {      imageArr.push(`url(${(res).currentSrc})`)      index = imageArr.length    })  })  showImg.value = true  let repeat = true  function changeImage(InBox: HTMLDivElement) {    if (repeat) {      breakBox.style.zIndex = "-10"      count++      count = count === index ? 0 : count      repeat = false      setTimeout(() => {        repeat = true        breakBox.style.zIndex = "100"        let currentImageLength = count === index - 1 ? 0 : count + 1        InBox.style.backgroundImage = imageArr[currentImageLength]      }, 1000)    }  }  let count = 0  let index = 0  let breakBox: HTMLDivElement = document.querySelector("#break")!  let InBox: HTMLDivElement = document.querySelector("#InBox")!  InBox.style.backgroundImage = imageArr[1]  const appendDom = (dom: HTMLElement) => {    for (let i = 0; i < 100; i++) {      let div = document.createElement("div")      let div1 = document.createElement("div")      div.style.width = "76px"      div.style.height = "41px"      div1.style.width = "76px"      div1.style.height = "40px"      div1.style.overflow = "hidden"      div.style.boxSizing = "border-box"      div.style.backgroundImage = imageArr[0]      let positionX = -(i % 10) * 76 + "px"      let positionY = -Math.floor(i / 10) * 40 + "px"      div.style.backgroundPosition = positionX + " " + positionY      div.style.backgroundSize = "760px 400px"      let style = document.styleSheets[0]      style.insertRule(`@keyframes secondrotate${i}        {            0%,30%{                transform:scale(1)            }            70%            {transform: rotateX(${180 + Math.random() * 720}deg) rotateY(${180 + Math.random() * 720}deg)}            100%            {transform: rotateX(${180 + Math.random() * 720}deg) rotateY(${180 + Math.random() * 720}deg)}        }`)      style.insertRule(`@keyframes secondrotateS${i}        {            0%,32%{                transform:scale(1);opacity:1;            }70%            {transform: translateZ(${300 + Math.random() * 1500}px) translate(${(0.5 - Math.random()) * 500}px,${        (0.5 - Math.random()) * 500      }px);opacity:0}            100%            {transform: translateZ(${300 + Math.random() * 1500}px) translate(${(0.5 - Math.random()) * 500}px,${        (0.5 - Math.random()) * 500      }px);opacity:0}        }`)      div1.style.animation = `secondrotateS${i} 4.5s ease-out infinite`      div.style.animation = `secondrotate${i} 4.5s ease-out infinite`      div.style.transformOrigin = `center center`      div.addEventListener("animationstart", () => {        timer1.value = setTimeout(() => {          changeImage(InBox)          div.style.backgroundImage = imageArr[count]        }, 4000)      })      div.addEventListener("animationiteration", () => {        timer2.value = setTimeout(() => {          changeImage(InBox)          div.style.backgroundImage = imageArr[count]        }, 4000)      })      div1.appendChild(div)      dom.appendChild(div1)    }  }  appendDom(breakBox)})onUnmounted(() => {  typeof timer1 === "number" && clearTimeout(timer1)  typeof timer2 === "number" && clearTimeout(timer2)})</script>

(学习视频分享:web前端开发、编程入门)

以上就是手把手教你使用Vue3实现图片散落效果的详细内容,更多请关注php中文网其它相关文章!

关键词: 背景图片 手把手教你 动画效果