1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 教你用面向对象方法写一个烟花爆炸的特效

教你用面向对象方法写一个烟花爆炸的特效

时间:2023-11-16 03:43:24

相关推荐

教你用面向对象方法写一个烟花爆炸的特效

由于是面向对象,所以步骤非常重要

**

一.OOA:

**

1. 创建元素;

2. 元素运动;

3. 烟花爆炸;

4. 随机位置;

5. 随机颜色;

二.OOD:

function FireWork( x , y ) {this.init( x , y );}FireWork.prototype = {constructor : FireWork , init : function( x , y ){},// 1. 创建元素;createFireWorkEle : function (){},// 2. 元素运动;fireWorkUp : function(){},// 3. 烟花爆炸;fireWorkBlast : function(){},// 4. 随机位置;randomBoundary : function(){}// 5. 随机颜色;randomColor : function(){}}

**

三.OOP

**

首先是布局:

<div class="box"></div>

然后是CSS样式:

<style>.box{width: 80%;height: 600px;border: 2px solid red;background: #000;margin:20px auto;cursor: pointer;position: relative;left: 0;top: 0;overflow: hidden;}.fire{width: 10px;height:10px;position: absolute;bottom: 0;}</style>

首先要初始化函数:

init : function( x , y ){//因为元素要运动,所以要初始化x,y坐标//把初始化出来的x,y坐标指向this//这里的this指向FireWork实例对象this.x = x;this.y = y;console.log(this,this.x,this.y,x,y);//因为要有火花,所以要创建元素//又因为有了创建函数,所以调用函数FireWorkCJ()this.ele = this.FireWorkCJ();console.log(this.ele);// 为了节省randomBoundary消耗的无用性能,统一获取一次left和top的最大值;// 注意程序的执行顺序, 元素的offset属性获取,必须要放在元素插入到页面之后才行;this.left_max = this.main.offsetWidth - this.ele.offsetWidth;this.top_max = this.main.offsetHeight - this.ele.offsetHeight;//给元素添加背景颜色this.FireWorkYS( this.ele );// 烟花主体升起;this.FireWorkYD( this.ele );},

创建元素

//1.创建元素// 什么时候要使用var 什么时候要使用 this.xxx ;// 如果这个数据在其他的方法里还要用,那么就放在this之中;// 如果感觉这个变量在当前函数使用结束就不用了,那么就用var;FireWorkCJ : function(){//首先要创建一个火花的盒子var ele = document.createElement("div");//让他拥有className,成为拥有该样式的盒子ele.className = "fire";//将这个火花盒子放到父级//由于传入了父级参数 selector ,将创建出来的 ele 放到父级this.main.appendchild( ele );//返回elereturn ele;}

,

其次是元素运动

//2.元素运动FireWorkYD : function( ele ){//创建元素的左右位置//left : 直接到达//top : 运动到达目的地//创建的元素 ele 的left为 this.x 的位置像素ele.style.left = this.x + "px";//调用运动函数animate( ele ,{top : this.y},function(){// 烟花运动结束要删除掉这个元素;ele.remove();// 直接调用烟花爆炸功能;this.FireWorkBZ();}.bind(this))},

强大的爆炸功能

//3.烟花爆炸FireWorkBZ : function(){//烟花爆炸,随机生成多个(20)个火花for( var i = 0 ; i < 20 ; i++){//创建火花var ele = this.FireWorkCJ();this.FireWorkYS( ele );//初始化火花的样式ele.style.left = this.x + "px";ele.style.top = this.y + "px";ele.style.borderRadius = "50%";//让元素有运动目标;animate( ele , this.BZ_type = "circular" ? this.BZ_YUAN( i , 20 ) : this.FireWorkWZ() , function( callback_ele ){// 什么时候会执行这个回调函数; 一定的时间之后; for循环早就执行完了;// 在这个作用域之中ele只有一个,当你执行回调函数的时候,ele已经被赋值20次了,ele里面的数据之后最后一个。// bind 的高级用法;callback_ele.remove();}.bind(this , ele)) // 因为执行了20次,会创造20个不同的函数;// 现在给每个匿名函数都去绑定一个ele元素;// function( ele ){ele => ele1 }.bind(this,ele1)// function( ele ){ele => ele2 }.bind(this,ele2)// function( ele ){ele => ele3 }.bind(this,ele3)// ... }},

爆炸后元素的随机位置

//4.随机位置6FireWorkWZ : function(){return {left : parseInt( Math.random() * ( this.left_max + 1) ),top : parseInt( Math.random() * ( this.top_max + 1) )}},

生成的随机颜色的烟花

//5.随机颜色//给已经创建出来的ele火花盒子添加随机颜色样式FireWorkYS : function( ele ){return ele.style.backgroundColor = "#" + parseInt( parseInt( "ffffff" , 16) * Math.random() ).toString(16).padStart( 6 , 0 );},

爆炸后呈圆形绽放

//6.扩展:爆炸后呈圆形绽放//now_index : 代表这是创建的第几个圆//total : 代表 一共要创建多少个BZ_YUAN : function( now_index , total ){var r = 100;// 计算角度;//reg : 代表第i个对应的角度var reg = (360 / total ) * now_index;// JS里面没有角度只有弧度; 换算弧度;//deg : 转化成弧度var deg = Math.PI / 180 * reg;return {left : parseInt(r * Math.cos( deg )) + this.x,top : parseInt(r * Math.sin( deg )) + this.y,} }

调用函数

document.querySelector(".box").addEventListener("click",function( evt ){var e = evt || event;new FireWork(e.offsetX , e.offsetY , ".box" , "circular")})

内置js函数

<script src="animate.js"></script>

代码展示//创建一个可以传入更多数据的函数方法-------回调函数//作用 :任意元素任意属性运动//参数解析://ele: 元素//attr_options : 调用的对象结构//callback: 函数方法function animate( ele , attr_options , callback){//获取元素当前的属性//遍历attr_option结构数组for( var attr in attr_options ){// 我们需要记录的数据有 : 属性名 : 目标点, 当前元素的属性;// {"width" : {// target : 200 ,// iNow : 元素的属性值;//} // }// attr : width : height |.......;//属性名:attr_options[ attr ]//传入的属性值:attr//目标 :target//当前元素的属性:iNowattr_options[ attr ] = {// 目标点 : 传入的数据;//目标点取值//当 目标点target 取出的 attr 的值 为opacity 时, target = attr_options[ attr ] * 100//当 目标点target 取出的 attr 的值 不为opacity 时,target = attr_options[ attr ] target : attr === "opacity" ? attr_options[ attr ] * 100 : attr_options[ attr ],//元素当前的属性值 ;//元素属性值取值//当 元素属性值iNow 取出的 attr 的值 为opacity 时, iNow = parseInt( getComputedStyle(ele)[attr] * 100 )//当 元素属性值iNow 取出的 attr 的值 不为opacity 时, iNow = parseInt( getComputedStyle(ele)[attr] )//getComputedStyle(ele)[attr] * 100-------->提取ele元素中 的该元素 ele.attr*100 的结果iNow : attr === "opacity" ? parseInt( getComputedStyle(ele)[attr] * 100 ) : parseInt( getComputedStyle(ele)[attr] )}}//把所有的定时器都放进ele对象之中;//关闭计时器clearInterval(ele.timer);ele.timer = setInterval(function(){//遍历attr_option结构数组//获取速度for( var attr in attr_options ){//创建一个参数存放属性名attr_option[attr]结构var item = attr_options[ attr ];//创建一个参数存放目标点var target = item.target;//创建一个参数存放元素当前的属性值var iNow = item.iNow;//运动所必须的值我们都有了;//运动速度的求取 = 目标点 - 元素当前的属性值//根据目标点求得运动的速度;var speed = ( target - iNow ) / 10;//速度取整//速度取整; 要查看速度是正数还是负数;//如果大于0,Math.ceil( speed )--------向上取整//如果小于0,Math.floor( speed )--------向下取整 speed = speed > 0 ? Math.ceil( speed ) : Math.floor( speed )//终止条件//通过终止条件,中止计时器//根据 target 和当前的元素位置判定速度为正数还是负数if( Math.abs(target - iNow) <= Math.abs( speed )){// 终止条件不可靠,因为目标的不一致会让运动次数执行不同,有可能提前关闭定时器;ele.style[attr] = attr === "opacity" ? target / 100 : target + "px";// 一条运动完成删除对象里面的数据;delete attr_options[ attr ];// 如果对象里面没有属性了,那么我们关闭定时器就可以了;//遍历attr_options结构数组for( var num in attr_options){// 如果attr_options里面有属性,那么此时我就不应该终止定时器;return false;}//关闭计时器clearInterval( ele.timer );//判断callback类型//如果callback的类型为函数,则执行callback//如果callback的类型不为函数,则执行“”(为空)typeof callback === "function" ? callback() : "";}else{//元素运动//因为 iNow 是一个临时变量,所以不能再去操作iNow , 要去操作iNow 的数据源;attr_options[ attr ].iNow += speed;ele.style[attr] = attr === "opacity" ? attr_options[attr].iNow / 100 : attr_options[attr].iNow + "px";}}},30)}

全部代码

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><style>.box{width: 80%;height: 600px;border: 2px solid red;background: #000;margin:20px auto;cursor: pointer;position: relative;left: 0;top: 0;overflow: hidden;}.fire{width: 10px;height:10px;position: absolute;bottom: 0;}</style></head><body><div class="box"></div><script src="animate.js"></script><script>// OOA // 1. 创建元素;// 2. 元素运动;// 3. 烟花爆炸;// 4. 随机位置;// 5. 随机颜色;//OODfunction FireWork( x , y , selector , BZ_type){//因为要有一个装 创建出来的 火花的盒子 ,所以需要创建一个父级参数selector// this.main = document.querySelector(selector);// 每次调用FireWork 都会进行元素选择,会导致元素选择次数太多;// 向Firework上存储数据;// 做一个逻辑 : 如果 FireWork上已经有选择好的元素了,那么我们就不需要重复进行选择了// 1. 如果已经选择过元素了,并且元素上的选择器和传入的选择器// 单例模式的思想;//如果 存在FireWork.main 并且 FireWork.main.selector === selector 的挂if( FireWork.main && FireWork.main.selector === selector){//由于已经经历过元素,就可以对需要的元素塑性进行直接赋值this.main = FireWork.main.ele;// console.log("已经经历过元素原则了,对需要属性进行直接赋值")}else{//如果没有的话//就代表没有选择过元素,现在需要对元素进行选择// console.log("还没有选择过元素,现在需要进行元素选择")//????FireWork.main = {ele : document.querySelector( selector ),selector : selector}this.main = FireWork.main.ele ;}//调用初始化函数,初始化数据this.init( x , y);//代表爆炸后呈现的的样式this.BZ_type = BZ_type;}//创建一个原型对象FireWork.prototype = {//固定单词 constructor,用来替代构造函数;constructor : FireWork,//初始化init : function( x , y ){//因为元素要运动,所以要初始化x,y坐标//把初始化出来的x,y坐标指向this//这里的this指向FireWork实例对象this.x = x;this.y = y;console.log(this,this.x,this.y,x,y);//因为要有火花,所以要创建元素//又因为有了创建函数,所以调用函数FireWorkCJ()this.ele = this.FireWorkCJ();console.log(this.ele);// 为了节省randomBoundary消耗的无用性能,统一获取一次left和top的最大值;// 注意程序的执行顺序, 元素的offset属性获取,必须要放在元素插入到页面之后才行;this.left_max = this.main.offsetWidth - this.ele.offsetWidth;this.top_max = this.main.offsetHeight - this.ele.offsetHeight;//给元素添加背景颜色this.FireWorkYS( this.ele );// 烟花主体升起;this.FireWorkYD( this.ele );},//1.创建元素// 什么时候要使用var 什么时候要使用 this.xxx ;// 如果这个数据在其他的方法里还要用,那么就放在this之中;// 如果感觉这个变量在当前函数使用结束就不用了,那么就用var;FireWorkCJ : function(){//首先要创建一个火花的盒子var ele = document.createElement("div");//让他拥有className,成为拥有该样式的盒子ele.className = "fire";//将这个火花盒子放到父级//由于传入了父级参数 selector ,将创建出来的 ele 放到父级this.main.appendchild( ele );//返回elereturn ele;},//2.元素运动FireWorkYD : function( ele ){//创建元素的左右位置//left : 直接到达//top : 运动到达目的地//创建的元素 ele 的left为 this.x 的位置像素ele.style.left = this.x + "px";//调用运动函数animate( ele ,{top : this.y},function(){// 烟花运动结束要删除掉这个元素;ele.remove();// 直接调用烟花爆炸功能;this.FireWorkBZ();}.bind(this))},//3.烟花爆炸FireWorkBZ : function(){//烟花爆炸,随机生成多个(20)个火花for( var i = 0 ; i < 20 ; i++){//创建火花var ele = this.FireWorkCJ();this.FireWorkYS( ele );//初始化火花的样式ele.style.left = this.x + "px";ele.style.top = this.y + "px";ele.style.borderRadius = "50%";//让元素有运动目标;animate( ele , this.BZ_type = "circular" ? this.BZ_YUAN( i , 20 ) : this.FireWorkWZ() , function( callback_ele ){// 什么时候会执行这个回调函数; 一定的时间之后; for循环早就执行完了;// 在这个作用域之中ele只有一个,当你执行回调函数的时候,ele已经被赋值20次了,ele里面的数据之后最后一个。// bind 的高级用法;callback_ele.remove();}.bind(this , ele)) // 因为执行了20次,会创造20个不同的函数;// 现在给每个匿名函数都去绑定一个ele元素;// function( ele ){ele => ele1 }.bind(this,ele1)// function( ele ){ele => ele2 }.bind(this,ele2)// function( ele ){ele => ele3 }.bind(this,ele3)// ... }},//4.随机位置6FireWorkWZ : function(){return {left : parseInt( Math.random() * ( this.left_max + 1) ),top : parseInt( Math.random() * ( this.top_max + 1) )}},//5.随机颜色//给已经创建出来的ele火花盒子添加随机颜色样式FireWorkYS : function( ele ){return ele.style.backgroundColor = "#" + parseInt( parseInt( "ffffff" , 16) * Math.random() ).toString(16).padStart( 6 , 0 );},//6.扩展:爆炸后呈圆形绽放//now_index : 代表这是创建的第几个圆//total : 代表 一共要创建多少个BZ_YUAN : function( now_index , total ){var r = 100;// 计算角度;//reg : 代表第i个对应的角度var reg = (360 / total ) * now_index;// JS里面没有角度只有弧度; 换算弧度;//deg : 转化成弧度var deg = Math.PI / 180 * reg;return {left : parseInt(r * Math.cos( deg )) + this.x,top : parseInt(r * Math.sin( deg )) + this.y,} }}// new FireWork( 200,200,".box");document.querySelector(".box").addEventListener("click",function( evt ){var e = evt || event;new FireWork(e.offsetX , e.offsetY , ".box" , "circular")})</script></body></html>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。