Let's see how to achieve image mosaic stylization using CSS?

青灯夜游
Release: 2022-03-08 20:02:41
forward
2405 people have browsed it

How to add mosaics to pictures usingCSS? The following article will share with you how to skillfully use CSS to stylize image mosaics. I hope it will be helpful to you!

Let's see how to achieve image mosaic stylization using CSS?

1. Introduction to image-rendering

There is an interesting feature in CSS calledimage-rendering, which can use algorithms to better display zoomed images. (Recommended learning:css video tutorial)

Suppose we have a smaller screenshot of the QR code (left below, only a schematic diagram and cannot be scanned), and the image will be enlarged 10 times Will be blurred (right below):

Lets see how to achieve image mosaic stylization using CSS?

At this time, add theimage-rendering: pixelatedfeature to the enlarged image, and the CSS will pass the algorithm Display it as pixels so that the outline of the image has sharper edges:

Lets see how to achieve image mosaic stylization using CSS?

This feature is very suitable for applications with single colors, clear outlines, and images that need to be enlarged. Can create a pseudo-vector sense of déjà vu (reduce distortion after magnification).

For photos with rich colors and more details,image-rendering: pixelatedwill create a mosaic look:

Lets see how to achieve image mosaic stylization using CSS?

This is still far from the mosaic effect that the title of this article hopes to achieve - currently the image needs to be enlarged to display the effect, and we hope to cover the image with a mosaic of equal sizes while maintaining the original image size.

Howeverimage-renderingThe property will not take effect on elements whose size has not been scaled:

MDN- This property has no effect on non-scaled images.

2. Implementation of equal-sized mosaics

The principle of equal-sized mosaics is equivalent to first placing a photo Blurred, and then processed by a sharpening algorithm to obtain various small squares.

image-rendering: pixelatedhelped us achieve the "sharpening" step, but we have to think about how to achieve "blurring".

First of all, the blur solution using filters is not feasible becauseimage-renderingis strongly related to the image scaling factor, so you should think about how to use the scaling ability of the image.

I have to say here that pictures on the WEB are very much like smart objects in Photoshop - you can modify its size arbitrarily (for example, enlarge it many times to make it blurry), but in the end you can change the picture back. The picture will return to its original size (without any distortion).

How to retain the "blurred" information after the picture is enlarged is a priority issue that needs to be solved.

Smart friends have already thought of trying to usecanvasto process it. After all,canvascan easily obtain and draw images, and the drawn image information is pure data. , rather than a graphics object (Image), so the image data drawn by enlarging it and then shrinking it (to the original size) will be distorted (this is exactly what we want to happen).

But there are also some pitfalls here:

  • The information displayed after the external image is processed by theimage-rendering: pixelatedalgorithm,canvasIt's impossible to get it, because it's something on the display layer.canvasWhat you get is still unsharpened and blurred native image content;
  • canvasIf it is not zoomed, givecanvasAddingimage-rendering: pixelatedhas no meaning.

This means that you cannot enlarge and sharpen the image outsidecanvas, and then writecanvasto shrink the drawing (and continue to iterate). Get the sharpened original size image.

3. Interesting canvas stretching

When solving the above problems, let’s first take a look at an interesting feature ofcanvas.

If we define the width and height in thecanvastag:

Copy after login

At the same time, we define another width and height forcanvasin the style:

canvas { width: 200px; height: 200px; }
Copy after login

So in which size willcanvasbe displayed?

The answer is displayed in CSS size, but the content size of the canvas will be based on the width and height defined in the canvas tag. This means that although we see a canvas of200px * 200px, its content is actually stretched (2x in width and 4x in height).

Lets see how to achieve image mosaic stylization using CSS?

注:左边为画布,右边为原图

这也是canvas作为可替换元素的一个特性 —— CSS 无法修改其内容。试想一下,如果 CSS 可以动态地修改canvas内容的尺寸,意味着canvas的内容会被裁剪掉一部分,或者多出来一部分空白区域,这显然是不可取的。所以canvas在保留内容完整的前提下,整体伸缩到样式规定尺寸,是合理的浏览器行为。

利用canvas的这个特性,我们可以这样来实现等尺寸马赛克:

  • 创建一个画布,通过样式规定好其宽高,并设置image-rendering: pixelated特性;
  • 计算图片最佳展示尺寸(以类似background-size: contain的形式展示);
  • 将画布的宽高(非样式)设置为样式宽高的1/N
  • 绘制图像,绘制的图像宽高为最佳展示尺寸的1/N

如此一来,我们实际绘制了一个尺寸仅为最佳尺寸1/N的图像,再通过canvasN倍放大又变回了视觉上的最佳尺寸。图像因为走的canvas绘制,所以放大回最佳尺寸后会保持模糊,从而满足了image-rendering的匹配需求。

注:这里提到的“最佳尺寸”,指的是步骤 2 里“确保完整展示图像”所对应的最佳尺寸,而非图片原生尺寸。

四、代码实现

我们按照上方步骤来书写对应代码,当然我们希望灵活一些,例如上述的N可以由用户自定义。另外本章的代码可以在 Github 上获取

4.1 HTML 部分

主要为选择图片的控件、画布、方便画布获取图像的Let's see how to achieve image mosaic stylization using CSS?、供用户自定义缩放倍数的文本框、执行按钮:

  Let's see how to achieve image mosaic stylization using CSS?   
Copy after login

4.2 CSS 部分

我们需要通过样式规定好画布的外观尺寸,并配置image-rendering: pixelated特性。另外Let's see how to achieve image mosaic stylization using CSS?标签只是一个传递用户所选图片到画布的中介,可以直接隐藏:

