Canvas如何做個雪花屏版404的實現(xiàn)
介紹
過往,電視用天線接收信號,沒信號出雪花屏,刺啦刺啦作響,然后趕緊扶正想辦法讓他找到信號。當(dāng)時電腦還經(jīng)常連上小霸王打游戲,魂斗羅,超級瑪麗,坦克大戰(zhàn)。。。時間如白駒過隙,科技進(jìn)步的飛快,現(xiàn)在都用網(wǎng)絡(luò)電視了再也不會出現(xiàn)那種情況了,但那真是段令人懷念的時光。
我們今天的主題就是做一個雪花屏版的404頁面,我們404找不到頁面不就是當(dāng)年沒信號讓你去扶正找信號一樣的活么,這次我們還是用canvas技術(shù)去實現(xiàn)他,還會用到微量的css,效果下圖:

本期我們會從基礎(chǔ)結(jié)構(gòu),繪制雪花屏,css3漸變,繪制文字,繪制波段幾個方面去講述這個項目。
出發(fā)
1.基礎(chǔ)結(jié)構(gòu)
我們先寫好html,在里面我們用module模式,方面后面的模塊加載。
<div class="content">
<canvas id="canvas"></canvas>
</div>
<script type="module" src="./app.js"></script>
再寫好css的基本樣式,這里我們讓里面的元素都是全屏顯示的。
* {
padding: 0;
margin: 0;
}
html,
body {
width: 100%;
height: 100vh;
overflow: hidden;
position: relative;
font-size: 12px;
}
#canvas {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
}
.content {
z-index: 9;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: transparent;
}
接下來,我將要寫主邏輯了:
/*app.js*/
class Application {
constructor() {
this.canvas = null; // 畫布
this.ctx = null; // 環(huán)境
this.w = 0; // 畫布寬
this.h = 0; // 畫布高
this.offset = 0; // 波段偏移位置
this.imgData = null; // 畫布圖信息
this.text = "404"; // 繪制文字
this.alpha = 0; // 透明度
this.alphaNum = 0.005; // 透明度衰減值
this.alphaMax = 0.35; // 透明度極值
this.init();
}
init() {
// 初始化
this.canvas = document.getElementById("canvas");
this.ctx = this.canvas.getContext("2d");
window.addEventListener("resize", this.reset.bind(this));
this.reset();
this.render();
}
reset() {
// 屏幕改變調(diào)用
this.w = this.canvas.width = this.ctx.width = window.innerWidth;
this.h = this.canvas.height = this.ctx.height = window.innerHeight;
}
render() {
// 主渲染
this.step();
}
drawBackground() {
// 繪制雪花屏
}
drawFrame(delta) {
// 繪制波段
}
drawText() {
// 繪制文字
}
step(delta) {
// 重繪
const {w, h, ctx} = this;
requestAnimationFrame(this.step.bind(this));
ctx.clearRect(0, 0, w, h);
this.drawBackground();
this.drawText();
this.drawFrame(delta);
}
}
window.onload = new Application();
繪制方面的內(nèi)容我們隨后會開展,目前做的事就是拿到畫布給其賦予寬高讓其鋪滿每次監(jiān)聽都可以改變其寬高,此外,其實也不斷在重繪執(zhí)行中,盡管他里面沒有東西空白一片。
2.繪制雪花屏
我們想讓畫布里面有點東西,先繪制雪花背景吧,所以我們先要分析雪花屏是如何產(chǎn)生的。
其實也不難,就是我們先要拿到當(dāng)前畫布內(nèi)所有點的色值信息,對其修改成隨機灰度值,當(dāng)不斷繪制的時候,便呈現(xiàn)出雪花不斷閃動。
/*app.js*/
reset() {
this.w = this.canvas.width = this.ctx.width = window.innerWidth;
this.h = this.canvas.height = this.ctx.height = window.innerHeight;
this.changeImgData()
}
changeImgData() {
const {w, h, ctx} = this;
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, w, h);
ctx.fill();
return this.imgData = ctx.getImageData(0, 0, w, h);
}
這一步我們就是期望再每次屏幕改變的時候都能拿到他的畫布圖片數(shù)據(jù)。imgData里面有個data信息,里面存儲了一個Uint8ClampedArray,他里面對應(yīng)的是點的色值信息,每隔從0到3分別代表紅,綠,藍(lán),透明度的信息。
接下來,我們將利用這些信息搞點事情出來:
/*app.js*/
drawBackground() {
const {ctx, imgData} = this;
for (let i = 0, data = imgData.data; i < data.length; i += 4) {
let color = Math.floor(Math.random() * 255) + 50;
data[i] = color;
data[i + 1] = color;
data[i + 2] = color;
}
ctx.putImageData(imgData, 0, 0);
}
我們拿到了信息中的data讓每一個色值都改變成一個隨機具有灰度的值。再利用putImageData再次對當(dāng)前矩形也就是整個畫布進(jìn)行繪制,這樣雪花屏就出現(xiàn)了~~

