我正在参加「码上挑战赛」详情请看:码上挑战赛来了!

前语

说起图片的马赛克,可能一般都是由后端完成然后传递图片到前端,但是前端也是可以经过canvas来为图片加上马赛克的,下面就经过码上来进行一个简单的完成。

完成

完成过程

思路

最开始需求完成马赛克功能是需求经过canvas供给的一个获取到图片每一个像素的方法,咱们都知道,图片本质上仅仅由像素组成的,越明晰的图片,就有着越高的像素,而像素的本质,就仅仅一个个拥有色彩的小方块罢了,只要把一张图片放大多倍,就可以清楚的发现。

canvas完成

经过 canvas 的 getImageData 这个方法,咱们就可以拿到图画上一切像素组成的数组,而且需求生成马赛克,意味着咱们需求把一个范围内的色块的色彩都改成相同的,也便是经过canvas来重绘图片,

 let pixeArr = ctx.getImageData(0, 0, w, h).data;
let sampleSize = 40;
for (let i = 0; i < h; i += sampleSize) {
    for (let j = 0; j < h; j += sampleSize) {
      let p = (j + i * w) * 4;
      ctx.fillStyle =
        "rgba(" +
        pixeArr[p] +
        "," +
        pixeArr[p + 1] +
        "," +
        pixeArr[p + 2] +
        "," +
        pixeArr[p + 3] +
        ")";
      ctx.fillRect(j, i, sampleSize, sampleSize);
    }
}

经过双重循环来循环图片一切的色块,其间的跨度便是咱们设定好的色块巨细,色块调整的越大,马赛克后图片更含糊,越小,图片的含糊度就会下降。在经过 fillStyle 选取色彩,以及 fillRect 重绘 canvas 完成了将整个 canvas 的色块都进行改动,最终在导出重绘后的图片,无论是改动原来的图片地址,或许是新加一张图片作为比照,就都是可行的了。

canvas 跨域问题

在运用 getImageData 获取图片的时候,假如运用的是线上图片,浏览器会爆出跨域的错误:

前端线上图片生成马赛克

而上文中出现问题的图片是存放在本地的或许线上的,本地的图片默许是没有域名的,线上的图片而且是跨域的,所以浏览器都认为你是跨域,导致报错。

那么关于本地图片,咱们只需求将图片放到和html对应的文件夹下,子文件夹也是不可以的,就可以处理,关于线上的图片,咱们可以采用先把它下载下来,再用方法来获取数据的这种方式来进行。

function getBase64(imgUrl) {
  return new Promise(function (resolve, reject) {
    window.URL = window.URL || window.webkitURL;
    let xhr = new XMLHttpRequest();
    xhr.open("get", imgUrl, true);
    xhr.responseType = "blob";
    xhr.onload = function () {
      if (this.status == 200) {
        let blob = this.response;
        let oFileReader = new FileReader();
        oFileReader.onloadend = function (e) {
          let base64 = e.target.result;
          resolve(base64);
        };
        oFileReader.readAsDataURL(blob);
      }
    };
    xhr.send();
  });
}

下载图片就不说了,经过浏览器供给的 API 或许其他封装好的恳求工具都是可以的,在恳求成功之后,咱们将图片转化为 base64 而且回来,这样就可以获取线上图片的数据了。

总结

本文供给了一种前端生成马赛克图片的计划,而且关于线上的图片,也可以经过先异步下载图片在进行转化的战略,完成了图片增加马赛克的功能。