HTML5 Canvas 提高班(一) —— 點陣圖形學(1)中點畫圓演算法

來源:互聯網
上載者:User

    本系列的隨筆在於給大家提供一些難度較深的canvas應用情境,借用數學或物理模型實現效果或效能媲美案頭應用的案例;並且此系將儘可能使用最簡明的js代碼展示效果。

    推薦使用:chrome、ie9瀏覽器進行閱讀,同時我還在做一個基於canvas的向量渲染器的類庫,希望大家關注。

    話不多說,我們現在開始第一次隨筆的內容。

點陣圖形學(1)中點畫圓演算法

    我們平時在使用canvas繪製圖形時,通常會調用context的各種API,如設定樣式的strokeline、fillcolor等;再如繪製圖形的context.arc,context.fillRect等。

    如果我們現在有一個情境,需要繪製1W個以上的圖形,並且要求其重新整理頻率達到12fps以上,也就是說我們必須要在1秒內完成10W次canvasAPI的調用,想想這有多麼可怕,大家可以在機子的機器上嘗試一下。。得卡到強制關閉瀏覽器。

    下面我們引入了點陣圖形學中的中點畫圓演算法。

   1.擷取context元素的像素數組:
    var cxt= canvas.getContext("2d");    cxt.clearRect(0, 0, width, height);    var data = cxt.getImageData(0, 0,width, height);    imageData = data.data;

    現在imageData變數便引用了當前canvas元素的所有像素數組。

    imageData的資料結構是一維數組,每四個元素表示一個像素的所有屬性,依次表示:r、g、b、alpha 的值,其範圍均是是(0——255)。

    有了這樣的理論邏輯我們可以通過canvas上的任意一點(x,y)計算出imageData中表示次像素的第一個元素的索引值。

    計算方式如下代碼:

function getStartIndex(x, y) {    return y * width * 4 + x * 4;}

    有了上面的理論知識,大家應該知道我們下面要做什麼了吧?對就是利用中點畫圓演算法對每一個像素進行顏色值(rgb)的修改。

    2.光柵學——中點畫圓

    首先我們通過圓的對稱性將其分為8個部分。

    

    現在我們假設,這個圓的中點位於(0,0)的位置。

    設d是點p(x,y)到圓心的距離:則我們得到這樣的圓方程FX(X,Y)  = d 。

    這裡我們按照Bresenham演算法,推出:

    

   (此部分可能需要有圖形學學習經驗的同學,再以後的隨筆中可能會介紹Bresenham演算法)。

    如果dM<0,表示下一點M在圓內,得

    

    如果dM>0,表示下一點M在圓外,得

    。

    有了上面的理論知識,我們就可以輕鬆的寫出繪製圓的演算法了:

// 中點畫圓法function circle(x, y, r, color) {    var tx = 0, ty = r, d = 1 - r;    while(tx <= ty){        // 利用圓的八分對稱性畫點        putpixel(x + tx, y + ty, color);        putpixel(x + tx, y - ty, color);        putpixel(x - tx, y + ty, color);        putpixel(x - tx, y - ty, color);        putpixel(x + ty, y + tx, color);        putpixel(x + ty, y - tx, color);        putpixel(x - ty, y + tx, color);        putpixel(x - ty, y - tx, color);        if(d < 0){            d += 2 * tx + 3;        }else{            d += 2 * (tx - ty) + 5;            ty--;        }        tx++;    }}

    putpixel函數用於將每一個像素的顏色值填入對應的數組當中,這裡我們的顏色只表示灰階值,因為還沒有對彩色做任何處理。

function putpixel(x, y, color){    var index = getStartIndex(x, y);    for(var i = 0; i< 4; i++) {        if(i == 3) {            imageData[index + i] = 255;        }        else{            // var co = parseInt(Math.random() * 255)            imageData[index + i] = color;        }    }}

    至此我們就已經把一個圓的像素填入我們的像素數組當中,最後將像素對象放回原來的canvas當中,就實現了圓的光柵畫法:

cxt.putImageData(data, 0, 0);
    3.案例 

    下面這個案例以1w個圓的邊界碰撞檢測運動為例,說明了我們實現的點陣圖形效能完全可以勝任各種bt情境。(首要推薦chrome18其他瀏覽器可能解析js代碼比較慢)

 


開始
停止

    下次提高班預告:實現光柵演算法中的畫線演算法。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.