前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[pixlate] 用 canvas 转像素画

[pixlate] 用 canvas 转像素画

原创
作者头像
kmokidd
发布2019-08-04 20:47:11
1.6K0
发布2019-08-04 20:47:11
举报

几周前看到这个像素猫的效果,这个版本的实现原理是 box-shadow,我想到用 grid 也可以实现一遍。接着发散到了“如何将任意图片像素化”上。

一开始的思路是如果还是用 grid 或者 box-shadow 的方式,需要遍历图片上的每个像素,拿到坐标和像素值,这样就需要用到 canvas。既然已经用到了 canvas… 其实就不用这么麻烦了,参考了 8-bit 的实现方法,可以用 drawImage 方法,将缩小的图片放大,通过 ctx.imageSmoothing = false 禁用掉浏览器器对图片平滑处理。

核心代码非常短:

代码语言:javascript
复制
var eightBit = function (canvas, image, scale) {
    scale *= 0.01;

    canvas.width = image.width;
    canvas.height = image.height;

		// 将图片缩小
    var scaledW = canvas.width * scale;
    var scaledH = canvas.height * scale;

    var ctx = canvas.getContext('2d');
  
		// 禁止浏览器的平滑处理
    ctx.mozImageSmoothingEnabled = false;
    ctx.webkitImageSmoothingEnabled = false;
    ctx.imageSmoothingEnabled = false;

    ctx.drawImage(image, 0, 0, scaledW, scaledH);
		// 但依然要画到和原图尺寸一样的画布上
    ctx.drawImage(canvas, 0, 0, scaledW, scaledH, 0, 0, canvas.width, canvas.height);
  };

背后的原理是将小尺寸的图片放到大尺寸的画布上,自然会“糊”,就像我们把 1x 的图片放在 Retina 屏幕上看一样。两者尺寸差别越大,模糊会越厉害,最极端的情况能到类似提取主题色那样的效果。因为要先缩小再真正画到画布上,所以先 draw image,再 draw canvas。从前我用 drawImage 基本画的都是媒体对象,这次画的是个 canvas 对象,对这个用法还蛮新奇的。根据 MDN,这个函数的第一个参数可以是任何的 canvas 图像源:

绘制到上下文的元素。允许任何的 canvas 图像源(CanvasImageSource),例如:CSSImageValueHTMLImageElementSVGImageElementHTMLVideoElementHTMLCanvasElementImageBitmap 或者OffscreenCanvas

如果不加上禁止平滑处理的话,出来的效果就会是这样,emm 谁把我的眼镜摘了:

CanvasRenderingContext2D.imageSmoothingEnabled 的文档里也说得很明白,如果开发者需要像素化的视觉效果,就需要禁用这个特性:

以缩放画布为例,这个属性对像素为主的游戏很有用。默认的改变大小的算法会造成图片模糊并且破坏图片原有的像素。 如果那样的话,设置属性值为false。 参见 CSS image-rendering 属性。

顺着这个属性,我爬到了 image-rendering 的文档页 — 哦!原来 image 也可以拿来这么处理啊。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档