基於canvas實現波浪式繪製圖片

寫在最前

本次的分享是一個基於canvas的更新圖片特效實現。其中主要涉及canvas中getImageData()、putImageData()、toDataURL()方法的使用。效果請看下面。
歡迎關注我的博客,不定期更新中——

PS:請在本地服務器中打開頁面,因谷歌瀏覽器中會有跨域問題,如需node靜態服務器可以參照這個地址

效果預覽


點我查看源碼倉庫

實現流程

  • 點擊換膚按鍵,在目標圖片的相應位置按照同等比例繪製一張空canvas畫布
  • 在畫布中以波浪的形式渲染圖片
  • 將畫布轉換爲圖片

繪製canvas覆蓋層

1.獲取底圖即目標圖的尺寸

//當點擊按鈕時傳遞底圖的寬高
var img = new Image()
img.src = 'xxx'
img.onload = function() {
    $('.btn').click(function() {
        ...
        var that = this
        var imgSize = {
            realHeight: that.height,
            realWidth: that.width
        }
        changeImg(imgSize, img)
    })
}

2.繪製畫布到相同位置

var changeImg = function(imgSize, oldImg) {
  var img = $(oldImg),
      offset = img.offset(),
      imgLeft = offset.left,
      imgTop = offset.top,
      canvasId = 'canvas'
  $('body').append('<canvas id='+ canvasId +' width='+ imgSize.realWidth+' height='+ imgSize.realHeight +'></canvas>')
  $('#'+ canvasId).css({
    'position': 'absolute',
    'left': imgLeft,
    'top': imgTop,
    'z-index': 1
  })
  ...
}

以波浪的形式渲染圖片

首先來介紹下getImageData()、putImageData()這兩個方法

CanvasRenderingContext2D.getImageData() 返回一個ImageData對象,用來描述canvas區域隱含的像素數據,這個區域通過矩形表示,起始點爲(sx, sy)、寬爲sw、高爲sh。

CanvasRenderingContext2D.putImageData() 是 Canvas 2D API 將數據從已有的 ImageData 對象繪製到位圖的方法。

這其中的重點則是ImageData對象是什麼。不妨我們打印一下看看:


image.png
image.png

image.png
image.png

可以看出一個2乘2的畫布佔4個像素,其中打印了一個長度爲16的一維數組,結合文檔中的講解我們可以知道,其中每一個像素均有4位分別爲rgba,故通過getImageData()我們可以得到一個拍平了的rgba數組,那麼當我們動態的去改變一些東西的時候整個圖像的色值透明度就會引起相應的變化,想想還有些小激動呢。同時putImageData()就很好理解了。當我們改變完像素數值後通過這個方法再反饋到畫布上。

//核心代碼
//通過sin函數畫出曲線
var imgData = content.getImageData(0, 0, width, height)
for(var i = 0; i < width / 10; i+=0.1 ) {
    x=Math.round(i*10)
    y=Math.round(Math.sin(i - t) * scale + initY) 
    //scale爲曲線幅度,initY爲初始位置
    for(var k = 0; k < y; k++) { 
        var sym = x * 4 + k * width * 4 
        //每個像素4位,sym表示當前爲第幾個像素的第一位
        imgData.data[sym + 3] = 0 //令該像素點變透明
        //imgData.data[sym + 3]會到達該像素點的透明度位即第四位
    }
}
content.putImageData(imgData, 0, 0, 0, 0, width, height)

其中initY爲sin曲線的縱座標位置,那麼當動態減小這個iniY時圖像渲染的曲線會一點點向上,同時透明的區域便一點點變小,同時改變t值會另曲線橫向移動,以此來形成最後的波浪形並緩緩向上的效果。

將畫布轉換爲圖片

oldImg.src = oCanvas.toDataURL('image/png')
$(oCanvas).remove()

通過toDataURL()方法,可以使畫布轉換成base64形式的img圖片,將其替換到舊圖片的url中便可以實現圖片的更新特效。

最後

慣例po作者的博客,不定時更新中——
有問題歡迎在issues下交流,捂臉求star=。=

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章