前言
前几日,在掘金刷到一片文章,叫产品经理:你能不能用div给我画条龙?,写得很生动,很有趣,就想着自己也去跟着作者去实现一下,话不多说,直接撸起袖子开干吧。
环境
window10 + vscode
搭建项目
因为只是为了实现效果,所以没有讲究其他什么性能,命名问题,直接就新建了一个html文件,取名也是粗暴,就叫"你不能不能用div给我画条龙.html",并添加一个canvas标签,用来作绘图准备。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Access-Control-Allow-Origin" content="*">
<title>你能不能用div给我画条龙</title>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
找图片
打开百度,直接搜索“龙 剪影”,选一张自己喜欢的图片,放在自己的工具目录中,取名 southeast.jpg
创建canvas上下文
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')
创建一个image实例
var image = new image
image.src = './imgs/southeast.jpg'
image.onload = function() {
canvas.width = image.width
canvas.height = image.height
// 绘图
ctx.drawImage(image, 0, 0)
}
现在显示的效果如下:
将图片像素化
要想实现图片像素化,可分为四步
1、获取像素
在canvas中有一个getImageData()的方法,可以获取图片的像素点
// 获取像素数据
var imageData = ctx.getImageData(0, 0, image.width, image.height)
2、点阵转换
imageData = convertPointArray(imageData)
// 点阵转换
function convertPointArray(image) {
for (var i=0; i<image.height; i=i+8) {
for (var j=0; j<image.width; j=j+8) {
var isCovered = isCover(image.data, image.width, i, j);
if (isCovered) {
image.data = drawPoints(image.data, image.width, i, j);
} else {
// 其他区域直接清空
image.data = drawPoints(image.data, image.width, i, j, true);
}
}
}
return image;
}
这里用到了一个帮助函数isCover,用来判断是否覆盖
// 判断像素块是否空白or像素覆盖
function isCover(imageData, width, x, y) {
var covered = 0
// 像素块为 8*8
for(var i = x; i < x + 8; i++) {
for (var j = y; j < y + 8; j++) {
var idx = i * 4 * width + 4 * j
// 阈值设为192
var r = imageData[idx]
var g = imageData[idx + 1]
var b = imageData[idx + 2]
if (r<192 || g<192 || b<192 ) {
covered++;
}
// 覆盖面积超过 45/64
if (covered > 45) {
return true;
}
}
}
return false
}
还用到了一个画点函数drawPoint:
// 填充像素块
function drawPoints(imageData, width, x, y, clear = false) {
for (var i = x; i < x + 8; i++) {
for (var j = y; j < y + 8; j++) {
var idx = i * 4 * width + 4 * j
if (i >=x+2 && i<x+6 && j>=y+2 && j<y+6 && !clear) {
// 画小方块
imageData[idx] = 168;
imageData[idx+1] = 168;
imageData[idx+2] = 168;
imageData[idx+3] = 192;
} else {
// 置为空白
imageData[idx] = 255;
imageData[idx+1] = 255;
imageData[idx+2] = 255;
imageData[idx+3] = 0;
}
}
}
return imageData
}
3、删除原来的图片
// 擦除原来的图片
ctx.clearRect(0, 0, canvas.width, canvas.height)
4、重新绘图
// 重新绘图
ctx.putImageData(imageData, 0, 0)
最后得到:
到此,结束,喜欢的朋友,可以点个关注,点个赞!
参考: