最近在瀏覽掘金網(wǎng)站的時(shí)候看到掘金小冊中有一個(gè)很有(便)意(宜)思的冊子:如何使用 Canvas 制作出炫酷的網(wǎng)頁背景特效酪碘,便想到給我的博客添加一個(gè)炫酷的背景。順便學(xué)習(xí)一下 canvas 這個(gè)元素的使用淮逻。
效果
最終效果就在博客上就能看到啦。下面來說一下實(shí)現(xiàn)方式。
實(shí)現(xiàn)
建議對 canvas 還不了解的同學(xué)去掘金小冊上學(xué)習(xí)學(xué)習(xí)欠母,我這里不再講解。
我的博客是用 Hexo 搭建的吆寨,使用了 Archer 主題赏淌,博客的最上層樣式作者定義在 layout.ejs 文件里。
<!DOCTYPE html>
<html>
...
<div class="wrapper">
...
</div>
...
</html>
既然是在 canvas 里面畫炫酷的背景啄清,那就需要在這里添加一個(gè) canvas 元素六水,并且和 div:class="wrapper" 一樣大。
改造 layout.ejs 文件,用一個(gè) div 將 div:class="wrapper" 和我們的 canvas 包裹起來:
<!DOCTYPE html>
<html>
...
<div id="container-wrapper-canvas" style="position:relative;">
<div class="wrapper">
...
</div>
<canvas id="myCanvas" style="position:absolute;left:0;top:0;z-index:0;pointer-events:none;" />
<script>
</script>
...
</div>
...
</html>
因?yàn)椴幌胱?canvas 響應(yīng)點(diǎn)擊事件掷贾,所以在它的 style 里面加上:
pointer-events:none;
先定義一些變量(以下代碼一股腦塞到 script 標(biāo)簽里就行啦)睛榄。
// 屏幕寬高
let container = document.getElementById('container-wrapper-canvas')
let WIDTH = container.offsetWidth
let HEIGHT = container.offsetHeight
// canvas
let canvas = document.getElementById('myCanvas')
let context = canvas.getContext('2d')
// 圓點(diǎn)數(shù)量
let roundCount = HEIGHT / 10
// 存放遠(yuǎn)點(diǎn)屬性的數(shù)組
let round = []
// 令 canvas 鋪滿屏幕
canvas.width = WIDTH
canvas.height = HEIGHT
構(gòu)造圓點(diǎn)位置顏色大小等屬性
// 構(gòu)造圓點(diǎn)位置顏色大小等屬性
function roundItem(index, x, y) {
this.index = index
this.x = x
this.y = y
this.r = Math.random() * 4 + 1
let alpha = (Math.floor(Math.random() * 5) + 1) / 10 / 2
this.color = "rgba(0,0,0," + alpha + ")"
}
畫圓點(diǎn)
// 畫圓點(diǎn)
roundItem.prototype.draw = function() {
context.fillStyle = this.color
context.shadowBlur = this.r * 2
context.beginPath()
context.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false)
context.closePath()
context.fill()
}
這里看著很熟悉,在做 android想帅、iOS 開發(fā)自定義 View 的時(shí)候就遇到過類似的代碼懈费,在 draw() 函數(shù)里畫圖,這里我想到可以在移動(dòng)端使用類似的方法畫出類似的背景博脑。
這個(gè)時(shí)候調(diào)用初始化函數(shù)就可以看到靜態(tài)的一個(gè)個(gè)小圓點(diǎn)了
// 調(diào)用初始化函數(shù)
init();
function init() {
for(var i = 0; i < roundCount; i++ ){
round[i] = new roundItem(i,Math.random() * WIDTH,Math.random() * HEIGHT);
round[i].draw();
}
animate()
}
為了讓小圓點(diǎn)動(dòng)起來憎乙,我們寫下面的函數(shù)。
// 移動(dòng)圓點(diǎn)
roundItem.prototype.move = function () {
// y方向移動(dòng)速度與圓點(diǎn)半徑成正比
this.y -= this.r / 20
// x方向移動(dòng)分兩個(gè)方向叉趣,移動(dòng)速度與圓點(diǎn)半徑成正比
if (this.index % 2 == 0) {
this.x -= 0.08
} else {
this.x += this.r / 40
}
// 如果超出范圍就把它拉回來
if (this.y <= 0) {
this.y += HEIGHT
}
if (this.x <= 0) {
this.x += WIDTH
}
if (this.x >= WIDTH) {
this.x -= WIDTH
}
this.draw()
}
// 定義動(dòng)畫
function animate() {
context.clearRect(0, 0, WIDTH, HEIGHT);
for (var i in round) {
round[i].move()
}
requestAnimationFrame(animate)
}
這個(gè)時(shí)候就可以看到動(dòng)態(tài)的一個(gè)個(gè)小圓點(diǎn)了泞边。
是不是很炫酷呢。有空我再將它改造得更炫酷一點(diǎn)疗杉。