Hello everyone, I am Han Cao 😈, a grass code ape 🐒. Intermittent warm blood ðŸ”Ĩ, continuous sand sculpture 🌟 if you like my article, you can pay attention to ➕ like, and grow with me ~

Preface 🌈

Canvas is new, please include more if you have trouble

I am Hancao. Recently, I have been very worried. Others are worried about more things and less money, but I am worried about less head pictures.

I have not only cold grass, but also green grass, purple grass, black grass, yellow grass, blue grass, red grass… My friends who used to talk to me often said to me,

“Grass elder brother you change head picture!” “Grass elder brother, you changed head again!!” “Grass elder brother, you double 叒 yi for head!!”

Sure, my profile picture changes every day and every week, but I’ve had a painful experience:

“I’m tired of watching…”

Men are hoofs. Yes, I had a crush on my avatar, so I needed a way to make my avatar come alive again. My idea was simple:

“Good photoshop!”

But I patted my hairy head and realized that the problem is not that simple. I can’t photoshop, I’m a vegetable dog… Instantly my world collapsed, and my intense desire for a new avatar and my inability to photoshop made me cry, but:

When god closes a door for us and we don't want to try to open that door, we need to open a window and get out

So I think of canvas. Although I am new to canvas, I feel that this thing is feasible, so I go ahead and do it! I’m going to start mine:

Glorious hair change plan ~

So, what color do I make my head?

There was a rainbow at dusk in Beijing the other day:

So, instead of using one color, I’m going to make my avatar a rainbow of colors.

Coding 🌈

Color extraction âœĻ

Let me first show you my original avatar:

First I want to extract the green parts and remove the grey circular background

let myCanvas = document.getElementById("my-canvas");
let cxt = myCanvas.getContext("2d");
const hancaoImage = new Image();
hancaoImage.src = "hancao.jpeg";
// The size of my avatar
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;
  // White fill
  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];
      // Given a color range, place the points that match the range into a list array for subsequent processing
      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);
        cxt.fillRect(w, h, 1.1); }}}Copy the code

So what happens is, I’ve already stored the purple points in the array.

Draw multiple colors âœĻ

Next I need to draw multiple colors, like a rainbow 🌈

const colorList = [
    '252240,91'.'119246220'.'92219138'.'241160149'.'252240,91'.'92219138'.'119246220',];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); }}Copy the code

The effect is this:

How ugly

Color gradient âœĻ

I was in an impasse, very painful, I carefully designed the avatar is not good-looking, is not the white blind CODE I wrote… And then I got this great advice:

Right! The gradient.

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 = `The ${Number(colorFront[0]) +Math.floor(rx * percent)}.The ${Number(colorFront[1]) +Math.floor(gx * percent)}.The ${Number(colorFront[2]) +Math.floor(bx * percent)}`;
    }
    cxt.fillStyle = `rgb(${color}) `;
    cxt.fillRect(list[index].w, list[index].h, 1.1);
}
Copy the code

I just do the difference in the array of colors, gradually approaching, the idea is very simple ~ after the effect is like this:

It looks better, but it feels a little cheap

Grind arenaceous feeling âœĻ

Add cheap matte, add granular sense! Please call me big smart ~

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(', ');
Copy the code

It’s just a random addition or subtraction to the color of the current point

Ah, feel full up ~ effect reached âœĻ

Of course, don’t go away, there are carefully mixed colors behind, and eggs ~

Full code âœĻ

<! DOCTYPEhtml>
<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>Cold grass head</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);
            cxt.fillRect(w, h, 1.1); }}}const colorList = [
        '79181118'.'68196137'.'40169174'.'40162183'.'76119136'.'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 = `The ${Number(colorFront[0]) +Math.floor(rx * percent)}.The ${Number(colorFront[1]) +Math.floor(gx * percent)}.The ${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>
Copy the code

Final effect âœĻ

Rich level, and there are more advanced granular sense, really beautiful ~

Thank you goose ðŸĶĒ give me pick color ~

So I want to be grateful to the goose, no thought in return, only to the body… Physical work in return:

I’m not gonna get yelled at…

Conclusion 🌈

To find the initial happiness and sense of achievement in the front of the front of the grass system

If there is an eighth color in the rainbow, you wish everyone a colorful life

Guys, if you like my article, you can like 👍 and follow ➕, which is the biggest support for me.

Add me on wechat: Hancao97, invite you into the group, understand the status quo of the Github group of han Grass ðŸŒŋ, learn front end together, become a better engineer ~ (group QR code is here -> front end late to sleep, qr code is overdue to see the comments in the boiling point of the link, I will put the latest QR code in the comment area, of course, you can also add my wechat I pull you into the group, After all, I’m also a fun front end, so it’s nice to know me 🌟 ~)