JavaScript實(shí)現(xiàn)煙花特效(面向?qū)ο?
本文實(shí)例為大家分享了JavaScript實(shí)現(xiàn)煙花特效的具體代碼,供大家參考,具體內(nèi)容如下
本特效使用面向?qū)ο缶幊?/strong>
分析
OOA
- 點(diǎn)擊觸發(fā)事件
- 煙花運(yùn)動(dòng)分成兩個(gè)階段
向上飛
爆炸
OOD
class FireWork{
constructor(){
}
bindEvent(){
let _this = this;
ele.onclick = function(){
//fly結(jié)束再去調(diào)用boom函數(shù)
_this.fly(_this.boom);
}
}
fly(boom){
}
boom(){
}
}
CSS設(shè)計(jì)實(shí)現(xiàn)
CSS代碼
*{
margin: 0;
padding: 0;
}
#box{
width:800px;
height:600px;
position: relative;
margin: 100px auto;
background:#000000;
border:2px solid red;
overflow: hidden;
}
.ball{
width: 40px;
height: 40px;
border-radius: 50%;
position: absolute;
bottom: 0;
}
JS編程實(shí)現(xiàn)
javascript代碼
<script src="./utils.js"></script>
<script>
//
class FireWork{
constructor(){
this.box = document.getElementById("box");
this.box_offset = {
left : box.offsetLeft,
top : box.offsetTop
}
}
bindEvent(){
let _this = this;
this.box.onclick = function( e ){
e = e || event;
_this.x = e.clientX - _this.box_offset.left;
_this.y = e.clientY - _this.box_offset.top;
_this.fly(_this.boom);
}
}
fly( boom ){
let ele = this.createEle();
let _this = this;
// 放入box之中;
ele.style.left = this.x + "px";
let _left = this.x ;
let _top = this.y ;
animate( ele , {
top : this.y
} , function(){
ele.remove();
_this.boom( _left , _top );
});
}
boom( x , y ){
let r = 100;
let count = 0 ;
let _this = this;
for(let i = 0 ; i < 20 ; i ++){
let ele = this.createEle();
ele.style.left = x +"px";
ele.style.top = y + "px";
let _left = parseInt(Math.cos( Math.PI / 10 * i ) * r ) + x ;
let _top = parseInt(Math.sin( Math.PI / 10 * i ) * r) + y
animate( ele , {
left : _left,
top : _top,
opacity : 0
} , function(){
ele.remove();
})
}
}
createEle(){
let ele = document.createElement("div");
ele.className = "ball";
ele.style.backgroundColor = `rgb(${parseInt(Math.random() * 255)},${parseInt(Math.random() * 255)},${parseInt(Math.random() * 255)})`;
this.box.appendChild( ele );
return ele ;
}
}
new FireWork().bindEvent();
</script>
引用的utils.js文件
function on(dom, event_name, handler_selector, delegation_handler) {
if( typeof handler_selector === "string" && typeof delegation_handler === "function"){
return delegation(dom, event_name, handler_selector, delegation_handler);
}
// 在dom對(duì)象里面建立一個(gè)事件名 : 事件處理函數(shù)對(duì)應(yīng)的數(shù)組;
// 判定當(dāng)前事件處理函數(shù)是否在dom對(duì)象之中;
var event_type = "_" + event_name;
if (event_type in dom) {
dom[event_type].push(handler_selector);
} else {
dom[event_type] = [handler_selector];
}
// 如果直接用事件名當(dāng)成對(duì)象之中的key值,那么會(huì)和原有的dom功能名稱沖突;
// 因?yàn)樘厥獾氖录麜?huì)導(dǎo)致事件無法觸發(fā),所以我們?cè)谶@里要對(duì)事件名進(jìn)行拆分處理;
dom.addEventListener(event_name.split(".")[0], handler_selector)
}
function off(dom, event_name) {
// 獲取到dom對(duì)象里面事件名對(duì)應(yīng)的一組事件處理函數(shù);
var callback_list = dom["_" + event_name];
// 根據(jù)列表里面的所有函數(shù)進(jìn)行事件移除 ;
callback_list.forEach(function (event_handler) {
dom.removeEventListener(event_name.split(".")[0], event_handler);
})
// 清空dom對(duì)象里面的事件處理函數(shù)組;
dom["_" + event_name].length = 0;
}
function trigger(dom, event_type) {
dom.dispatchEvent(new Event(event_type));
}
function delegation(dom, event_name, selector, event_handler) {
dom.addEventListener(event_name, function (e) {
e = e || event;
var target = e.target || e.srcElement;
while (target !== dom) {
switch (selector[0]) {
case ".":
if (selector.slice(1) === target.className) {
event_handler.call(target , e )
return;
}
case "#":
if (selector.slice(1) === target.id) {
event_handler.call(target, e)
return;
}
default:
if (selector.toUpperCase() === target.nodeName) {
event_handler.call(target, e)
return;
}
}
target = target.parentNode;
}
})
}
function animate( dom , attrs , callback , transition = "buffer", speed = 10 ){
// transition : 有兩種動(dòng)畫方式 "buffer" , "liner"
var _style = getComputedStyle( dom );
// - 1. 數(shù)據(jù)變形 ;
for(var attr in attrs ){
attrs[attr] = {
target : attrs[attr],
now : _style[attr]
}
// - 2. 速度 : 勻速運(yùn)動(dòng)速度正負(fù) ;
if( transition === "liner" ){
attrs[attr].speed = attrs[attr].target > attrs[attr].now ? speed : - speed;
}
if( attr === "opacity"){
attrs[attr].target *= 100
attrs[attr].now *= 100
}else{
attrs[attr].now = parseInt(attrs[attr].now)
}
}
// - 關(guān)閉開啟定時(shí)器;
clearInterval( dom.interval );
dom.interval = setInterval( function(){
for(var attr in attrs ){
// 取出當(dāng)前值和屬性值 ;
// attrs[attr].target : 目標(biāo)值;
// attrs[attr].now : 當(dāng)前值;
let { target , now } = attrs[attr];
// 緩沖運(yùn)動(dòng)時(shí)候的速度;
if( transition === "buffer" ){
var speed = (target - now ) / 10 ;
speed = speed > 0 ? Math.ceil( speed ) : Math.floor( speed );
}else if(transition === "liner"){
var speed = attrs[attr].speed;
}
if( Math.abs(target - now) <= Math.abs( speed ) ){
if( attr === "opacity"){
dom.style[attr] = target / 100;
}else{
dom.style[attr] = target + "px";
}
delete attrs[attr];
for(var attr in attrs ){
// 如果有數(shù)據(jù)循環(huán)會(huì)執(zhí)行至少一次;
return false;
}
clearInterval(dom.interval);
typeof callback === "function" ? callback() : "";
}else{
now += speed;
if( attr === "opacity"){
dom.style[attr] = now / 100;
}else{
dom.style[attr] = now + "px";
}
// 給對(duì)象賦值;
attrs[attr].now = now;
}
}
} , 30)
}
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
js無后端實(shí)現(xiàn)點(diǎn)擊加載查看更多(提示SEO友好度)
為了提示SEO友好度,并且避免調(diào)用后端接口給服務(wù)器造成負(fù)擔(dān),可以使用js無后端實(shí)現(xiàn)點(diǎn)擊加載查看更多,比如HTML中源碼存在60條記錄,預(yù)先顯示20條記錄,點(diǎn)擊“查看更多”一次追加10條,最后一次后按鈕文本改為“已查看全部”,在JavaScript中,你可以使用以下步驟來實(shí)現(xiàn)2024-10-10
js實(shí)現(xiàn)獲取div坐標(biāo)的方法
這篇文章主要介紹了js實(shí)現(xiàn)獲取div坐標(biāo)的方法,通過調(diào)用jQuery插件實(shí)現(xiàn)獲取div元素坐標(biāo)的功能,非常簡單實(shí)用,需要的朋友可以參考下2015-11-11
ES2020讓代碼更優(yōu)美的運(yùn)算符 (?.) (??)
這篇文章主要介紹了ES2020讓代碼更優(yōu)美的運(yùn)算符 (?.) (??),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
ECMAScript6塊級(jí)作用域及新變量聲明(let)
這篇文章主要介紹了ECMAScript6塊級(jí)作用域及新變量聲明(let) 的相關(guān)資料,需要的朋友可以參考下2015-06-06
原生JS面向?qū)ο髮?shí)現(xiàn)打磚塊小游戲
這篇文章主要為大家詳細(xì)介紹了原生JS面向?qū)ο髮?shí)現(xiàn)打磚塊小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09

