Bootstrap
博客内容搜索
Kaysama's Blog

群里跟人斗图的时候,有没有碰到这样的?

这时候没有图咋办?总不能真退群啊,但是又没图可以斗,于是乎~

唉,尴尬不尴尬,斗图拼的就是时效性,等你找到,黄花菜都凉了。于是乎,这篇博客就应运而生了

我会那么肤浅,直接把文字贴到图片上就算了?

你是喜欢下左边的图当表情还是右边的图?

是我就选右边,为啥?当然是因为高清的表情包是没有灵魂的,咳咳,当然是因为这个啦

这才是我们要的效果嘛,来,看我怎么实(zhuang)现(B)。

这里只谈核心实现,博客底部放源码和在线地址。

国际惯例,先讲原理:canvas有这么一个接口可以把canvas内容转化为base64字符串:HTMLCanvasElement.toDataURL(),接收俩参数,第一个是mime类型,如果mime是image/jpeg 或 image/webp,第二个参数表示输出质量,类型是0~1之间的浮点数,通过这个参数,我们就可以获取低质量的图片的base64字符串,然后将其赋值给一张图片的src属性,载入完成后再将这张图片绘制到canvas上,然后通过CanvasRenderingContext2D.getImageData() 获取每个像素的rgb数据,然后修改g通道的值,为了保证亮度不变,当g通道变化了delta,r和b通道应该变化-delta/2。

因为涉及的知识点不是很多,直接看render部分的代码吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function render () {
...
...
offScreenContext.fillStyle = '#ffffff'
offScreenContext.fillRect(0, 0, cvsWidth, cvsHeight)
...
...
originImageData = offScreenContext.getImageData(0, 0, cvsWidth, cvsHeight)
originImageDataContent = originImageData.data
var img = new Image()
img.onload = function () {
offScreenContext.drawImage(img, 0, 0, cvsWidth, cvsHeight)
imageData = offScreenContext.getImageData(0, 0, cvsWidth, cvsHeight)
imageDataContent = imageData.data
for (y = 0; y < cvsHeight; y++) {
for (x = 0; x < cvsWidth; x++) {
pos = y * cvsWidth + x
r = imageDataContent[pos * 4]
g = imageDataContent[pos * 4 + 1]
b = imageDataContent[pos * 4 + 2]
imageDataContent[pos * 4] = r - gOffset / 2 < 0 ? 0 : r - gOffset / 2
imageDataContent[pos * 4 + 1] = g + gOffset > 255 ? 255 : g + gOffset
imageDataContent[pos * 4 + 2] = b - gOffset / 2 < 0 ? 0 : b - gOffset / 2
imageDataContent[pos * 4 + 3] = originImageDataContent[pos * 4 + 3]
}
}
offScreenContext.putImageData(imageData, 0, 0)
context.drawImage(offScreenCanvas, 0, 0, cvsWidth, cvsHeight)
}
img.src = offScreenCanvas.toDataURL('image/jpeg', quality)
}

这里我用了两个canvas,一个用来做离屏渲染,提高性能,另一个是输出到屏幕上的。

额~好像其他没什么能讲的了,就这样吧,还有一些功能要完善,比如裁剪图片,修改图片在画布中的定位等,留个坑吧。

有什么其他好玩的建议欢迎交流

完整代码戳这里

在线演示