0

0

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

青灯夜游

青灯夜游

发布时间:2022-04-27 10:57:19

|

2772人浏览过

|

来源于掘金社区

转载

基于vue3怎么实现图片散落效果?下面本篇文章给大家介绍一下使用vue3实现图片散落效果的方法,希望对大家有所帮助!

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

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

做啥好呢

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

出现问题

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

立即学习前端免费学习笔记(深入)”;

1.png

原理

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

HTML结构

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

Skybox AI
Skybox AI

一键将涂鸦转为360°无缝环境贴图的AI神器

下载

准备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 = 0
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
    })
  })
  })

创建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存在间隙的问题

2.png

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

代码详情





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

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

0

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

0

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

0

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

0

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

19

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

16

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

17

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

2

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Vue 教程
Vue 教程

共42课时 | 7.4万人学习

Vue3.x 工具篇--十天技能课堂
Vue3.x 工具篇--十天技能课堂

共26课时 | 1.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号