H5之canvas制作图片马赛克
原理:马赛克就是于取一块像素点换成他附近大小的像素点。
用到的比较少接触的api:
getImageData:
返回一个ImageData
对象,用来描述canvas区域隐含的像素数据,这个区域通过矩形表示,起始点为*(sx, sy)、宽为sw、高为sh。*
ImageData ctx.getImageData(sx, sy, sw, sh);
sx //将要被提取的图像数据矩形区域的左上角 x 坐标。
sy //将要被提取的图像数据矩形区域的左上角 y 坐标。
sw // 将要被提取的图像数据矩形区域的宽度。
sh // 将要被提取的图像数据矩形区域的高度。
返回一个ImageData 对象,包含canvas给定的矩形图像数据。
createImageData:
是 Canvas 2D API 创建一个新的、空白的、指定大小的 ImageData
对象。 所有的像素在新对象中都是透明的
ImageData ctx.createImageData(width, height);
ImageData ctx.createImageData(imagedata);
width // ImageData 新对象的宽度。
height // ImageData 新对象的高度。
imagedata //从现有的 ImageData 对象中,复制一个和其宽度和高度相同的对象。图像自身不允许被复制。
返回:指定了宽度和高度的,新的 ImageData 对象。 新对象使用透明的像素进行填充。
putImageData:
是 Canvas 2D API 将数据从已有的 ImageData
对象绘制到位图的方法。 如果提供了一个绘制过的矩形,则只绘制该矩形的像素。此方法不受画布转换矩阵的影响。
void ctx.putImageData(imagedata, dx, dy);
void ctx.putImageData(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight);
imageData // ImageData ,包含像素值的数组对象。
dx //源图像数据在目标画布中的位置偏移量(x 轴方向的偏移量)。
dy //源图像数据在目标画布中的位置偏移量(y 轴方向的偏移量)。
dirtyX //可选,在源图像数据中,矩形区域左上角的位置。默认是整个图像数据的左上角(x 坐标)。
dirtyY //可选,在源图像数据中,矩形区域左上角的位置。默认是整个图像数据的左上角(y 坐标)。
dirtyWidth //可选,在源图像数据中,矩形区域的宽度。默认是图像数据的宽度。
dirtyHeight //可选,在源图像数据中,矩形区域的高度。默认是图像数据的高度。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style> * { margin: 0; padding: 0; } #canvas { height: 300px; width: 600px; position: absolute; left: 50%; top: 50%; transform: translate3d(-50%, -50%, 0); transform: translate3d(-50%, -50%, 0); background-color: #0077AA; } </style>
</head>
<body>
<canvas id='canvas'></canvas>
</body>
<script> //Canvas_operation const Canvas_operation = function() { // 获取ImageData单个像素点 this.GetPixel = function(ImageData, x, y) { var ColorArr = [] var width = ImageData.width; // 由ragb组成 所以*4 每四位四位取 // width * y + x 之前有多少个像素点 == width*y + x => 还是那张图 去看透 ColorArr[0] = ImageData.data[(width * y + x) * 4 + 0] ColorArr[1] = ImageData.data[(width * y + x) * 4 + 1] ColorArr[2] = ImageData.data[(width * y + x) * 4 + 2] ColorArr[3] = ImageData.data[(width * y + x) * 4 + 3] return ColorArr; } // 写入ImageData单个像素点 this.SetPixel=function(ImageData, x, y, ColorArr) { var width = ImageData.width; ImageData.data[(width * y + x) * 4 + 0] = ColorArr[0]; ImageData.data[(width * y + x) * 4 + 1] = ColorArr[1]; ImageData.data[(width * y + x) * 4 + 2] = ColorArr[2]; ImageData.data[(width * y + x) * 4 + 3] = ColorArr[3]; } //画布中的文字水平垂直居中 this.text_center = function(canvas, ctx, textValue = "默认文字", fontSize = 10, fontColor = "blue", textBaseline = "middle", fill_stroke = "fill") { // 兼容ES5 textValue = textValue == undefined ? "默认文字" : textValue fontSize = fontSize == undefined ? 10 : fontSize fontColor = fontColor == undefined ? "blue" : fontColor textBaseline = textBaseline == undefined ? "middle" : textBaseline fill_stroke = fill_stroke == undefined ? "fill" : fill_stroke ctx.save() fill_stroke == "fill" ? ctx.fillStyle = fontColor : ctx.strokeRect = fontColor ctx.font = fontSize + "px" + " " + "serif" ctx.textBaseline = textBaseline ctx.beginPath() let text = ctx.measureText(textValue) fill_stroke == "fill" ? ctx.fillText(textValue, canvas.width / 2 - text.width / 2, canvas.height / 2) : ctx.strokeText(textValue, canvas.width / 2 - text.width / 2, canvas.height / 2) ctx.restore() /* 参数: canvas(DOM对象) ctx(getcontext('2d')的对象) textValue 文本内容(String) fontSize 字体大小(Number) fontColor 字体颜色(String) textBaseline 文本对准基线(String) fill_stroke 画的字体是什么种类的(String) 返回: 没有返回值 调用示例: text_center(canvas, ctx, '这是一个已经封装好的画布文本居中显示',40,"pink" ,'middle',"fill") text_center(canvas, ctx, '这是一个已经封装好的画布文本居中显示',40,"blue","middle","storke") */ } } </script>
<script> const canvas = document.querySelector('#canvas') var ctx = canvas.getContext('2d') var size = 5 // 模糊尺寸 const cxy = new Canvas_operation() var img = new Image() img.src = 'Images/01.jpg' img.onload = function() { ctx.drawImage(img, 0, 0, 150, 300) console.log('注意canvas没有异步思想01,我帮读者踩坑') // 获取所有老图的像素点 let OldImgData = ctx.getImageData(0, 0, 150, 300) //OldImgData里面的data一串 由ragb组成 // 创建新图像素对象 let NewImgData = ctx.createImageData(300, 300) // 循环:将老图的像素点 复制到 新图像素点并且模糊size部分大小, for (let i = 0; i < OldImgData.width; i++) { for (let j = 0; j < OldImgData.height; j++) { //(i,j)是每个马赛克矩形的坐标 var color = cxy.GetPixel(OldImgData, Math.floor(i * size + Math.random() * size), Math.floor(j * size + Math.random() * size)) //马赛克原理在于取一块像素点换成size附近大小的像素点 for (var a = 0; a < size; a++) { for (var b = 0; b < size; b++) { cxy.SetPixel(NewImgData, i * size + a, j * size + b, color); } } } } ctx.putImageData(NewImgData,150,0) } console.log('注意canvas没有异步思想02,我帮读者踩坑') ctx.save() ctx.beginPath() ctx.restore() </script>
</html>
效果图:
还没有评论,来说两句吧...