大家好,我是寒草😈,一只草系码猿🐒。间歇性热血🔥,持续性沙雕🌟
如果喜欢我的文章,可以关注➕点赞,与我一同成长吧~
前言🌈
canvas萌新,如果做麻烦了,请多多包含
我是寒草,最近很烦恼,别人烦恼于事多钱少,而我却烦恼于头像少,给大家看看我的头像库:
我不仅仅有寒草,还有绿草,紫草,黑草,黄草,蓝草,红草...可谓是人丁兴旺,经常和我说话的朋友也会经常和我说:
“草哥你换头像了!”
“草哥,你又换头像了!!”
“草哥,你又双叒叕换头像了!!!”
没错,我的头像天天换一周也不会重样,但是我遇到了一个很痛苦的事情:
“我看腻了。。。”
正所谓男人都是大猪蹄子,没错,我对我的头像开始喜新厌旧了,所以我需要一个办法,让我的头像再次焕发生机,我的想法很简单:
“PS大法好!”
但是我拍了拍我那毛发旺盛的脑袋瓜,发现问题并不是那么简单,我不会PS啊,我是菜狗子。。。瞬间我的世界坍塌了,渴望新头像的强烈情感与不会PS的手足无措让我痛苦万分,甚至哭出声来,但是:
上帝给我们关上了一扇门,我们又不想去试图打开那扇门的时候,我们需要打开一扇窗,翻出去
于是我就想到了canvas,虽然我是canvas萌新,但是我却感觉到这件事情可行,于是说干就干!我要开始我的:
光辉荣耀的换头计划~
那么,我把头像变成什么颜色呢?
前几天北京的傍晚出现了彩虹:
所以,我不采用单色调了,我要把我的头像变成彩虹般五彩斑斓~岂不是非常炫酷,说干就干!
编码🌈
颜色提取✨
首先给大家看一下我的原始头像吧:
首先我要把绿色的部分提取出来,并把灰色的圆形背景去掉
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>
最终效果✨
富有层次,而且还有比较高级的颗粒感,真的很漂亮~
感谢大鹅🦢给我挑颜色~
于是我想感激大鹅,无以为报,只有以身。。。体力行的作品作为回报了:
我不会被骂吧。。。
结束语🌈
找寻学习前端最初始的快乐与成就感,尽在草系前端的前端冰可乐
写在最后
如果彩虹有第八种颜色
那就是你
祝大家拥有五彩斑斓的生活
伙伴们,如果喜欢我的文章,可以点赞 👍 关注➕ ,这是对我最大的支持。
加我微信:hancao97,邀你进群,了解寒草🌿 的github小组现状,一起学习前端,成为更优秀的工程师~(群二维码在这里->前端晚晚睡, 二维码过期了的话看链接沸点中的评论,我会把最新的二维码放在评论区,当然也可以加我微信我拉你进群,毕竟我也是有趣的前端,认识我也不赖🌟~)