3.圓形漸變
但是,看著花屏太白了,沒那種電視框起來那種味道,所以我們用css3在容器寫一個漸變背景的偽類覆蓋上。中間稍留一點白,為了讓后面的主題文字更加讓人一目了然。當(dāng)然,你也可以在畫布上繪制一個漸變上去,同樣可以實現(xiàn)效果。
.content::after {
content: "";
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 99;
background: radial-gradient(
ellipse at center,
rgba(0, 0, 0, 0) 0%,
rgba(0, 0, 0, 0.6) 100%
);
}

是不是瞬間感覺好多了~
4.繪制文字
drawText() {
this.alpha += this.alphaNum;
if (this.alpha >= this.alphaMax) {
this.alpha = this.alphaMax;
this.alphaNum *= -1;
} else if (this.alpha < 0) {
this.alpha = 0;
this.alphaNum *= -1;
}
const {ctx, text, w, h} = this;
let fontSize = w * 0.36;
ctx.save();
ctx.fillStyle = `rgba(0,0,0,${this.alpha})`
ctx.font = `bold ${fontSize}px fantasy, monospace`;
ctx.textAlign = "center";
ctx.textBaseline = 'middle';
ctx.shadowColor = "black";
ctx.shadowBlur = 20;
ctx.fillText(text, w / 2, h / 2);
ctx.restore();
}
這里在繪制前先要改變他的透明度,讓他有規(guī)律的一閃一閃,就是他讓從0不斷累加其透明度到達(dá)臨界值時其再取反,反之亦然。后面的繪制也很簡單,讓他居中顯示在屏幕中間加點投影罷了,這里不做過多贅述。

現(xiàn)在我們的已經(jīng)可以看到字體動畫了,別著急,為了更加的逼真,我們隔一段時間再生成一個波段矩形,讓人感覺到信號不穩(wěn)定,跟字體閃動的動畫相輔相成。
5.繪制波段
drawFrame(delta) {
this.offset = delta / 10;
const {w, h, ctx} = this;
for (let y = -h / 5, v = h / 5; y < h; y += v) {
ctx.fillStyle = `rgba(0,0,0,${(this.alphaMax - this.alpha) / 8 + 0.02})`;
ctx.shadowColor = "black";
ctx.shadowBlur = 20;
ctx.fillRect(0, y + this.offset % v, w, v / 2);
}
}
這里我們設(shè)置每隔一個階段自動繪制一個矩形,他的透明周期和文字的成負(fù)相關(guān),文字透明度越高他的就會月低,使其主題文字更加明顯。
里面的offset變量是為了波段經(jīng)歷的偏移位置,使其不間斷的往下移動。后面就是正常的繪制矩形再略微加些投影,更加逼真。
講到這里我們就做完了,還挺簡單的吧,一下子就回到童年了,在線演示
拓展與延伸
本期,其本質(zhì)上還是通過getImageData與putImageData一次結(jié)合使用,當(dāng)然我們也不僅限于此,可以聯(lián)想到各種各樣的效果。還有,其實我們還可以把字體做高斯模糊算法去處理等這類操作,更加有特點。
注意:雪花屏?xí)層脩舻难劬芸炱?,影響健康,所以目的是讓用戶趕緊想辦法換了,找到正確頁面。開發(fā)者做的時候千萬,別長期盯著看,不然會有不適,呃~
到此這篇關(guān)于Canvas如何做個雪花屏版404的實現(xiàn)的文章就介紹到這了,更多相關(guān)Canvas雪花屏版404內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!
相關(guān)文章
這篇文章主要介紹了使用canvas實現(xiàn)雪花飄動效果的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一2021-03-19
HTML5 Canvas實現(xiàn)的火花燃燒匯聚成文字特效源碼
HTML5 Canvas實現(xiàn)的火花燃燒匯聚成文字特效源碼是一段基于Canvas繪制酷炫的火花合成文字代碼,且鼠標(biāo)滑過的時候還會有切割裂開的效果2019-01-30


