Skip to content

提取图片主色调

起因

偶尔会下载豆瓣app到手机里使用下,看见书影音tabbar页下,随便点击一个链接,进入某一个电影或者书籍之类的详情页,可以看见背景色都是不同的。这个设计效果看着挺有意思的,如是想这个在web端该如何实现。

豆瓣效果图

豆瓣详情页效果图

解决办法

canvas的getImageData可以获取图片的每一个像素点的信息。通过将所有的rgb值相加,得到三个颜色通道的总值。再将总值除去所有的像素点之和,就可以得到平均每一个通道的值。这样就拿到一张图片的主色调了。

演示示例

代码

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>获取图片主色</title>
</head>
<body>
<div class="poster_wrap">
    <canvas id="poster"></canvas>
</div>
<script>
    let oImg = new Image();
    oImg.src = '../assets/img/001.jpg';// 请替换成自己准备的图片
    let oCanvas = document.querySelector('#poster');
    let ctx = oCanvas.getContext('2d');
    oImg.onload = function () {
        const { width, height } = oImg;
        let sum_r = 0, sum_g = 0, sum_b = 0;
        let r = null, g = null, b = null;
        oCanvas.width = width;
        oCanvas.height = height;
        const totalPixel = width * height;
        ctx.drawImage(oImg, 0, 0);
        const imgData = ctx.getImageData(0, 0, oCanvas.width, oCanvas.height);
        for (let i = 0; i < imgData.data.length; i += 4) {
            r = imgData.data[i];
            g = imgData.data[i + 1];
            b = imgData.data[i + 2];
            sum_r += r;
            sum_g += g;
            sum_b += b;
        }
        const avg_r = Math.round(sum_r / totalPixel);
        const avg_g = Math.round(sum_g / totalPixel);
        const avg_b = Math.round(sum_b / totalPixel);

        // 主色调
        const mainColor = `rgb(${avg_r}, ${avg_g}, ${avg_b})`;
        document.querySelector('body').style.backgroundColor = mainColor;
    }
</script>
</body>
</html>

尾声

这个需要在服务器上才能运行。

Designed & Powerd by liujun