“This is the 11th day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021”

“If you can use CSS to change a picture of a heart into pixel style, I will date you today,” product sister told her colleague A Yang.

I patted a Yang’s shoulder, meaningfully said: “rest assured, senior will help you.”

What is pixel wind?

Pixel style is an art style that uses fixed size solid color pixel blocks as its basic unit for creation, including but not limited to painting, architecture, games and other fields. One of the most recognizable, of course, is the pixelated graphics of early video games



[Pixel image of Mario on the early Red and White machine]

Of course, early video games adoptedPixel windIn fact, it is a kind of historical helplessness, the limitations of hardware conditions, so that game developers have to choose thisCash power.Performance overheadLow art style.

However, pixel wind is still popular in all fields today, which is endowed with more aesthetic and retro significance.

Thought analysis

Let’s take a look at the original “love map” :



[Heart diagram]

To turn an image like this into pixels, the first thought came to mind:

Idea 1: Cut and fill with canvas

Canvas is used to cut the picture into N*N blocks, and then the median color of each area is calculated separately and filled with solid color. Yes, this idea can undoubtedly solve the problem quickly and flexibly. But in this way, without using CSS, my colleague a Yang’s first date would be completely ruined. ❌❌ no no no! I had to change my mind and use CSS!

Idea two: large radius Gaussian blur filter to take the median value

The main idea is as follows:

  1. Divide the image into N divs, each of which holds a portion of the image.
  2. Each div is evaluated once via CSS-filterBlur (blur)VisuallyTake the median value and populate the divThe effect.

According to this idea, there is only one difficulty: how to make each div hold a part of the image?

Oh, it can not be difficult to help my colleagues that big heart.

The implementation of

It’s not hard:

  1. First, we split a div into 64 parts with an 8 × 8 grid layout.



Code:

<style>
    .mask-group {
      width: 128px;
      height: 128px;
      display: grid;
      grid-template-columns: repeat(8.1fr);
      grid-template-rows: repeat(8.1fr);
    }
</style>
<script>
  const el = document.querySelector('.mask-group')
    for(let i = 0; i< 64; i++) {
      const itemEl = document.createElement('div')
      itemEl.className = 'mask-item'
      el.appendChild(itemEl)
    }
  }
</script>
Copy the code
  1. Then we give each of the.mask-item elements a heart-shaped background

And then it looks like this, because every background starts in the top left corner, so it definitely doesn’t match the expectations.



Next: we need to insert the following statement in the js traversal:

itemEl.style.backgroundPosition = ` -The ${Math.floor(i%8) * 16}px -The ${Math.floor(i/8) * 16}px `
Copy the code

This line of code gives each of the.mask-item elements a separate background-position style, calculating that the upper left corner of the background of all the.mask-item elements is superimposed on a single coordinate point. The effect is as follows:



3. Add spacing and Gaussian blur as envisaged, we just need to give divCombined with intervalAnd give inGaussian blur, can achieve the effect. So the code looks like this:

.mask-group {
  /* Add */
  grid-row-gap: 2px;
  grid-column-gap: 2px;
}
.mask-item {
  /* Add */
  filter: blur(8px)}Copy the code

But the effect is:

What went wrong? Gaussian blur applies to areas outside the inner-box.

  1. Mask-image defines the visible area

In order to limit the effect area of gaussian blur, I had to use mask-image. Start with a 16-by-16-pixel all-black. PNG file. The code is as follows:

.mask-item {
  /* Add */
  -webkit-mask-image: url('./all-black.png');
  mask-image: url('./all-black.png');  
}
Copy the code

Effect:

Hey hey, it’s like that now, but because of the gauss reason, the color is a lot lighter, nothing, fine tuning can be.

  1. Adjust the color

The code is as follows:

.mask-item {
  /* The following is the change */
  filter: blur(8px) contrast(400%) saturate(400%);
}
Copy the code



Done!!

The story ends

Absolutely did not expect, colleague a Yang still failed to complete and product sister small beauty date. The reason is: the product sister thinks I write code appearance is too pretty boy, must date with me!



— The end of the play