【如何在JavaScript中删除画布周围的透明像素】在某些情况下, 当你使用Canvas或不使用Canvas时, 你将无法为画布提供固定的大小, 因为它可能是库自动生成的, 现在由你自行负责。这种方法的问题在于, 有时这些画布将在内容周围包含巨大的空白, 基本上是空白空间, 没人会在图像中希望这样做, 因为这会大大增加大小(视觉和文件大小)。
如果你想快速, 轻松地解决此问题, Remy Sharp编写的以下trimCanvas函数将帮助你解决许多开发人员在使用Canvas时可能需要的有问题的功能:
// MIT http://rem.mit-license.orgfunction trimCanvas(c) {var ctx = c.getContext('2d'), copy = document.createElement('canvas').getContext('2d'), pixels = ctx.getImageData(0, 0, c.width, c.height), l = pixels.data.length, i, bound = {top: null, left: null, right: null, bottom: null}, x, y;
// Iterate over every pixel to find the highest// and where it ends on every axis ()for (i = 0;
i <
l;
i += 4) {if (pixels.data[i + 3] !== 0) {x = (i / 4) % c.width;
y = ~~((i / 4) / c.width);
if (bound.top === null) {bound.top = y;
}if (bound.left === null) {bound.left = x;
} else if (x <
bound.left) {bound.left = x;
}if (bound.right === null) {bound.right = x;
} else if (bound.right <
x) {bound.right = x;
}if (bound.bottom === null) {bound.bottom = y;
} else if (bound.bottom <
y) {bound.bottom = y;
}}}// Calculate the height and width of the contentvar trimHeight = bound.bottom - bound.top, trimWidth = bound.right - bound.left, trimmed = ctx.getImageData(bound.left, bound.top, trimWidth, trimHeight);
copy.canvas.width = trimWidth;
copy.canvas.height = trimHeight;
copy.putImageData(trimmed, 0, 0);
// Return trimmed canvasreturn copy.canvas;
}
该函数的逻辑虽然不容易编写, 但很容易理解。该函数希望将画布对象作为第一个参数, 而不是上下文, 因为脚本需要复制画布才能创建具有其内容的新画布对象, 但不覆盖原始内容。然后, 所有像素都存储在一个数组中, 该数组将使用for循环进行迭代, 以在图像中找到最高边界点以对其进行修剪(基本上是使用存储画布数据的坐标来构建一个对象)。存储点(顶部, 左侧, 底部和右侧)后, 它们将用于剪切画布的原始数据并将新内容附加到创建的副本中。该副本由函数返回, 这意味着将返回另一个Canvas实例。
例子 在此示例中, 我们将向你展示如何使用以下代码修剪将在400× 400画布内绘制的火柴人:
<
canvas id="stickman" width="400" height="400">
<
/canvas>
<
script>
var canvas = document.getElementById("stickman");
context = canvas.getContext("2d");
// get Canvas Context objectcontext.beginPath();
context.fillStyle = "bisque";
// #ffe4c4context.arc(200, 50, 30, 0, Math.PI * 2, true);
// draw circle for head// (x, y) center, radius, start angle, end angle, anticlockwisecontext.fill();
context.beginPath();
context.strokeStyle = "red";
// colorcontext.lineWidth = 3;
context.arc(200, 50, 20, 0, Math.PI, false);
// draw semicircle for smilingcontext.stroke();
// eyescontext.beginPath();
context.fillStyle = "green";
// colorcontext.arc(190, 45, 3, 0, Math.PI * 2, true);
// draw left eyecontext.fill();
context.arc(210, 45, 3, 0, Math.PI * 2, true);
// draw right eyecontext.fill();
// bodycontext.beginPath();
context.moveTo(200, 80);
context.lineTo(200, 180);
context.strokeStyle = "navy";
context.stroke();
// armscontext.beginPath();
context.strokeStyle = "#0000ff";
// bluecontext.moveTo(200, 80);
context.lineTo(150, 130);
context.moveTo(200, 80);
context.lineTo(250, 130);
context.stroke();
// legscontext.beginPath();
context.strokeStyle = "orange";
context.moveTo(200, 180);
context.lineTo(150, 280);
context.moveTo(200, 180);
context.lineTo(250, 280);
context.stroke();
<
/script>
先前的代码将在画布上生成一个火柴人, 如果将其导出, 则png图像的结果如下:
文章图片
如你所见, 我们只想拥有火柴人, 但是我们的画布比绘制的路径大, 因此, 通过执行以下操作, 可以简单地使用trimCanvas函数丢弃很多空间:
// Crop and obtain the new canvasvar trimmedCanvas = trimCanvas(canvas);
// data:image/png;
base64, iVBORw0KGgoAAAANSUhE..........XTklIOUbk4AAAAAElFTkSuQmCCconsole.log(trimmedCanvas.toDataURL());
如果显示包含图像的生成的base64字符串的预览, 则输出现在将只是我们的火柴人, 因为trimCanvas函数删除了围绕原始画布的空白像素:
文章图片
编码愉快!
推荐阅读
- 制作还是嵌入(确定如何在你的应用程序中构建分析)
- 使用onlinetuner.co在JavaScript中实现Live Guitar Tuner
- 如何检查reCAPTCHA框是否已过期
- 使用VexFlow 2在JavaScript中渲染音乐符号(乐谱)
- 如何在JavaScript中从字符串名称执行函数(按名称执行函数)
- Java读取txt文件,并且对其文件内容进行统计排序
- Opencv图像读取,显示,保存,类型转换
- Java逐行读取数据
- java读取txt文件