摘要:好看漂亮的網(wǎng)頁(yè)特效學(xué)習(xí)筆記猜猜下一個(gè)顏色是什么分步詳細(xì)解釋第一步很簡(jiǎn)單的初始化函數(shù)。繪制新的火焰紅色的圓以及火花之前元素,即新的火焰紅色的圓以及火花的生命周期未完的話,就繼續(xù)更新它,否則就刪除它第五步以火焰為粒子。
效果:
逼真的火焰跟隨鼠標(biāo),還冒出火花,照亮背景文字
使用canvas繪制
使用javascript,但并無(wú)復(fù)雜邏輯。上手程度:簡(jiǎn)單
歡迎來(lái)我的博客看此文章: https://clatterrr.com/archive...
源碼:演示地址:https://clatterrr.github.io/f...
源碼已在下方給出,或者訪問(wèn)github代碼倉(cāng)庫(kù)https://github.com/clatterrr/...
學(xué)習(xí)筆記: google字體在上一篇中已講過(guò)。好看漂亮的html5網(wǎng)頁(yè)特效學(xué)習(xí)筆記(3)_猜猜下一個(gè)顏色是什么?
javascript分步詳細(xì)解釋
很簡(jiǎn)單的初始化函數(shù)。
var oCanvas; init = function() { oCanvas = new Fire(); oCanvas.run(); } window.onload = init;第二步:
初始化canvas,定義各種基礎(chǔ)的東西,以及為鼠標(biāo)添加事件監(jiān)測(cè)。addEventListener第三個(gè)參數(shù)的意思是,若為false,則為事件處理順序?yàn)橄冗M(jìn)先處理,為true則為先進(jìn)后處理。具體請(qǐng)看https://www.runoob.com/jsref/...
var Fire = function(){ this.canvas = document.getElementById("fire"); this.ctx = this.canvas.getContext("2d"); this.canvas.height = window.innerHeight; this.canvas.width = window.innerWidth; this.aFires = []; this.aSpark = []; this.aSpark2 = []; this.mouse = { x : this.canvas.width * .5, y : this.canvas.height * .75, } //一旦鼠標(biāo)移動(dòng),就更新this.mouse.x和this.mouse.y,因?yàn)樵O(shè)置了false,所以先進(jìn)來(lái)的事件先處理 this.canvas.addEventListener("mousemove", this.updateMouse.bind( this ), false); } Fire.prototype.updateMouse = function( e ){ this.mouse.x = e.clientX; this.mouse.y = e.clientY; }第三步:
使用requestAnimationFrame使下一幀重新運(yùn)行一遍run函數(shù)。為什么不用setInterval呢?因?yàn)閮?nèi)在運(yùn)行機(jī)制會(huì)讓它運(yùn)行速度隨機(jī)器性能變化而變化,導(dǎo)致時(shí)間控制不精確。而requestAnimationFrame使用系統(tǒng)時(shí)間,保證每秒執(zhí)行60次。參考:https://www.cnblogs.com/xiaoh...
并用bind()方法創(chuàng)建一個(gè)新的函數(shù),在bind()被調(diào)用時(shí),這個(gè)新函數(shù)的this被bind的第一個(gè)參數(shù)指定,其余的參數(shù)將作為新函數(shù)的參數(shù)供調(diào)用時(shí)使用。參考:https://developer.mozilla.org...
Fire.prototype.run = function(){ //重新新繪制火焰和火花 this.update(); this.draw(); //穩(wěn)定重繪畫面 requestAnimationFrame( this.run.bind( this ) ); }第四步:
重新繪制一個(gè)火焰(實(shí)際上是紅色的圓)和兩個(gè)火花(實(shí)際上是小長(zhǎng)方形)。若有火焰或火花的生命周期完了,那么就用刪除它。否則繼續(xù)更新它。
注意火焰火花原本被存儲(chǔ)在數(shù)組里,所以刪除用slice就好了。
Fire.prototype.update = function(){ //繪制新的火焰(紅色的圓)以及火花 this.aFires.push( new Flame( this.mouse ) ); this.aSpark.push( new Spark( this.mouse ) ); this.aSpark2.push( new Spark( this.mouse ) ); //之前元素,即新的火焰(紅色的圓)以及火花的生命周期未完的話,就繼續(xù)更新它,否則就刪除它 for (var i = this.aFires.length - 1; i >= 0; i--) { if( this.aFires[i].alive ) this.aFires[i].update(); else this.aFires.splice( i, 1 ); } for (var i = this.aSpark.length - 1; i >= 0; i--) { if( this.aSpark[i].alive ) this.aSpark[i].update(); else this.aSpark.splice( i, 1 ); } for (var i = this.aSpark2.length - 1; i >= 0; i--) { if( this.aSpark2[i].alive ) this.aSpark2[i].update(); else this.aSpark2.splice( i, 1 ); } }第五步:
以火焰為粒子。部分注釋在代碼中。先使用構(gòu)造函數(shù)確定火焰的各項(xiàng)參數(shù)。若火焰被更新,那么就更新它的坐標(biāo),生命周期,以及用生命周期計(jì)算顏色。這里的顏色使用的是HSLA顏色,參考:http://caibaojian.com/css3/va...。
火花的構(gòu)造參數(shù)和更新參數(shù)也是一樣的。
var Flame = function( mouse ){ //鼠標(biāo)坐標(biāo) this.cx = mouse.x; this.cy = mouse.y; //隨機(jī)在鼠標(biāo)周圍產(chǎn)生 this.x = rand( this.cx - 25, this.cx + 25); this.y = rand( this.cy - 5, this.cy + 5); //隨機(jī)變量,橫軸縱軸以及半徑的變化 this.vy = rand( 1, 3 ); this.vx = rand( -1, 1 ); this.r = rand( 20, 30 ); //生命周期 this.life = rand( 3, 6 ); this.alive = true; //用于繪制火焰顏色 this.c = { h : Math.floor( rand( 2, 40) ), s : 100, l : rand( 80, 100 ), a : 0, ta : rand( 0.8, 0.9 ) } } Flame.prototype.update = function() { //y坐標(biāo)變化 this.y -= this.vy; this.vy += 0.05; //x坐標(biāo)變化 this.x += this.vx; if( this.x < this.cx ) this.vx += 0.1; else this.vx -= 0.1; //半徑變化 if( this.r > 0 ) this.r -= 0.1; if( this.r <= 0 ) this.r = 0; //計(jì)算生命周期,根據(jù)生命周期計(jì)算火焰顏色 this.life -= 0.15; if( this.life <= 0 ){ this.c.a -= 0.05; if( this.c.a <= 0 ) this.alive = false; }else if( this.life > 0 && this.c.a < this.c.ta ){ this.c.a += .08; } }第六步:
canvas的主場(chǎng),繪制背景,包括黑色背景,文字FIRE,以及一個(gè)跟隨在火焰后的暗紅色大圓。這個(gè)大圓大圓,更像是墻壁的上的投影,需要仔細(xì)一點(diǎn)才能發(fā)現(xiàn)。canvas參考https://www.w3school.com.cn/t...,自己一個(gè)函數(shù)一個(gè)函數(shù)慢慢去查才能加深印象。
注意globalCompositeOperation的參數(shù)soft-light和color-dodge似乎國(guó)內(nèi)網(wǎng)站都沒(méi)找到解釋,只在英文mdn上看到了樣例。參考:
https://developer.mozilla.org...
Fire.prototype.draw = function(){ //繪制背景 this.ctx.globalCompositeOperation = "source-over"; this.ctx.fillStyle = "rgba( 15, 5, 2, 1 )"; this.ctx.fillRect( 0, 0, window.innerWidth, window.innerHeight ); //定義漸變顏色樣式 this.grd = this.ctx.createRadialGradient( this.mouse.x, this.mouse.y - 200,200,this.mouse.x, this.mouse.y - 100,0 ); this.grd.addColorStop(0,"rgb( 15, 5, 2 )"); this.grd.addColorStop(1,"rgb( 30, 10, 2 )"); //繪制一個(gè)圓形,并使用顏色漸變樣式。這個(gè)圓是一個(gè)暗紅色的大圓 //跟隨在火焰后的大圓,更像是墻壁的上的投影,需要仔細(xì)一點(diǎn)才能發(fā)現(xiàn) this.ctx.beginPath(); this.ctx.arc( this.mouse.x, this.mouse.y - 100, 200, 0, 2*Math.PI ); this.ctx.fillStyle= this.grd; this.ctx.fill(); //繪制文字Fire this.ctx.font = "15em Amatic SC"; this.ctx.textAlign = "center"; this.ctx.strokeStyle = "rgb(50, 20, 0)"; this.ctx.fillStyle = "rgb(120, 10, 0)"; this.ctx.lineWidth = 2; this.ctx.strokeText("Fire",this.canvas.width/2, this.canvas.height * .72 ); this.ctx.fillText("Fire",this.canvas.width/2, this.canvas.height * .72 ); //繪制火焰 this.ctx.globalCompositeOperation = "overlay"; for (var i = this.aFires.length - 1; i >= 0; i--)this.aFires[i].draw( this.ctx ); //繪制粒子 this.ctx.globalCompositeOperation = "soft-light"; for (var i = this.aSpark.length - 1; i >= 0; i--) if( ( i % 2 ) === 0 ) this.aSpark[i].draw( this.ctx ); //繪制粒子2 this.ctx.globalCompositeOperation = "color-dodge"; for (var i = this.aSpark2.length - 1; i >= 0; i--) this.aSpark2[i].draw( this.ctx ); }最后一步:
最關(guān)鍵但也很簡(jiǎn)單的地方,就是真正的繪制火焰和火花啦。beginpath(),arc(),fillstyle()和fill()都是canvas的方法。慢慢查找資料吧。只是注意這兒的顏色用的是hsla顏色而不是rgba顏色哦。
Flame.prototype.draw = function( ctx ){ ctx.beginPath(); ctx.arc( this.x, this.y, this.r * 3, 0, 2*Math.PI ); ctx.fillStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + (this.c.a/20) + ")"; ctx.fill(); ctx.beginPath(); ctx.arc( this.x, this.y, this.r, 0, 2*Math.PI ); ctx.fillStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + this.c.a + ")"; ctx.fill(); }完整源碼:
Canvas實(shí)現(xiàn)火焰跟隨鼠標(biāo)動(dòng)畫
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/116336.html
摘要:對(duì)于來(lái)說(shuō),表示元素,除了優(yōu)先級(jí)更高之外,與選擇器相同。從父元素繼承顏色漸變背景漂亮的深藍(lán)淺藍(lán)效果就是這個(gè)的作用。媒體查詢,簡(jiǎn)單來(lái)說(shuō)就是可以讓網(wǎng)頁(yè)自動(dòng)適應(yīng)不同的設(shè)備屏幕尺寸。具體請(qǐng)看貝塞爾曲線,用來(lái)生成水墨效果的關(guān)鍵。 showImg(https://segmentfault.com/img/bVbwNaj); 效果 鼠標(biāo)觸碰按鈕,出現(xiàn)水墨風(fēng)格動(dòng)畫 屏幕自適應(yīng) 一份html文件,一份c...
摘要:對(duì)于來(lái)說(shuō),表示元素,除了優(yōu)先級(jí)更高之外,與選擇器相同。從父元素繼承顏色漸變背景漂亮的深藍(lán)淺藍(lán)效果就是這個(gè)的作用。媒體查詢,簡(jiǎn)單來(lái)說(shuō)就是可以讓網(wǎng)頁(yè)自動(dòng)適應(yīng)不同的設(shè)備屏幕尺寸。具體請(qǐng)看貝塞爾曲線,用來(lái)生成水墨效果的關(guān)鍵。 showImg(https://segmentfault.com/img/bVbwNaj); 效果 鼠標(biāo)觸碰按鈕,出現(xiàn)水墨風(fēng)格動(dòng)畫 屏幕自適應(yīng) 一份html文件,一份c...
摘要:定義標(biāo)準(zhǔn)的文本。然后看看函數(shù)的定義自啟動(dòng)來(lái)按下按鈕的時(shí)差不能超過(guò)最大持續(xù)時(shí)間重新繪制菜單項(xiàng)的位置先用確定按下按鈕的時(shí)間,儲(chǔ)存在中。如果到了規(guī)定時(shí)間的話,就執(zhí)行。然后再把取下的第一個(gè)當(dāng)成第十三個(gè)接在最后面,又成了新的菜單排列。 showImg(https://segmentfault.com/img/bVbw1zV?w=818&h=479); 效果: 弧形菜單,文字按規(guī)則變形以及變換透...
摘要:表情繪制使用純代碼繪制。其它表情請(qǐng)看源代碼。當(dāng)評(píng)分改變,這個(gè)高度很大的元素就向上移動(dòng),把需要的表情顯示出來(lái)。源碼不同投票不同表情 showImg(https://segmentfault.com/img/bVbwOQe?w=254&h=198); 特點(diǎn): 根據(jù)不同評(píng)分顯示不同表情,并且這些表情看起來(lái)像是在一個(gè)傳送帶上可以滾動(dòng) 使用純代碼(svg)繪制表情以及用于評(píng)分的星星 html+...
摘要:表情繪制使用純代碼繪制。其它表情請(qǐng)看源代碼。當(dāng)評(píng)分改變,這個(gè)高度很大的元素就向上移動(dòng),把需要的表情顯示出來(lái)。源碼不同投票不同表情 showImg(https://segmentfault.com/img/bVbwOQe?w=254&h=198); 特點(diǎn): 根據(jù)不同評(píng)分顯示不同表情,并且這些表情看起來(lái)像是在一個(gè)傳送帶上可以滾動(dòng) 使用純代碼(svg)繪制表情以及用于評(píng)分的星星 html+...
閱讀 1491·2023-04-25 19:51
閱讀 1954·2019-08-30 15:55
閱讀 1782·2019-08-30 15:44
閱讀 2720·2019-08-30 13:58
閱讀 2719·2019-08-29 16:37
閱讀 1098·2019-08-29 15:34
閱讀 4057·2019-08-29 11:05
閱讀 2656·2019-08-28 17:51