canvas簡單動畫--躁動的小球

前言

我們都知道canvas實際就是一個H5新增的標簽,它呢,可以用來制作照片集或者制作簡單(也不是那么簡單)的動畫作儿,甚至可以進行實時視頻處理和渲染洛二。
制作動畫的原理實際上也非常簡單:
利用定時執(zhí)行一定語句的方法來重復執(zhí)行繪圖功能,
常用的方法有:
1. setInterval()
2. setTimeout()
3. requestAnimationFrame()

一個簡單的demo

在講解躁動的小球之前呢,我們先來看一個簡單的動畫:

讓一個方塊以勻速向右移動

<canvas id="canvas" width="400" height="400" style="border: 1px solid #000">您的瀏覽器不支持</canvas>
<script>
        //獲取canvas
        let canvas = document.querySelector('#canvas')
        //獲取2d的上下文對象
        let cxt = canvas.getContext('2d')
        //創(chuàng)建一個方塊對象
        let rect = {
            w:50,   //寬
            h:50,   //高
            x:20,   //x軸方向的位移
            y:0,    //y方向的位移
            color:'red',    //填充色
        }
        //給方塊對象中添加繪制的方法
        rect.draw=function(){
            //每調用一次這個函數(shù)執(zhí)行一次x+2的操作
            this.x += 2
            cxt.fillStyle = this.color
            cxt.fillRect(this.x, this.y, this.w, this.h)
        }

        setInterval(function () {
            //繪圖之前先清空畫布,如果不清空的話,就會看到一連串的方塊
            ctx.clearRect(0, 0, canvas.width, canvas.height)
            //調用繪制方塊的函數(shù)
            rect.draw()
        },30)
</script>

上面的例子我們可以看到,我先創(chuàng)建了一個rect對象,這個對象中儲存的是繪制的方塊的各種信息,如寬高,位移,顏色等.
然后給rect對象添加一個繪制的功能(draw),其中這個功能中將this.x累加,
最后在外面利用一個沒30毫秒執(zhí)行一次的定時器來調用rect.draw(),這樣就實現(xiàn)了讓方塊一直向右運動的效果(有一點要注意,在每次調用繪制方法之前,都得清空當前的畫布)
清空畫布的方法:
clearRect(startX,startY,endX,endY)
第一,二個參數(shù)表示的是清空的其實位置,后倆個位置表示清空的結束位置.
這里我想清空的是整個畫布,也就是其實位置從(0,0)點開始,結束位置就是整個畫布的寬度和高度(畫布的最右下角).

躁動的小球

好的,說完上面的例子,我就可以來介紹這篇文章的主要內容,"躁動的小球",我們先來看下效果圖:

image.png

可以看到,效果就是在畫布中,繪制出各種顏色不同,透明度不同的小球,并且這些小球是可以四處亂竄的.

1. 布局

先來看看布局,實際是布局上很簡單,就是一個class為out的div內盛放一個<canvas>

<div class="out">
    <canvas id="canvas" width="1000" height="600"></canvas>
</div>

而在樣式上內,我是這樣設定的:

<style>
        *{
            padding: 0;
            margin: 0;
        }
        body{
            background-color: #333333;
        }
        .out{
            height: 600px;
            width: 1000px;
            margin: 50px auto;
            box-shadow: 2px 2px 10px #999;
        }
    </style>

2. JS部分

<script>
    /**
     * 創(chuàng)建一個小球的構造函數(shù)
     * @param canvasW   畫布的寬
     * @param canvasH   畫布的高
     * @param ctx       2d上下文
     * @constructor
     */
    function Ball(canvasW, canvasH, ctx) {
        this.canvasW = canvasW
        this.canvasH = canvasH
        this.ctx = ctx
        this.r = this.randomInt(10, 80)
        this.x = this.randomInt(this.r, this.canvasW - this.r)
        this.y = this.randomInt(this.r, this.canvasH - this.r)

        let R = this.randomInt(0, 255)
        let G = this.randomInt(0, 255)
        let B = this.randomInt(0, 255)
        let A = Math.random()
        this.color = `rgba(${R},${G},${B},${A})`

        let speedX = this.randomInt(1, 4)
        this.speedX = this.randomInt(0, 100) > 50 ? speedX : -speedX
        let speedY = this.randomInt(1, 4)
        this.speedY = this.randomInt(0, 100) > 50 ? speedY : -speedY
    }
    //繪制一個小球
    Ball.prototype.draw = function () {
        let deg = Math.PI / 180
        this.ctx.beginPath()
        this.ctx.arc(this.x, this.y, this.r, 0, 360 * deg, true)
        this.ctx.closePath()
        this.ctx.fillStyle = this.color
        this.ctx.fill()
    }

    //小球移動
    Ball.prototype.ballMove = function () {
        this.x += this.speedX
        this.y += this.speedY

        if (this.x >= this.canvasW - this.r) {
            this.speedX *= -1
        } else if (this.x <= this.r) {
            this.speedX *= -1
        }

        if (this.y >= this.canvasH - this.r) {
            this.speedY *= -1
        } else if (this.y <= this.r) {
            this.speedY *= -1
        }
    }

    //產(chǎn)生范圍隨機數(shù)的函數(shù)
    Ball.prototype.randomInt = function (from, to) {
        return parseInt(Math.random() * (to - from + 1) + from);
    }

    let canvas = document.querySelector('#canvas');
    let ctx = canvas.getContext('2d')
    //定義一個數(shù)組用來盛放所有的小球"對象"
    let balls = []
    for (let i = 0; i < 100; i++) {
        let ball = new Ball(canvas.width, canvas.height, ctx);
        balls.push(ball)
    }

    setInterval(function () {
        //繪圖之前先清空畫布
        ctx.clearRect(0, 0, canvas.width, canvas.height)
        for (let i = 0; i < balls.length; i++) {
            balls[i].ballMove();
            balls[i].draw()
        }
    }, 30)