canvas { display: block; border: gray solid 1px; width: 600px; height: 600px; image-rendering: pixelated; } img { display: none; }
Copy after login

4.3 JS 部分

let imgBlobUrl; const file = document.getElementById('file'); const img = document.getElementById('img-raw'); const compressTimes = document.getElementById('compress-times'); const defaultCompressTimes = compressTimes.value | 0; const canvas = document.getElementById('canvas'); const button = document.querySelector('button'); const boundingRect = canvas.getBoundingClientRect(); const ctx = canvas.getContext('2d'); const canvas_w = boundingRect.width; const canvas_h = boundingRect.height; // 以 background-size: contain 形式设置图片尺寸 function matchImgSizeToCanvas(imgElem = img) { let w = imgElem.width; let h = imgElem.height; if (w > canvas_w || h > canvas_h) { let radio = Math.max(h / canvas_h, w / canvas_w); radio = Number(radio.toFixed(2)); imgElem.width = parseInt(w / radio); imgElem.height = parseInt(h / radio); } } // 绘制 1/N 大小的图像,画布宽高属性设为样式宽高的 1/N,从而实现画布内容的 N 倍放大 function run() { let ct = parseInt(compressTimes.value) || defaultCompressTimes; canvas.width = parseInt(canvas_w / ct); canvas.height = parseInt(canvas_h / ct); ctx.drawImage(img, 0, 0, parseInt(img.width / ct), parseInt(img.height / ct)); } function cleanCanvas() { ctx.clearRect(0, 0, canvas_w, canvas_h); } function reset() { img.removeAttribute('width'); img.removeAttribute('height'); cleanCanvas(); matchImgSizeToCanvas(img); run(); } file.addEventListener('change', function (e) { window.URL.revokeObjectURL(imgBlobUrl); const picFile = this.files[0]; imgBlobUrl = window.URL.createObjectURL(picFile); img.onload = function init() { reset(); } img.src = imgBlobUrl; }, false); button.addEventListener('click', reset, false);
Copy after login

执行效果:

Lets see how to achieve image mosaic stylization using CSS?

选中文件/点击按钮后,能按压缩倍数得到对应的像素风格艺术照。

五、Mosaic 插件封装

通过上方示例我们学习了如何利用canvas特性来设计等尺寸的马赛克效果,现在我们尝试把该功能封装为一个简易插件,可以让页面上的图片列表一键 Mosaicing。

插件的实现方案也很简单 —— 用户点击按钮时,往图片容器上插入一个和容器等尺寸的画布(尺寸通过样式设置),再绘制覆盖画布的图像,并缩小画布的宽高属性来放大画布内容:

5.1 插件脚本

/** @file mosaic.js **/ class Mosaic { constructor(url, container, options = {}) { if (typeof container === 'string') { container = document.querySelector(container); } if (!url || !container?.style) { console.error('参数不正确'); } this.url = url; this.options = options; this.container = container; this.init(); } init() { const img = new Image(); const canvas = document.createElement('canvas'); canvas.style.position = 'absolute'; canvas.style.zIndex = 999; canvas.style.imageRendering = 'pixelated'; this.img = img; this.canvas = canvas; this.ctx = canvas.getContext('2d'); const containerBoundingRect = this.container.getBoundingClientRect(); const container_w = containerBoundingRect.width; const container_h = containerBoundingRect.height; // 通过样式初始化画布尺寸为容器尺寸 canvas.style.width = container_w + 'px'; canvas.style.height = container_h + 'px'; img.onload = () => { this.run(container_w, container_h); } img.src = this.url; } run(w, h) { // 缩小倍数,可以由参数传入,默认为 12 const compressTimes = parseInt(this.options.compressTimes) || 12; let compress_w = parseInt(w / compressTimes); let compress_h = parseInt(h / compressTimes); // 修改画布尺寸属性为 1/缩小倍数 this.canvas.width = compress_w; this.canvas.height = compress_h; // 绘制图片覆盖缩小后的画布 this.ctx.drawImage(this.img, 0, 0, compress_w, compress_h); this.container.prepend(this.canvas); this.img = null; } remove() { this.container.removeChild(this.canvas); this.canvas = null; } } export default Mosaic;
Copy after login

5.2 插件使用页

/** @file plugin-demo.html **/   
  • Let's see how to achieve image mosaic stylization using CSS?
  • Let's see how to achieve image mosaic stylization using CSS?
  • Let's see how to achieve image mosaic stylization using CSS?
  • Let's see how to achieve image mosaic stylization using CSS?
Copy after login

执行效果:

Lets see how to achieve image mosaic stylization using CSS?

点击“铺上”或“移除”按钮,可以轻松实现/移除列表上各图片的像素风格化。

六、兼容性

image-rendering的兼容性可以从caniuse上查到,目前覆盖率如下:

Lets see how to achieve image mosaic stylization using CSS?

影响较大的主要还是在 IE、UC,以及安卓 4.4.4 版本的浏览器,需要酌情考虑是否在产品上使用此 CSS 特性。


以上便是本文全部内容,相关代码可以在 Github 上获取(地址:https://github.com/VaJoy/BlogDemo3/tree/main/220226-pixelated)。

希望能令你有所收获,共勉~

(Learning video sharing:Web front-end introductory tutorial)

The above is the detailed content of Let's see how to achieve image mosaic stylization using CSS?. For more information, please follow other related articles on the PHP Chinese website!

source:juejin.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!