个性化阅读
专注于IT技术分析

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

在某些情况下, 当你使用Canvas或不使用Canvas时, 你将无法为画布提供固定的大小, 因为它可能是库自动生成的, 现在由你自行负责。这种方法的问题在于, 有时这些画布将在内容周围包含巨大的空白, 基本上是空白空间, 没人会在图像中希望这样做, 因为这会大大增加大小(视觉和文件大小)。

如果你想快速, 轻松地解决此问题, Remy Sharp编写的以下trimCanvas函数将帮助你解决许多开发人员在使用Canvas时可能需要的有问题的功能:

// MIT http://rem.mit-license.org
function 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 content
    var 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 canvas
    return 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 object

    context.beginPath();
    context.fillStyle = "bisque"; // #ffe4c4
    context.arc(200, 50, 30, 0, Math.PI * 2, true); // draw circle for head
    // (x, y) center, radius, start angle, end angle, anticlockwise
    context.fill();

    context.beginPath();
    context.strokeStyle = "red"; // color
    context.lineWidth = 3;
    context.arc(200, 50, 20, 0, Math.PI, false); // draw semicircle for smiling
    context.stroke();

    // eyes
    context.beginPath();
    context.fillStyle = "green"; // color
    context.arc(190, 45, 3, 0, Math.PI * 2, true); // draw left eye
    context.fill();
    context.arc(210, 45, 3, 0, Math.PI * 2, true); // draw right eye
    context.fill();

    // body
    context.beginPath();
    context.moveTo(200, 80);
    context.lineTo(200, 180);
    context.strokeStyle = "navy";
    context.stroke();

    // arms
    context.beginPath();
    context.strokeStyle = "#0000ff"; // blue
    context.moveTo(200, 80);
    context.lineTo(150, 130);
    context.moveTo(200, 80);
    context.lineTo(250, 130);
    context.stroke();

    // legs
    context.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 canvas
var trimmedCanvas = trimCanvas(canvas);

// data:image/png;base64, iVBORw0KGgoAAAANSUhE..........XTklIOUbk4AAAAAElFTkSuQmCC
console.log(trimmedCanvas.toDataURL());

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

从画布示例中删除透明像素

编码愉快!

赞(0)
未经允许不得转载:srcmini » 如何在JavaScript中删除画布周围的透明像素

评论 抢沙发

评论前必须登录!