【CSS】398- 原生JS实现DOM爆炸效果
爆炸动效分享
前言
此次分享是一次自我组件开发的总结,还是有很多不足之处,望各位大大多提宝贵意见,互相学习交流。
分享内容介绍
通过原生js代码,实现粒子爆炸效果组件 组件开发过程中,使用到了公司内部十分高效的工程化环境,特此打个广告:新浪移动诚招各种技术大大!可以私聊投简历哦!
效果预览
效果分析
* 点击作为动画开始的起点,自动结束
* 每次效果产生多个抛物线粒子运动的元素,方向随机,展示内容不一样,有空间上Z轴的大小变化
* 需求上可以无间隔点击,即第一组动画未结束可播放第二组动画
* 动画基本执行时长一致
css操作态变换(如focus)使子元素执行动画
`不可取,效果可多次连点,css状态变换与需求不符`
Js 控制动画开始,事先写好css动画预置,通过class 包含选择器切换动画 例如:.active .items{animation:xxx ...;}
`不可取,单次执行动画没有问题,但是存在效果的固定,以及无法连续执行动画`
事先写好大量动画,隐藏大量dom元素,动画开始随机选取dom元素执行自己唯一的动画keyframes
`实现层面来说,行得通,但是评论列表长的时候,dom数量巨大,且css大量动画造成代码量沉重、无随机性`
抛弃css动画,使用canvas 绘制动画
`可行,但是canvas维护成本略高,且自定义功能难设计,屏幕适配也有一定成本`
js做dom创建,生成随机css @keyframes
`可行,但是创建style样式表,引发css重新渲染页面,会导致页面的性能下降,且抛物线css的复杂度不低,暂不作为首选`
js 刷帧 做dom渲染
`可行,但是刷帧操作会造成性能压力`
结论
canvas虽说可行,但由于其开发弊端 本次分享不以canvas为分享内容,而是使用最后一种 js刷帧的dom操作
组件结构
由截图分享,动画可以分为两个模块,首先,随机发散的粒子具有共性:抛物线动画,淡出,渲染表情
而例子数量变多之后则为截图中的效果
但是,由于性能原因,我们需要做到粒子的掌控,实现资源再利用,那么还需要第二个模块,作为粒子的管控组件
所以:此功能可使用两个模块进行开发:partical.js 粒子功能 与 boom.js 粒子管理
实现 Partical.js
1. 前置资源:抛物线运动的物理曲线需要使用Tween.js提供的速度函数
若不想引入Tween.js 可以使用以下代码
/** Tween.js* t: current time(当前时间);* b: beginning value(初始值);* c: change in value(变化量);* d: duration(持续时间)。* you can visit '缓动函数速查表' to get effect*/
const Quad = {
easeIn: function(t, b, c, d) {
return c * (t /= d) * t + b;
},
easeOut: function(t, b, c, d) {
return -c *(t /= d)*(t-2) + b;
},
easeInOut: function(t, b, c, d) {
if ((t /= d / 2) < 1) return c / 2 * t * t + b;
return -c / 2 * ((--t) * (t-2) - 1) + b;
}}const Linear = function(t, b, c, d) {
return c * t / d + b; }
2. 粒子实现
实现思路:
希望在粒子管控组件时,使用new partical的方式创建粒子,每个粒子存在自己的动画开始方法,动画结束回调。
由于评论列表可能存在数量巨大的情况,我们希望只全局创建有限个数的粒子,那么则提供呢容器移除粒子功能以及容器添加粒子的功能,实现粒子的复用
partical_style.css
//粒子充满粒子容器,需要容器存在尺寸以及relative定位.Boom-Partical_Holder{
position: absolute;
left:0;
right:0;
top:0;
bottom:0;
margin:auto;}
particle.js
import "partical_style.css";
class Partical{
// dom为装载动画元素的容器 用于设置位置等样式
dom = null;
// 动画开始时间
StartTime = -1;
// 当前粒子的动画方向,区别上抛运动与下抛运动
direction = "UP";
// 动画延迟
delay = 0;
// 三方向位移值
targetZ = 0;
targetY = 0;
targetX = 0;
// 缩放倍率
scaleNum = 1;
// 是否正在执行动画
animating = false;
// 粒子的父容器,标识此粒子被渲染到那个元素内
parent = null;
// 动画结束的回调函数列表
animEndCBList = [];
// 粒子渲染的内容容器 slot
con = null;
constructor(){
//创建动画粒子dom
this.dom = document.createElement("div");
this.dom.classList.add("Boom-Partical_Holder");
this.dom.innerHTML = ` <div class="Boom-Partical_con"> Boom </div> `;
}
// 在哪里渲染
renderIn(parent) {
// dom判断此处省略
parent.appendChild(this.dom);
this.parent = parent;
// 此处为初始化 slot 容器
!this.con && ( this.con = this.dom.querySelector(".Boom-Partical_con"));
}
// 用于父容器移除当前粒子
deleteEl(){
// dom判断此处省略
this.parent.removeChild(this.dom);
}
// 执行动画,需要此粒子执行动画的角度,动画的力度,以及延迟时间
animate({ deg, pow, delay } = {}){
// 后续补全
}
// 动画结束回调存储
onAnimationEnd(cb) {
if (typeof cb !== 'function') return;
this.animEndCBList.push(cb);
}
// 动画结束回调执行
emitEndCB() {
this.dom.style.cssText += `;-webkit-transform:translate3d(0,0,0);opacity:1;`;
this.animating = false;
try {
for (let cb of this.animEndCBList) {
cb();
}
} catch (error) {
console.warn("回调报错:",cb);
}
}
// 简易实现slot功能,向粒子容器内添加元素
insertChild(child){
this.con.innerHTML = '';
this.con.appendChild(child);
}}
致此,我们先创建了一个粒子对象的构造函数,现在考虑一下我们实现了我们的设计思路吗?
* 使用构造函数new Partical( )粒子
* 粒子实力对象存在 animate 执行动画方法
* 有动画结束回调函数的存储和执行
* 设置粒子的父元素: renderIn 方法
* 父元素删除粒子: deleteEl 方法
为了更好的展示粒子内容,我们特意在constructor里创建了一个 Boom-Partical_con 元素用于模拟slot功能: insertChild方法,用于使用者展示不同的内容进行爆炸
【CSS】398- 原生JS实现DOM爆炸效果的更多相关文章
- 框架操作DOM和原生js操作DOM比较
问题引出 对于Angular和React操作DOM的速度,和原生js操作DOM的速度进行了一个比较: 一个同学做的demo 代码如下: <!DOCTYPE html> <html n ...
- 面向对象原生js幻灯片代淡出效果
面向对象原生js幻灯片代淡出效果 下面是代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" & ...
- 原生JS封装简单动画效果
原生JS封装简单动画效果 一致使用各种插件,有时候对原生JS陌生了起来,所以决定封装一个简单动画效果,熟悉JS原生代码 function animate(obj, target,num){ if(ob ...
- 原生js实现的放大镜效果
这是我用原生js写的放大镜效果,与各种各样的框架技术相比,我喜欢使用原生的js,在这里,想和大家一起谈谈原生和框架技术的理解与个人喜好. <!DOCTYPE HTML><html&g ...
- jq与原生js实现收起展开效果
jq与原生js实现收起展开效果 (jq需自己加载) <!DOCTYPE html> <html> <head> <meta charset="UTF ...
- 原生JS获取DOM 节点到浏览器顶部的距离或者左侧的距离
关于js获取dom 节点到浏览器顶/左部的距离,Jquery里面有封装好的offset().top/offset().left,只到父级的顶/左部距离position().top/position() ...
- 原生js操作Dom节点:CRUD
知识点,依然会遗忘.我在思考到底是什么原因.想到研究生考试准备的那段岁月,想到知识体系的建立,知识体系分为正向知识体系和逆向知识体系:正向知识体系可以理解为教科书目录,逆向知识体系可以理解考试真题. ...
- 关于Echarts的原生js获取DOM元素与动态加载DOM元素的冲突问题
1.前言: 最近在做的看板项目,因为需要循环加载后台数据,并且用Echarts做数据呈现,所以jQuery和angular等库统统靠边站,Echarts用的是原生js获取DOM元素,至于诸多不兼容等深 ...
- 原生js操作dom的方法
今天学习了原生js的dom节点的操作,就记录下来,仅供自己以后参考. 1)创建节点:除了可以使用createElement创建元素,也可以使用createTextNode创建文本节点. documen ...
随机推荐
- nyoj 257 郁闷的C小加(一)(栈、队列)
郁闷的C小加(一) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 我们熟悉的表达式如a+b.a+b*(c+d)等都属于中缀表达式.中缀表达式就是(对于双目运算符来说 ...
- 【Java】抽象类和接口详解
抽象类 一.抽象类的概述 现在请思考一个问题:假如我现在又Dog.Cat.Pig等实例对象,现在我们把它们都抽象成一个Animal类,这个类应该包含了这些Dog.Cat.Pig等实例对象eat的功能, ...
- 力扣(LeetCode)整数形式的整数加法 个人题解
对于非负整数 X 而言,X 的数组形式是每位数字按从左到右的顺序形成的数组.例如,如果 X = 1231,那么其数组形式为 [1,2,3,1]. 给定非负整数 X 的数组形式 A,返回整数 X+K 的 ...
- 领扣(LeetCode)寻找旋转排序数组中的最小值 个人题解
假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 请找出其中最小的元素. 你可以假设数组中不存在重 ...
- opencv 7 直方图与匹配
图像直方图概述 直方图的计算与绘制 计算直方图:calcHist()函数 找寻最值:minMaxLoc()函数 示例程序:绘制H-S直方图 #include "opencv2/highgui ...
- Alibaba Nacos 学习(三):Spring Cloud Nacos Discovery - FeignClient,Nacos 服务注册与发现
Alibaba Nacos 学习(一):Nacos介绍与安装 Alibaba Nacos 学习(二):Spring Cloud Nacos Config Alibaba Nacos 学习(三):Spr ...
- 2019-9-26:渗透测试,基础学习,nmap扫描kali虚拟机服务
初识Nmap 1, 首先确定kali的ip地址,输入命令ifconfig 2, 开启所需要扫描的服务, 开启ssh:service ssh start, 确认ssh服务是否开启service ssh ...
- 揭秘String类型背后的故事——带你领略汇编语言魅力
字符串或串(String)是由数字.字母.下划线组成的一串字符.一般记为 s=“a1a2···an”(n>=0).它是编程语言中表示文本的数据类型.在程序设计中,字符串(string)为符号或数 ...
- k8s 获取 Pod ip 添加到环境变量
0x00 事件 有一个需要将 Pod 自身的 ip 地址添加到环境变量的需求,可以在 yaml 文件的 env 中这样设置: env: - name: POD_OWN_IP_ADDRESS value ...
- Spring IOC 的简单使用
Spring IOC (Inversion Of Control反转控制容器 一.对于IOC容器的简单理解 在java开发中将程序中的对象交给容器管理,而不是在对象的内部管理. 那么两个简单的问题去分 ...