摘要:今天是中秋節(jié),于是突發(fā)奇想,欸不如用來畫一畫月亮吧。徑向漸變這是月亮的類,主要用到了里的徑向漸變效果。然后整體傾角度,并且填充時用上一個徑向漸變,就可以相當完美的達到流行尾巴那樣漸行漸遠漸模糊的樣子。
今天是中秋節(jié),于是突發(fā)奇想,欸不如用canvas來畫一畫月亮吧。
于是一副用canvas畫出的星空就這樣誕生了。
Demo在這里我用了ES6語法,星星,月亮和流星都多帶帶寫成了一個module。
于是我把js一共分成這四個文件:main.js, Moon.js, Stars.js和Meteor.js,后面三個各自export出一個類。
源碼為了方便,用了gulp做自動化的工具。
main.jsimport Stars from "./Stars" import Moon from "./Moon" import Meteor from "./Meteor" let canvas = document.getElementById("canvas"), ctx = canvas.getContext("2d"), width = window.innerWidth, height = window.innerHeight, //實例化月亮和星星。流星是隨機時間生成,所以只初始化數(shù)組 moon = new Moon(ctx, width, height), stars = new Stars(ctx, width, height, 200), meteors = [], count = 0 canvas.width = width canvas.height = height //流星生成函數(shù) const meteorGenerator = ()=> { //x位置偏移,以免經(jīng)過月亮 let x = Math.random() * width + 800 meteors.push(new Meteor(ctx, x, height)) //每隔隨機時間,生成新流星 setTimeout(()=> { meteorGenerator() }, Math.random() * 2000) } //每一幀動畫生成函數(shù) const frame = ()=> { //每隔10幀星星閃爍一次,節(jié)省計算資源 count++ count % 10 == 0 && stars.blink() moon.draw() stars.draw() meteors.forEach((meteor, index, arr)=> { //如果流星離開視野之內(nèi),銷毀流星實例,回收內(nèi)存 if (meteor.flow()) { meteor.draw() } else { arr.splice(index, 1) } }) requestAnimationFrame(frame) } meteorGenerator() frame()
開頭分別引入了另外三個module,分別是星星,月亮和流星。
接著初始化了月亮和星星,但由于流星是不定時隨機生成的,所以初始化一個數(shù)組用來保存接下來生成的流星。
在每一幀中,分別調(diào)用moon,star和meteor的draw函數(shù),用來畫出每一幀,特別的,因為星星需要閃爍,流星需要移動,所以在draw之前對半徑和坐標進行處理。如果流星跑出了canvas外,就從數(shù)組中清除相應(yīng)的流星,從而解除引用和回收內(nèi)存。
Moon.jsexport default class Moon { constructor(ctx, width, height) { this.ctx = ctx this.width = width this.height = height } draw() { let ctx = this.ctx, gradient = ctx.createRadialGradient( 200, 200, 80, 200, 200, 800) //徑向漸變 gradient.addColorStop(0, "rgb(255,255,255)") gradient.addColorStop(0.01, "rgb(70,70,80)") gradient.addColorStop(0.2, "rgb(40,40,50)") gradient.addColorStop(0.4, "rgb(20,20,30)") gradient.addColorStop(1, "rgb(0,0,10)") ctx.save() ctx.fillStyle = gradient ctx.fillRect(0, 0, this.width, this.height) ctx.restore() } }
這是月亮的類,主要用到了canvas里的徑向漸變效果。為了達到和諧的程度,我試了好久T_T...
Stars.jsexport default class Stars { constructor(ctx, width, height, amount) { this.ctx = ctx this.width = width this.height = height this.stars = this.getStars(amount) } getStars(amount) { let stars = [] while (amount--) { stars.push({ x: Math.random() * this.width, y: Math.random() * this.height, r: Math.random() + 0.2 }) } return stars } draw() { let ctx = this.ctx ctx.save() ctx.fillStyle = "white" this.stars.forEach(star=> { ctx.beginPath() ctx.arc(star.x, star.y, star.r, 0, 2 * Math.PI) ctx.fill() }) ctx.restore() } //閃爍,星星半徑每隔10幀隨機變大或變小 blink() { this.stars = this.stars.map(star=> { let sign = Math.random() > 0.5 ? 1 : -1 star.r += sign * 0.2 if (star.r < 0) { star.r = -star.r } else if (star.r > 1) { star.r -= 0.2 } return star }) } }
星星的集合。因為不至于給每一個星星都寫成多帶帶的對象,于是就寫了一個星星的集合類,所有的星星都保存在實例的stars中。其中的blink函數(shù)用來隨機改變每一個星星的半徑大小,從而產(chǎn)生閃爍的效果。
Meteor.jsexport default class Meteor { constructor(ctx, x, h) { this.ctx = ctx this.x = x this.y = 0 this.h = h this.vx = -(4 + Math.random() * 4) this.vy = -this.vx this.len = Math.random() * 300 + 500 } flow() { //判定流星出界 if (this.x < -this.len || this.y > this.h + this.len) { return false } this.x += this.vx this.y += this.vy return true } draw() { let ctx = this.ctx, //徑向漸變,從流星頭尾圓心,半徑越大,透明度越高 gra = ctx.createRadialGradient( this.x, this.y, 0, this.x, this.y, this.len) const PI = Math.PI gra.addColorStop(0, "rgba(255,255,255,1)") gra.addColorStop(1, "rgba(0,0,0,0)") ctx.save() ctx.fillStyle = gra ctx.beginPath() //流星頭,二分之一圓 ctx.arc(this.x, this.y, 1, PI / 4, 5 * PI / 4) //繪制流星尾,三角形 ctx.lineTo(this.x + this.len, this.y - this.len) ctx.closePath() ctx.fill() ctx.restore() } }
流星就比較有意思啦。猜猜每一個流星是怎么畫的?
實際上每一個流星的輪廓由一個半圓和一個三角形組成,類似于一個不倒翁。然后整體傾角45度,并且填充時用上一個徑向漸變,就可以相當完美的達到流行尾巴那樣漸行漸遠漸模糊的樣子。
對,就是這么干凈利落~
最后看了一下CPU和GPU的占用,還好,優(yōu)化的還比較到位,我那渣族手機都能跑的很流暢...
今天是中秋節(jié),可惜我這下雨了...沒月亮可看...
不過我有了這個月亮。
“但愿人長久,千里共嬋娟”,千里之外的朋友,看到同一輪“明月”,也是緣分吧~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/87906.html
摘要:現(xiàn)在就一起來做一場流星雨,用程序員的野路子浪漫一下。要畫一場流星雨,首先,自然我們要會畫一顆流星。畫一顆流星是的,的卻是沒這個,但是不代表我們畫不出來。而我們每一幀要保留的就是,上一幀透明度的流星,覆蓋畫布黑色矩形我們不能顯示。 開始 妹子都喜歡流星,如果她說不喜歡,那她一定是一個假妹子。 現(xiàn)在就一起來做一場流星雨,用程序員的野路子浪漫一下。 要畫一場流星雨,首先,自然我們要會畫一顆流...
摘要:又一個酷炫的后臺管理,依然前后端分離用打開,還沒適配移動端。如果覺得還行,歡迎項目地址項目后臺地址我的博客地址好了,溜了溜了。。。 又一個Vue+Cnavas酷炫的后臺管理,依然前后端分離(用PC打開,還沒適配移動端)。 項目地址: https://github.com/hzzly/canv...demo地址: http://hjingren.cn/curriculum...賬號:hz...
摘要:按下右側(cè)的點擊預(yù)覽按鈕可以在當前頁面預(yù)覽,點擊鏈接可以打開原始頁面。 按下右側(cè)的點擊預(yù)覽按鈕可以在當前頁面預(yù)覽,點擊鏈接可以打開原始頁面。 制作像素畫的畫板https://codepen.io/abeatrize/... 純 css 畫的晚上的風車https://codepen.io/miocene/fu... 純 css 畫的可愛貓頭鷹https://codepen.io/mali_...
摘要:按下右側(cè)的點擊預(yù)覽按鈕可以在當前頁面預(yù)覽,點擊鏈接可以打開原始頁面。 按下右側(cè)的點擊預(yù)覽按鈕可以在當前頁面預(yù)覽,點擊鏈接可以打開原始頁面。 制作像素畫的畫板https://codepen.io/abeatrize/... 純 css 畫的晚上的風車https://codepen.io/miocene/fu... 純 css 畫的可愛貓頭鷹https://codepen.io/mali_...
閱讀 2805·2019-08-30 15:55
閱讀 2852·2019-08-30 15:53
閱讀 2288·2019-08-26 13:47
閱讀 2551·2019-08-26 13:43
閱讀 3152·2019-08-26 13:33
閱讀 2794·2019-08-26 11:53
閱讀 1789·2019-08-23 18:35
閱讀 795·2019-08-23 17:16