昨天看到群里一个人的主题,首页的轮播很有意思,然后他的轮播底色是根据文章图片颜色来自动变动的,我当时就觉得蛮有意思的,但是我没怎么接触过canvas这个东西,html5的时候匆匆带过,然后js的时候也没有讲,索性就自己百度看看教程了,找了好久,大部分都是转载的同一篇文章,然后大佬的那个js算法我实在看不懂,搞不懂为什么要for循环的时候i要乘以图片的宽度,然后再乘以4,在加123这些,后面慢慢搞懂了*4和+123这些意思,但是还是不太懂为啥要乘以图片宽度,嘛,这些暂时不管了,先看看我的想法吧!

获取颜色平均值理论阶段

首先通过canvas获取到图片的每个像素点的rgba值,然后for循环的时候将r、g、b、a四个的值对应的相加,最后得到的rgba值是全部像素的总和,然后用这个对应的总和除以图片的像素点总和,最终求得每个像素点的平均值。

当然这只是理论的平均值,其实每张图片他有深色和浅色区域,往往深色区域的值高于浅色区域好多倍,那么这样得到的平均值是否就是我们需要的值呢,这个就要考虑下算法了,不过我们目前先将这个想法实现为目的。

了解canvas

canvas是用于绘制图像的,复杂点你甚至能玩出花样,但是canvas元素本身是没有绘画能力的,我初次使用感觉就是复制,有点像是拼图,你实现准备好图片,然后通过js进行拼接,这里我们只是使用到convas的复制图片的能力。

首先我们要了解需要使用到的几个代码:

getContext("2d")

drawImage(img,0,0)

getImageData(0,0,width,height)

.data 

第一个getContext("2d");是表示canvas要绘制一个2d图像,而且只有这一个选项,canvas目前只支持2d,所以你没得选,照着写就对了。

第二个是drawImage(img,0,0);表示规定要使用的图像,后面两个0表示开始裁剪这个图片的x,y轴坐标,其实他后面还有填值,具体我就拿w3c的说明吧!

context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
参数描述
img规定要使用的图像、画布或视频。
sx可选。开始剪切的 x 坐标位置。
sy可选。开始剪切的 y 坐标位置。
swidth可选。被剪切图像的宽度。
swidth可选。被剪切图像的宽度。
sheight可选。被剪切图像的高度。
x在画布上放置图像的 x 坐标位置。
y在画布上放置图像的 y 坐标位置。
width可选。要使用的图像的宽度。(伸展或缩小图像)
height可选。要使用的图像的高度。(伸展或缩小图像)

第三个getImageData(0,0,width,height);表示计算图片的像素数据,第一个0表示x轴哪个位置开始就算,第二个0表示从y轴哪个位置计算,width和height表示计算的宽高大小。

第四个.data是和getImageData配合使用的,只有使用了.data才能拿到对应的像素数据。

注意:

获取的像素数据是一个数组集合,每个下标分别保存r、g、b、a四个值的信息,也就是这样[r,g,b,a,r,g,b,a,.....]这样循环下去。

创建canvas并获取到图片信息

window.onload = function() {
    //获取图片颜色平均值
        (function getcolor() {
            //js创建一个canvas元素
            var canvas = document.createElement('canvas');
            //设置canvas的大小,默认是300*150,这样就无法获取到全部的图片像素了,这个值也是看你怎么设置的,动态获取也是可以的。
            canvas.width = 900;
            canvas.height = 350;
            //表示绘制一个2d图
            var context = canvas.getContext("2d");
            //获取图片元素
            var img = document.getElementById('myimg');    
            //创建图片元素用来加载图片地址        
            var nimg = new Image();
            nimg.onload = function(){
                var r = 0;
                var g = 0;
                var b = 0;
                var a = 0;
                var fxs = 900 * 300;
                //设置要绘制的图片
                context.drawImage(nimg,0,0);
                //获取图片的像素信息,并.data获得数组
                var data = context.getImageData(0,0,900,300).data;
                //获取所有的rgba的和
                for(var i = 0;i<data.length/4;i++) {
                    r += data[i * 4];
                    g += data[i * 4 + 1];
                    b += data[i * 4 + 2];
                    a += data[i * 4 + 3];
                }
                //获得平均值
                var rgba = 'rgba('+ parseInt(r/fxs) +','+ parseInt(g/fxs) +','+ parseInt(b/fxs) +','+ parseInt(a/fxs) +')';
                document.documentElement.style.backgroundColor = rgba;
            })
            //将图片地址传给nimg
            nimg.src = img.src ;
    
        })();
}

效果图

进阶想法

通过上面这个我们可以获取到图片的平均色,但是有时候并不是很如意,我们可以自行去调整算法,比如,你只需要计算某一个角,如80*80的大小,或者5x5的方块取一个点,如图:

并且还可以骚一点,取高亮色或者低亮色,那么怎么计算呢,你可以先取得平均色,然后再一个个for循环判断,如果这个颜色大于平均色50个值以上,那就push这个rgba到新的数组中,然后再求一次这个新数组的平均色,或者再复杂一点,多次for循环,直到高亮色的数组length不超过30对,那么再求平均估计会好很多,这个后续我要是有时间肯定会再次研究了,欢迎讨论。

分类: JavaScript 标签: canvas获取图片颜色平均值

评论

全部评论 1

  1. 木灵鱼儿
    木灵鱼儿
    FireFox Windows 10
    写完发现对方的背景色变动只不过放大了然后磨砂效果,我日,我心好痛:hejiu::hejiu:

目录