Rumah  >  Artikel  >  hujung hadapan web  >  Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?

Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?

青灯夜游
青灯夜游ke hadapan
2022-02-28 10:15:042499semak imbas

Bagaimana untuk menambah mozek pada imej menggunakan CSS? Artikel berikut akan berkongsi dengan anda cara menggunakan CSS dengan mahir untuk menggayakan mozek imej saya harap ia akan membantu anda!

Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?

1. Pengenalan kepada pemaparan imej

Terdapat ciri menarik dalam CSS yang dipanggil perenderan imej , yang boleh menggunakan algoritma untuk memaparkan imej yang dizum dengan lebih baik. (Pembelajaran yang disyorkan: tutorial video css)

Katakan kita mempunyai tangkapan skrin yang lebih kecil bagi kod QR (kiri di bawah, hanya gambar rajah skema dan tidak boleh diimbas), dan imej akan dibesarkan 10 kali akan dikaburkan (kanan di bawah):

Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?

Pada masa ini, tambahkan ciri image-rendering: pixelated pada imej yang diperbesarkan dan CSS akan pikselkannya melalui algoritma untuk membuat ia Garis besar imej mempunyai tepi yang lebih tajam:

Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?

Ciri ini sangat sesuai untuk aplikasi dengan warna tunggal, garis besar yang jelas dan imej yang perlu dibesarkan, mencipta pseudo-vektor kesan. Déjà vu (mengurangkan herotan selepas pembesaran).

Untuk foto dengan warna dan butiran yang kaya, image-rendering: pixelated akan mencipta rupa mozek:

Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?

Ini jauh daripada tajuk artikel ini kesan yang kami harap dapat dicapai masih agak jauh - pada masa ini imej perlu dibesarkan untuk memaparkan kesannya, dan kami berharap dapat menutup imej dengan mozek yang sama saiz sambil mengekalkan saiz imej asal.

Walau bagaimanapun, sifat image-rendering tidak akan berkuat kuasa ke atas elemen yang saiznya belum diskalakan:

MDN - Hartanah ini tidak mempunyai kesan ke atas bukan -imej berskala.

2 Pelaksanaan mozek bersaiz sama dalam lubang

Prinsip mozek bersaiz sama adalah bersamaan dengan mengaburkan foto dahulu , dan kemudian melepasinya Algoritma penajaman memproses pelbagai petak kecil.

image-rendering: pixelated membantu kami mencapai langkah "menajamkan", tetapi kami perlu memikirkan bagaimana untuk mencapai "kaburan".

Pertama sekali, penyelesaian kabur menggunakan penapis tidak akan berfungsi kerana image-rendering sangat berkaitan dengan faktor penskalaan imej, jadi anda harus memikirkan bagaimana anda boleh menggunakan keupayaan zum imej.

Saya perlu katakan di sini bahawa gambar di WEB sangat mirip dengan objek pintar dalam Photoshop - anda boleh mengubah suai saiznya sesuka hati (contohnya, membesarkannya berkali-kali untuk menjadikannya kabur), tetapi akhirnya anda boleh menukar gambar kembali. Gambar akan kembali ke saiz asalnya (tanpa sebarang herotan).

Cara mengekalkan maklumat "kabur" selepas gambar diperbesarkan adalah isu keutamaan yang perlu diselesaikan.

Rakan pintar sudah terfikir untuk cuba menggunakan canvas untuk mengendalikannya, canvas boleh mendapatkan dan melukis imej dengan mudah, dan maklumat imej yang dilukis adalah data tulen, bukan objek grafik (), jadi data imej yang dilukis dengan membesarkannya dan kemudian mengecilkannya (kepada saiz asal) akan diherotkan (inilah yang kita mahu berlaku). Image

Tetapi terdapat juga beberapa perangkap di sini:

    Maklumat yang dipaparkan selepas imej luaran diproses oleh algoritma
  • , image-rendering: pixelated tidak boleh diperolehi, kerana ia daripada perkara lapisan paparan. canvas Apa yang anda perolehi masih belum diasah dan kandungan imej asli yang kabur; jika canvas
  • itu sendiri tidak diskalakan, menambah canvas pada canvas tidak masuk akal. image-rendering: pixelated
Ini bermakna anda tidak boleh membesarkan dan menajamkan imej di luar

, dan kemudian menulis canvas untuk mengecilkan lukisan (dan terus mengulang) untuk mendapatkan imej saiz asal yang diasah. canvas

3. Regangan kanvas yang menarik

Apabila menyelesaikan masalah di atas, mari kita lihat

ciri yang menarik. canvas

Jika kita mentakrifkan lebar dan tinggi dalam tag

: canvas

