相信很多人应该都知道8月份发生的就希望APP主题颜色随手机壳自动调整的流血事件,当晚刷爆朋友圈。然而第二天我接到一个需求,设计希望前端自动读取banner的主题色在图片上面添加主题色的渐变蒙版,当时我默默的拿出手机播放了前一天晚上刷爆朋友圈视频,然后再把描述也给UI读了一遍,是否他就懂了我的意思,转身就改设计稿去了,这件事也就偶尔被当做笑料谈一谈。但当时的我竟没有仔细想一想,没有研究就果断的拒绝UI,现在回想起原来被当做笑料的是我自己。。。
需求描述
要求就是达到如下效果,获取每一个节目单 banner 的主题色彩,然后在banner上加上一层渐变的主题色,因为 banner 为电台客户自己上传,不可控,所以需要开发添加。
实现方案
1、获取点色
简单逻辑获取主色调当然就是直接判断哪个色彩的RGB值出现次数最多就取哪个颜色了,如果要深入考虑的话当然还有密集度重要因素,这里就不做赘述了,我们就采用简单粗暴的方案就可解决当前需求。
我们可以通过 canvers 的 getImageData 方法获取到每一个像素点的 ImageData 对象,ImageData.data 中存储着我们需要的具体数据,方法如下:
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="UTF-8">
5 <title></title>
6 </head>
7 <body>
8 <canvas id="canvas" width="300" height="300"></canvas>
9 </body>
10
11 <script type="text/javascript">
12 let img = new Image()
13 let canvas = document.getElementById('canvas')
14 let ctx = canvas.getContext('2d')
15
16 img.onload = function() {
17 ctx.drawImage(img, 0, 0)
18 img.style.display = 'none'
19 let imgData = (ctx.getImageData(0, 0, img.width, img.height)).data
20 }
21
22 img.src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=182623993,1093186456&fm=27&gp=0.jpg"
23 img.crossOrigin="anonymous"
24 </script>
25 </html>
问题:
Ⅰ、这里因为 canvers 有安全监测机制,所以 img 的地址不能使用本地的图片,会涉及跨域的问题,当然如果你比较皮,非要使用本地图片作为测试数据,那也不是没办法,这里提供两个方案:
① 写成本地图片后页面使用 Firefox 打开,不会报错
② 借助第三方中转,随便找个网址注册,上传测试图片作为头像后将头像地址拿过来,就OK
Ⅱ、canvers img 如果使用网络地址还会触发另一个问题,就是地址得以 https 协议传输,否则同样报错。
2、数据处理
我们拿到点色数据后接下来的工作当然就是对二维色点数组的 RGB 值做处理,这里就需要一定的算法来支撑。
要注意的是颜色是有三个值来控制的(RGB),如果取单值来统计的话就显得粗漏,所以就需要分别对R、G、B的值进行统计。
主要的一些算法有 颜色量化法 → 八叉树算法、中位切分法,聚类 → KMeans 算法,色彩建模 等方法
这里我们选取八叉树算法来处理数据,八叉树顾名思义共八层,每层每个节点都有八个子节点(叶子节点除外)