</script>

1.也是和上面的demo一樣,我想將每一個小球都當成一個"對象"來寫,只不過小球的數(shù)量不確定,所以我寫了一個構造函數(shù)Ball,用它來創(chuàng)建每一個小球對象,這樣只要利用一個for循環(huán),就可以創(chuàng)建我們想要的數(shù)量的小球了.
2.這里的繪制小球和移動小球我分別用了倆個函數(shù)draw()ballMove()來寫,這樣的目的能也是為了達到面向對象的效果,將各個功能拆分開來,一個方法實現(xiàn)一種功能.
3.利用for循環(huán)來重復調用構造函數(shù)Ball,每創(chuàng)建一個小球"對象",就把它推進數(shù)組balls中,這樣for循環(huán)完之后,balls數(shù)組中存放的就是一個個的小球"對象".
4.利用定時器setInterval,每隔30毫秒,調用一次ballMove()draw()

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市攻锰,隨后出現(xiàn)的幾起案子晾嘶,更是在濱河造成了極大的恐慌,老刑警劉巖娶吞,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件垒迂,死亡現(xiàn)場離奇詭異,居然都是意外死亡妒蛇,警方通過查閱死者的電腦和手機机断,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來材部,“玉大人毫缆,你說我怎么就攤上這事唯竹±值迹” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵浸颓,是天一觀的道長物臂。 經(jīng)常有香客問我,道長产上,這世上最難降的妖魔是什么棵磷? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮晋涣,結果婚禮上仪媒,老公的妹妹穿的比我還像新娘。我一直安慰自己谢鹊,他們只是感情好算吩,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著佃扼,像睡著了一般偎巢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上兼耀,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天压昼,我揣著相機與錄音求冷,去河邊找鬼。 笑死窍霞,一個胖子當著我的面吹牛匠题,可吹牛的內容都是我干的。 我是一名探鬼主播官撼,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼梧躺,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了傲绣?” 一聲冷哼從身側響起掠哥,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎秃诵,沒想到半個月后续搀,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡菠净,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年禁舷,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毅往。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡牵咙,死狀恐怖,靈堂內的尸體忽然破棺而出攀唯,到底是詐尸還是另有隱情洁桌,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布侯嘀,位于F島的核電站另凌,受9級特大地震影響,放射性物質發(fā)生泄漏戒幔。R本人自食惡果不足惜吠谢,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望诗茎。 院中可真熱鬧工坊,春花似錦、人聲如沸敢订。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枢析。三九已至玉掸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間醒叁,已是汗流浹背司浪。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工泊业, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人啊易。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓吁伺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親租谈。 傳聞我的和親對象是個殘疾皇子篮奄,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內容

  • 在前面一篇文章中窟却,我們分析了Android應用程序窗口的繪圖表面的創(chuàng)建過程。Android應用程序窗口的繪圖表面在...
    一個不掉頭發(fā)的開發(fā)閱讀 4,548評論 0 14
  • 一:canvas簡介 1.1什么是canvas呻逆? ①:canvas是HTML5提供的一種新標簽 ②:HTML5 ...
    GreenHand1閱讀 4,667評論 2 32
  • 一夸赫、canvas簡介 1.1 什么是canvas?(了解) 是HTML5提供的一種新標簽 Canvas是一個矩形區(qū)...
    J_L_L閱讀 1,499評論 0 4
  • 第一次與它見面咖城,是一個灰蒙蒙的夜晚茬腿。白色籠罩著這個城市,同行的人走的遠些便湮沒在白霧里消失不見了宜雀。那時候才知道切平,這...
    叁點壹閱讀 129評論 0 0
  • 【禪語】 心即是佛,即佛即心辐董。凡人能悟即是菩薩悴品,佛祖不悟也是眾生。在家孝順父母郎哭,父母即是菩薩他匪,在單位盡心工作菇存,恪...
    武漢如心閱讀 437評論 3 6