ホームページ > 記事 > ウェブフロントエンド > CSS を使用して画像モザイクの様式化を実現する方法を見てみましょう。
CSS を使用して写真にモザイクを追加するにはどうすればよいですか?次の記事では、CSS を上手に使って画像モザイクのスタイルを設定する方法を紹介します。
image-rendering## と呼ばれる興味深い機能があります。 # 、アルゴリズムを使用してズームされた画像をより適切に表示できます。 (推奨される学習: css ビデオ チュートリアル ) QR コードの小さいスクリーンショット (下左、概略図のみでスキャンできません) があるとします。画像は拡大されます。 10 回 ぼかします (右下):
このとき、拡大画像に
image-rendering:pixelated 機能を追加し、 CSS は、画像の輪郭がより鮮明になるように、ピクセルとして表示するアルゴリズムを渡します。
この機能は、単色、明確な輪郭、および擬似ベクトルの既視感を作り出すことができます(拡大後の歪みを軽減します)。
豊かな色とより詳細な写真の場合、
image-rendering:pixelated によりモザイクのような外観が作成されます:
これはまだですこの記事のタイトルで実現したいモザイク効果とは程遠いです。現在、効果を表示するには画像を拡大する必要がありますが、元の画像サイズを維持しながら同じサイズのモザイクで画像をカバーしたいと考えています。
ただし
image-rendering このプロパティは、サイズがスケールされていない要素には効果がありません:
MDN#2. 等サイズ モザイクの実装
image-rendering:pixelated
は「シャープ化」ステップを達成するのに役立ちましたが、「ぼかし」を達成する方法を考える必要があります。まず第一に、
image-rendering
ここで言わなければならないのは、WEB 上の写真は Photoshop のスマート オブジェクトによく似ているということです。サイズは任意に変更できます (たとえば、何回も拡大してぼやけるなど)。画像を元に戻すことができます。画像は元のサイズ (歪みなし) に戻ります。
canvas
を使って処理しようと考えているでしょう。結局のところ、canvas は簡単に画像を取得して描画することができ、描画された画像情報は純粋ですdata. はグラフィックス オブジェクト (
Image) ではなく、そのため、拡大してから (元のサイズに) 縮小することで描画された画像データは歪みます (これがまさに私たちが望んでいることです)。
しかし、ここにはいくつかの落とし穴もあります。
外部画像が
image-rendering:pixelated 表示レイヤー上にあるものなので取得することは不可能です。
canvas 得られるのは、まだシャープ化されておらずぼやけたネイティブ画像コンテンツです。
canvas# を追加しますimage-rendering:pixelated
には意味がありません。
これは、
canvas を記述して図面を縮小したり (繰り返しを継続したり) できないことを意味します。シャープ化された元のサイズの画像。 3. 興味深いキャンバスの伸縮
canvas
タグで幅と高さを定義する場合:
<canvas width="100" height="50" ></canvas>
同時に、canvas
に別の幅と高さを定義します。スタイル:
canvas { width: 200px; height: 200px; }
それでは、canvas
はどのサイズで表示されますか?
答えは CSS サイズで表示されますが、キャンバスのコンテンツのサイズは、canvas タグで定義された幅と高さに基づきます。これは、200px * 200px
のキャンバスが表示されますが、そのコンテンツは実際には引き伸ばされていることを意味します (幅 2 倍、高さ 4 倍)。
注:左边为画布,右边为原图
这也是 canvas
作为可替换元素的一个特性 —— CSS 无法修改其内容。试想一下,如果 CSS 可以动态地修改 canvas
内容的尺寸,意味着 canvas
的内容会被裁剪掉一部分,或者多出来一部分空白区域,这显然是不可取的。所以 canvas
在保留内容完整的前提下,整体伸缩到样式规定尺寸,是合理的浏览器行为。
利用 canvas
的这个特性,我们可以这样来实现等尺寸马赛克:
image-rendering: pixelated
特性;background-size: contain
的形式展示);1/N
;1/N
。如此一来,我们实际绘制了一个尺寸仅为最佳尺寸 1/N
的图像,再通过 canvas
的 N
倍放大又变回了视觉上的最佳尺寸。图像因为走的 canvas
绘制,所以放大回最佳尺寸后会保持模糊,从而满足了 image-rendering
的匹配需求。
注:这里提到的“最佳尺寸”,指的是步骤 2 里“确保完整展示图像”所对应的最佳尺寸,而非图片原生尺寸。
我们按照上方步骤来书写对应代码,当然我们希望灵活一些,例如上述的 N
可以由用户自定义。另外本章的代码可以在 Github 上获取。
4.1 HTML 部分
主要为选择图片的 <input>
控件、画布、方便画布获取图像的 <img alt="CSS を使用して画像モザイクの様式化を実現する方法を見てみましょう。" >
、供用户自定义缩放倍数的文本框、执行按钮:
<input id="file" type="file" accept="image/*" /> <canvas id="canvas"></canvas> <img id="img-raw" / alt="CSS を使用して画像モザイクの様式化を実現する方法を見てみましょう。" > <label for="compress-times">压缩倍数:</label> <input id="compress-times" type="number" value="12"> <button>马赛克化</button>
4.2 CSS 部分
我们需要通过样式规定好画布的外观尺寸,并配置 image-rendering: pixelated
特性。另外 <img alt="CSS を使用して画像モザイクの様式化を実現する方法を見てみましょう。" >
标签只是一个传递用户所选图片到画布的中介,可以直接隐藏:
canvas { display: block; border: gray solid 1px; width: 600px; height: 600px; image-rendering: pixelated; } img { display: none; }
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);
执行效果:
选中文件/点击按钮后,能按压缩倍数得到对应的像素风格艺术照。
通过上方示例我们学习了如何利用 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;
5.2 插件使用页
/** @file plugin-demo.html **/ <head> <style> ul { list-style: none; margin: 0; padding: 0; } li { float: left; line-height: 0; margin: 0 20px 20px 0; } li>img { max-height: 180px; } div { display: block; clear: both; } </style> </head> <body> <ul> <li><img src="./assert/0.png" / alt="CSS を使用して画像モザイクの様式化を実現する方法を見てみましょう。" ></li> <li><img src="./assert/1.png" / alt="CSS を使用して画像モザイクの様式化を実現する方法を見てみましょう。" ></li> <li><img src="./assert/2.png" / alt="CSS を使用して画像モザイクの様式化を実現する方法を見てみましょう。" ></li> <li><img src="./assert/3.png" / alt="CSS を使用して画像モザイクの様式化を実現する方法を見てみましょう。" ></li> </ul> <div> <button id="generate">铺上马赛克</button> <button id="remove">移除马赛克</button> </div> <script type="module"> import Mosaic from './mosaic.js'; let liElems = document.querySelectorAll('li'); let mosaicList = []; document.querySelector('#generate').onclick = () => { remove(); for (let i = 0; i < liElems.length; i++) { let liElem = liElems[i]; let url = liElem.querySelector('img').src; let mosaic = new Mosaic(url, liElem); mosaicList.push(mosaic); } } function remove() { mosaicList.forEach((mosaic) => { mosaic.remove(); }); mosaicList.length = 0; } document.querySelector('#remove').onclick = remove; </script> </body>
执行效果:
点击“铺上”或“移除”按钮,可以轻松实现/移除列表上各图片的像素风格化。
image-rendering
的兼容性可以从 caniuse 上查到,目前覆盖率如下:
影响较大的主要还是在 IE、UC,以及安卓 4.4.4 版本的浏览器,需要酌情考虑是否在产品上使用此 CSS 特性。
以上便是本文全部内容,相关代码可以在 Github 上获取(地址:https://github.com/VaJoy/BlogDemo3/tree/main/220226-pixelated)。
希望能令你有所收获,共勉~
(学習ビデオ共有: Web フロントエンド入門チュートリアル )
以上がCSS を使用して画像モザイクの様式化を実現する方法を見てみましょう。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。