用canvas绘制流星夜空
流星是一種唯美的天文現象,我一度想用所學知識將它繪制,最近閱讀MDN上的canvas教程得到啟發,用一個canvas的長尾效果繪制流星……
什么是長尾效果?
我們知道,canvas動畫實現依賴于畫布的重繪,通過不停的清空畫布,繪制畫布就能實現基本的動畫效果。一般使用clearRect方法清除指定矩形區域,來實現重繪。長尾效果是使用透明的填充色代替clearRect方法來實現的。
使用clearRect
吐槽:由于錄屏軟件fps跟不上canvas所以這個gif圖有點卡頓
使用fillRect
1.透明度為1
可以看出透明度為1時,效果與清除效果一致,我們可以理解為在畫布上又蓋上了一畫布 ,遮住了之前所畫的內容所以和清除效果是一樣的。2.透明度為0 透明度為0的效果,則等價于沒有清除畫布的效果,此時運動的球體像一只尾巴不斷變長的蛇,可以以此猜想,將透明度設為0~1之間,就能調整尾巴的長度,達到一個帶尾巴的運動模糊效果。
3.長尾效果 因為不斷蓋上透明的畫布,所以從繪制點到出發點就產生了一條顏色不斷變淺的路徑,給人視覺效果就是一個動態模糊。
流星
可以將流星解構為一個圓形和長尾效果:
肉眼效果:
實際效果:封裝頁面形狀
使用面向對象編程完成canvas繪制
月亮類
因為月亮是靜止在頁面上的,所以只有一個draw方法,月亮光暈的實現是把陰影和填充設為同一顏色,然后讓陰影透明度大于填充透明度,就形成一個外發光的效果。
星星類
星星與月亮的唯一區別是可以移動,所以用星星類去繼承月亮類,實現面向對象的繼承與多態。
用星星緩慢的向右移動可以模擬地球自轉帶來的效果。
流星類
同理用流星類去繼承星星類。
注意的是,流星類與星星類運動的不同之處是流星劃過天空有一個夾角,所以在繪制時將畫布旋轉了角度之后,需要回歸原位。
為了讓流星出現的位置不會太密集,我將流星在y軸出現的位置設置在-2倍畫布高度到1倍畫布高度之間,并在draw方法中將畫布往上挪了畫布高度的2/3(同理要將畫布歸位)。
繪制canvas
流星需要使用長尾效果渲染,星星需要clearRect重繪,月亮就只需要繪制一次。為了三種形狀互不干擾,我分別使用了不同畫布去渲染它們。
優點:互不干擾,繪制邏輯清晰,優化渲染。
源碼
const meteorCanvas = document.getElementById('meteor');const starCanvas = document.getElementById('star');const moonCanvas = document.getElementById('moon');const meteors = [], stars = [];meteorCanvas.width = document.body.clientWidth;meteorCanvas.height = document.body.clientHeight;starCanvas.width = document.body.clientWidth;starCanvas.height = document.body.clientHeight / 3;moonCanvas.width = document.body.clientWidth;moonCanvas.height = document.body.clientHeight / 3;const meteorCtx = meteorCanvas.getContext('2d');const starCtx = starCanvas.getContext('2d');const moonCtx = moonCanvas.getContext('2d');init();animate();function init() {for (var i = 0; i < 4; i++) {meteors[i] = new Meteor(Math.random() * meteorCanvas.width,-2 * meteorCanvas.height + Math.random() * meteorCanvas.height * 3,meteorCtx, Math.floor(Math.random() * 2) + 1.5, Math.PI / 7);meteors[i].draw();}for (var i = 0; i < 60; i++) {stars[i] = new Star(Math.random() * starCanvas.width, Math.random() * starCanvas.height,starCtx, Math.random());stars[i].draw();}moon = new Moon(moonCanvas.width - 50, 50, moonCtx)moon.draw();}function animate() {starCtx.clearRect(0, 0, starCanvas.width, starCanvas.height);meteorCtx.fillStyle = `rgba(0, 0, 0, 0.1)`;meteorCtx.fillRect(0, 0, meteorCanvas.width, meteorCanvas.height);for (let meteor of meteors)meteor.move();for (let star of stars)star.move();requestAnimationFrame(animate);}function recover() {for (let meteor of meteors)meteor = null;for (let star of stars)star = null;moon = null;}window.onresize = function () {meteorCanvas.width = document.body.clientWidth;meteorCanvas.height = document.body.clientHeight;starCanvas.width = document.body.clientWidth;starCanvas.height = document.body.clientHeight / 3;moonCanvas.width = document.body.clientWidth;moonCanvas.height = document.body.clientHeight / 3;recover();init();} 復制代碼結語
陪你去看流星雨落在這地球上
讓你的淚落在我肩膀
要你相信我的愛只肯為你勇敢……
文章隨著《流星雨》的歌聲,也走向了尾聲。人生如流星劃過,轉瞬即逝,然而,流星易逝,真情永恒……
總結
以上是生活随笔為你收集整理的用canvas绘制流星夜空的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 鬼谷子谋略之空手套白狼
- 下一篇: 试炼第三天