<canvas width="100" height="50" ></canvas>
dan pada masa yang sama tentukan lebar dan tinggi lain untuk

dalam gaya: canvas

canvas {
  width: 200px;
  height: 200px;
}
Jadi dalam saiz manakah

akan dipaparkan? canvas

Jawapan dipaparkan dalam saiz CSS, tetapi saiz kandungan kanvas akan berdasarkan lebar dan ketinggian yang ditakrifkan dalam teg kanvas. Ini bermakna walaupun kita melihat kanvas

, kandungannya sebenarnya terbentang (2x lebar dan 4x tinggi). 200px * 200px

Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan 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 部分

主要为选择图片的 <input> 控件、画布、方便画布获取图像的 <img alt="Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?" >、供用户自定义缩放倍数的文本框、执行按钮:

  <input id="file" type="file" accept="image/*" />
  <canvas id="canvas"></canvas>
  <img  id="img-raw" / alt="Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?" >
  <label for="compress-times">压缩倍数:</label>
  <input id="compress-times" type="number" value="12">
  <button>马赛克化</button>

4.2 CSS 部分

我们需要通过样式规定好画布的外观尺寸,并配置 image-rendering: pixelated 特性。另外 <img alt="Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan 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(&#39;file&#39;);
    const img = document.getElementById(&#39;img-raw&#39;);
    const compressTimes = document.getElementById(&#39;compress-times&#39;);
    const defaultCompressTimes = compressTimes.value | 0;
    const canvas = document.getElementById(&#39;canvas&#39;);
    const button = document.querySelector(&#39;button&#39;);

    const boundingRect = canvas.getBoundingClientRect();
    const ctx = canvas.getContext(&#39;2d&#39;);
    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(&#39;width&#39;);
      img.removeAttribute(&#39;height&#39;);
      cleanCanvas();
      matchImgSizeToCanvas(img);
      run();
    }

    file.addEventListener(&#39;change&#39;, 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(&#39;click&#39;, reset, false);

执行效果:

Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?

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

五、Mosaic 插件封装

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

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

5.1 插件脚本

/** @file mosaic.js **/

class Mosaic {
    constructor(url, container, options = {}) {
        if (typeof container === &#39;string&#39;) {
            container = document.querySelector(container);
        }

        if (!url || !container?.style) {
            console.error(&#39;参数不正确&#39;);
        }

        this.url = url;
        this.options = options;
        this.container = container;

        this.init();
    }
    init() {
        const img = new Image();
        const canvas = document.createElement(&#39;canvas&#39;);
        canvas.style.position = &#39;absolute&#39;;
        canvas.style.zIndex = 999;
        canvas.style.imageRendering = &#39;pixelated&#39;;
        this.img = img;
        this.canvas = canvas;
        this.ctx = canvas.getContext(&#39;2d&#39;);
        const containerBoundingRect = this.container.getBoundingClientRect();
        const container_w = containerBoundingRect.width;
        const container_h = containerBoundingRect.height;

        // 通过样式初始化画布尺寸为容器尺寸
        canvas.style.width = container_w + &#39;px&#39;;
        canvas.style.height = container_h + &#39;px&#39;;

        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="Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?" ></li>
    <li><img  src="./assert/1.png" / alt="Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?" ></li>
    <li><img  src="./assert/2.png" / alt="Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?" ></li>
    <li><img  src="./assert/3.png" / alt="Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?" ></li>
  </ul>
  <div>
    <button id="generate">铺上马赛克</button>
    <button id="remove">移除马赛克</button>
  </div>


  <script type="module">
    import Mosaic from &#39;./mosaic.js&#39;;

    let liElems = document.querySelectorAll(&#39;li&#39;);
    let mosaicList = [];

    document.querySelector(&#39;#generate&#39;).onclick = () => {
      remove();
      for (let i = 0; i < liElems.length; i++) {
        let liElem = liElems[i];
        let url = liElem.querySelector(&#39;img&#39;).src;
        let mosaic = new Mosaic(url, liElem);
        mosaicList.push(mosaic);
      }
    }

    function remove() {
      mosaicList.forEach((mosaic) => {
        mosaic.remove();
      });
      mosaicList.length = 0;
    }

    document.querySelector(&#39;#remove&#39;).onclick = remove;

  </script>
</body>

执行效果:

Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?

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

六、兼容性

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

Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?

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


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

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

(Belajar perkongsian video: Tutorial pengenalan bahagian hadapan web)

Atas ialah kandungan terperinci Mari lihat bagaimana untuk mencapai penggayaan mozek imej menggunakan CSS?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:juejin.cn. Jika ada pelanggaran, sila hubungi admin@php.cn Padam