如何在JavaScript中删除画布周围的透明像素

【如何在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图像的结果如下:
如何在JavaScript中删除画布周围的透明像素

文章图片
如你所见, 我们只想拥有火柴人, 但是我们的画布比绘制的路径大, 因此, 通过执行以下操作, 可以简单地使用trimCanvas函数丢弃很多空间:
// Crop and obtain the new canvasvar trimmedCanvas = trimCanvas(canvas); // data:image/png; base64, iVBORw0KGgoAAAANSUhE..........XTklIOUbk4AAAAAElFTkSuQmCCconsole.log(trimmedCanvas.toDataURL());

如果显示包含图像的生成的base64字符串的预览, 则输出现在将只是我们的火柴人, 因为trimCanvas函数删除了围绕原始画布的空白像素:
如何在JavaScript中删除画布周围的透明像素

文章图片
编码愉快!

    推荐阅读