第 361 篇 · 第 14 卷 前端,沒有極限 2026 年 6 月 9 日 · 台北
ls -lt ./posts --since=2013 REC · node 361 · uplink

canvas

專輯封面顏色作為背景色(平均色)

2014 年 12 月 18 日 · 3 分鐘閱讀 · By Wang Casper

現在有些音樂專輯選單做得很豐富,其中一種背景色會隨著專輯色改變,我剛好想到以前有做一個CSS專輯選單,如果結合Canvas似乎就能達到差不多的效果,所以就來試試看。

範例

之前的CSS範例

去年在練習CSS時就有寫一篇文章,是把CD封面作成3D的,這次就再拿這個範例做實驗,結果如下:

背景的顏色是使用Canvas來抓顏色資料,所以他還是必須有canvas元素,這也是可以隱藏的。

實作

這一個實作的重點在於RGB顏色的平均,上一篇有介紹怎麼取得RGB的顏色,這次其實只要將RGB的顏色平均後寫入背景色就算完成了。

$(document).ready(function(){
  var _canvas = document.getElementById('canvas');
  var ctx = _canvas.getContext('2d');

  $('#album input').on('change', function(){
    //取得選擇的專輯封面
    if ($(this).is(':checked')){
      imgPath = $(this).next('li').find('img')
        .attr('src');
      getImg(imgPath);
    }
  });

  function getImg(imgPath){
    var img = new Image();
    img.src = imgPath;
    //取得圖片的路徑,並且讀取後取得長寬資料
    img.onload = function(){   
      ctx.canvas.width = img.width;
      ctx.canvas.height = img.height ;
      draw(this,0,0);
      //draw function
    };

  }

  function draw(imgObj,w,h){
    var x = 0, y = 0;
    var r=[],g=[],b=[];//準備空的R,G,B陣列
    ctx.drawImage(imgObj,x,y);
    //將圖片繪製在canvas上
    var imgData = ctx.getImageData(x, y, imgObj.width, imgObj.height);

    for(var i = 0; i < imgData.data.length; i += 4) {
        //製作原始R,G,B陣列
        // red
        r.push(imgData.data[i]);
        // green
        g.push(imgData.data[i + 1]);
        // blue
        b.push(imgData.data[i + 2]);
    }
    rgb = avg(r) + ',' + avg(g) + ',' + avg(b); //平均R,G,B顏色
    $('#album').css('background-color','rgba('+rgb+',1)'); //將顏色寫入背景
  }

  function avg(arguments) {
    //取得平均值,並且轉為整數
    var sum = 0;
    for (var i = 0, j = arguments.length; i < j; i++) {
        sum += arguments[i];
    }
    return Math.floor(sum / arguments.length);
  }
});

後記

不過我相信實作並不是這麼容易做出來的,還會去分析顏色所佔的面積,利用較大面積色彩作為背景色,如果是這樣平均的色彩容易髒髒的,在畫面上不一定好看。並且還要去計算所適合的文字色彩,這麼說一說,似乎還有很多可以研究…。