编码🌈
颜色提取✨
首先给大家看一下我的原始头像吧:
网络异常,图片无法展示
|
首先我要把绿色的部分提取出来,并把灰色的圆形背景去掉
let myCanvas = document.getElementById("my-canvas"); let cxt = myCanvas.getContext("2d"); const hancaoImage = new Image(); hancaoImage.src = "hancao.jpeg"; // 我原本头像的大小 hancaoImage.width = 212; hancaoImage.height = 199; hancaoImage.onload = function () { myCanvas.width = hancaoImage.width; myCanvas.height = hancaoImage.height; cxt.drawImage(hancaoImage, 0, 0); let imageData = cxt.getImageData(0, 0, hancaoImage.width, hancaoImage.height).data; // 白色填充 cxt.fillStyle = "#ffffff"; cxt.fillRect(0, 0, 212, 199); let list = []; for (let h = 0; h < hancaoImage.height; h += 1) { for (let w = 0; w < hancaoImage.width; w += 1) { let position = (hancaoImage.width * h + w) * 4; let r = imageData[position], g = imageData[position + 1], b = imageData[position + 2], a = imageData[position + 3]; // 给定颜色范围,把符合范围的点的放入list数组以便进行后续处理 if (((r + g + b) < 665) && (r + g + b) > 410) { cxt.fillStyle = `rgba(166, 166, 255, 1)`; cxt.fillRect(w, h, 1, 1); list.push({ h, w }) } else if((r + g + b) < 410){ cxt.fillStyle = `rgb(0,0,0)`; cxt.fillRect(w, h, 1, 1); } } }
效果就先变成了这样,我这时候已经把紫色的部分的点存在了数组里。
网络异常,图片无法展示
|
绘制多种颜色✨
下面我需要绘制多种颜色,像彩虹一样🌈
const colorList = [ '252,240,91', '119,246,220', '92,219,138', '241,160,149', '252,240,91', '92,219,138', '119,246,220', ]; const colorLength = colorList.length; const step = Math.floor(list.length / colorLength); for(let index = 0; index < list.length; index++) { const colorIndex = Math.floor(index/step); let color = colorList[colorIndex] || colorList[colorLength - 1]; cxt.fillStyle = `rgb(${color})`; cxt.fillRect(list[index].w, list[index].h, 1, 1); } }
效果就变成了这样:
网络异常,图片无法展示
|
好丑啊~
颜色渐变✨
我陷入了僵局,十分的痛苦,我精心设计的头像不好看,岂不是白瞎了我写的代
码。。。
之后我受到了高人点拨:
网络异常,图片无法展示
|
对!加渐变!
const colorLength = colorList.length; const step = Math.floor(list.length / colorLength); for(let index = 0; index < list.length; index++) { const colorIndex = Math.floor(index/step); let color = colorList[colorIndex] || colorList[colorLength - 1]; if(colorIndex < colorLength - 1){ const percent = (index%step) / step; const colorFront = colorList[colorIndex].split(','); const colorBehind = colorList[colorIndex + 1].split(','); const rx = Number(colorBehind[0]) - Number(colorFront[0]); const gx = Number(colorBehind[1]) - Number(colorFront[1]); const bx = Number(colorBehind[2]) - Number(colorFront[2]); color = `${Number(colorFront[0])+Math.floor(rx * percent)},${Number(colorFront[1])+Math.floor(gx * percent)},${Number(colorFront[2])+Math.floor(bx * percent)}`; } cxt.fillStyle = `rgb(${color})`; cxt.fillRect(list[index].w, list[index].h, 1, 1); }
我就是在颜色数组做差,逐渐趋近,思路很简单~
之后效果就变成了这样子:
网络异常,图片无法展示
|
好看点了,但是总感觉有一点廉价~
磨砂感✨
廉价就加入磨砂,加入颗粒感!请叫我大聪明~
color = color.split(',').map(item => { const flag = Math.random() > 0.5; const random = Math.floor( 15 * Math.random()); if(flag){ return Number(item) - random; } return Number(item) + random; }).join(',');
其实就是对当前点的颜色做一点随机的加减
网络异常,图片无法展示
|
诶呀,感觉饱满起来了~
效果达成✨
当然别走开,后面还有精心调制的颜色,以及彩蛋~
完整代码✨
<!DOCTYPE html> <html lang="en"> <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> <style> #my-canvas { position: absolute; left: 30vw; top: 20vh; } </style> </head> <body> <canvas id="my-canvas"></canvas> <script> let myCanvas = document.getElementById("my-canvas"); let cxt = myCanvas.getContext("2d"); const hancaoImage = new Image(); hancaoImage.src = "hancao.jpeg"; hancaoImage.width = 212; hancaoImage.height = 199; hancaoImage.onload = function () { myCanvas.width = hancaoImage.width; myCanvas.height = hancaoImage.height; cxt.drawImage(hancaoImage, 0, 0); let imageData = cxt.getImageData(0, 0, hancaoImage.width, hancaoImage.height).data; cxt.fillStyle = "#ffffff"; cxt.fillRect(0, 0, 212, 199); let list = []; for (let h = 0; h < hancaoImage.height; h += 1) { for (let w = 0; w < hancaoImage.width; w += 1) { let position = (hancaoImage.width * h + w) * 4; let r = imageData[position], g = imageData[position + 1], b = imageData[position + 2], a = imageData[position + 3]; if (((r + g + b) < 665) && (r + g + b) > 410) { cxt.fillStyle = `rgba(166, 166, 255, 1)`; cxt.fillRect(w, h, 1, 1); list.push({ h, w }) } else if((r + g + b) < 410){ cxt.fillStyle = `rgb(0,0,0)`; cxt.fillRect(w, h, 1, 1); } } } const colorList = [ '79,181,118', '68,196,137', '40,169,174', '40,162,183', '76,119,136', '108,79,99', '67,44,57', ] const colorLength = colorList.length; const step = Math.floor(list.length / colorLength); for(let index = 0; index < list.length; index++) { const colorIndex = Math.floor(index/step); let color = colorList[colorIndex] || colorList[colorLength - 1]; if(colorIndex < colorLength - 1){ const percent = (index%step) / step; const colorFront = colorList[colorIndex].split(','); const colorBehind = colorList[colorIndex + 1].split(','); const rx = Number(colorBehind[0]) - Number(colorFront[0]); const gx = Number(colorBehind[1]) - Number(colorFront[1]); const bx = Number(colorBehind[2]) - Number(colorFront[2]); color = `${Number(colorFront[0])+Math.floor(rx * percent)},${Number(colorFront[1])+Math.floor(gx * percent)},${Number(colorFront[2])+Math.floor(bx * percent)}`; } color = color.split(',').map(item => { const flag = Math.random() > 0.5; const random = Math.floor( 15 * Math.random()); if(flag){ return Number(item) - random; } return Number(item) + random; }).join(','); cxt.fillStyle = `rgb(${color})`; cxt.fillRect(list[index].w, list[index].h, 1, 1); } } </script> </body> </html>
最终效果✨
网络异常,图片无法展示
|
富有层次,而且还有比较高级的颗粒感,真的很漂亮~
感谢大鹅🦢给我挑颜色~
于是我想感激大鹅,无以为报,只有以身。。。体力行的作品作为回报了:
网络异常,图片无法展示
|
我不会被骂吧。。。
结束语🌈
网络异常,图片无法展示
|
找寻学习前端最初始的快乐与成就感,尽在草系前端的前端冰可乐
写在最后
如果彩虹有第八种颜色
那就是你
祝大家拥有五彩斑斓的生活
伙伴们,如果喜欢我的文章,可以点赞 👍 关注➕ ,这是对我最大的支持。