【问题标题】:Image as a stencil for html canvas图像作为 html 画布的模板
【发布时间】:2018-09-25 20:46:54
【问题描述】:

我正在尝试让用户手动为图像的某些部分着色。例如,这是一只猫 https://techflourish.com/images/3-cat-clipart-9.png。如果他们愿意,用户应该能够在猫的脚上着色。我希望它们只在画布的猫身体图像部分内着色(不是图像的背景部分或画布的空白,但我想我可以手动修剪图像)。

到目前为止,我尝试过的内容如下。基本上,我会检查我所在位置的像素颜色,并且仅在不是该背景颜色时才绘制。这种工作,但我能够很容易地流血,因为有些东西是关闭的。我想知道是否可以设置特定的剪辑区域,但无法弄清楚。

`

    var canvas = document.getElementById("space");
    var ctx = canvas.getContext("2d");

    var pos = { x: 0, y: 0 };

    // new position from mouse events
    function setPosition(e) {
        pos.x = e.clientX;
        pos.y = e.clientY;
    }

    function rgbToHex(r, g, b) {
        if (r > 255 || g > 255 || b > 255)
            throw "Invalid color component";
        return ((r << 16) | (g << 8) | b).toString(16);
    }

    function draw(e) {
        if (e.buttons !== 1) return; // if mouse is pressed.....

        var color = "#cb3594";

        ctx.beginPath(); // begin the drawing path

        ctx.lineWidth = 5; // width of line
        ctx.lineCap = "round"; // rounded end cap
        ctx.strokeStyle = color; // hex color of line

        var p = ctx.getImageData(pos.x, pos.y, 1, 1).data;
        var sourceColor = rgbToHex(p[0], p[1], p[2]);
        if(sourceColor != "BACKGROUNDHEX" && sourceColor != color) {
            ctx.moveTo(pos.x, pos.y); // from position
            setPosition(e);
            p = ctx.getImageData(pos.x, pos.y, 1, 1).data;
            targetColor = rgbToHex(p[0], p[1], p[2]);

            if(targetColor != "BACKGROUNDHEX" && targetColor != color) {
                ctx.lineTo(pos.x, pos.y); // to position
                ctx.stroke(); // draw it!
            }
        }

    }

    var outlineImage = new Image();
    outlineImage.onload = function() {
        ctx.drawImage(outlineImage, 0, 0, 704, 720);
    }
    outlineImage.src = "IMAGE.png";

    space.addEventListener("mousemove", draw);
    space.addEventListener("mousedown", setPosition);
    space.addEventListener("mouseenter", setPosition);


</script>

`

(相关编辑:出血是由我的“sourceColor!= color”错误引起的,但问题仍然相关,因为这仍然不是一个很好的解决方案)

【问题讨论】:

  • 好吧,解决这个问题的一种方法是使用图像映射。这是我用来突出 &lt;map&gt; 元素中的 &lt;area&gt; 元素的东西。如果光标不在当前允许的多边形内,您可以简单地阻止任何标记操作。 stackoverflow.com/questions/12661124/…
  • 有意思,去看看

标签: javascript html canvas html5-canvas


【解决方案1】:

由于您不想着色的图像部分是透明的,您可以将上下文的globalCompositeOperation 设置为'source-atop'。之后,您在画布上绘制的任何像素都会自动采用被覆盖的像素的不透明度,并且您不必乱用getImageData

var canvas = document.getElementById("space");
var ctx = canvas.getContext("2d");

var pos = {
  x: 0,
  y: 0
};

// new position from mouse events
function setPosition(e) {
  // offsetX/Y gives the correct coordinates within the canvas
  // assuming it has no padding
  pos.x = e.offsetX;
  pos.y = e.offsetY;
}

function draw(e) {
  if (e.buttons !== 1) return; // if mouse is pressed.....

  var color = "#cb3594";

  ctx.beginPath(); // begin the drawing path

  ctx.lineWidth = 5; // width of line
  ctx.lineCap = "round"; // rounded end cap
  ctx.strokeStyle = color; // hex color of line

  ctx.moveTo(pos.x, pos.y); // from position
  setPosition(e);
  ctx.lineTo(pos.x, pos.y); // to position
  ctx.stroke(); // draw it!
}

var outlineImage = new Image();
outlineImage.onload = function() {
  // the default, set explicitly because we're changing it elsewhere
  ctx.globalCompositeOperation = 'source-over';
  
  ctx.drawImage(outlineImage, 0, 0);

  // don't draw over the transparent parts of the canvas
  ctx.globalCompositeOperation = 'source-atop';
  
  // wait until the stencil is loaded before handing out crayons
  space.addEventListener("mousemove", draw);
  space.addEventListener("mousedown", setPosition);
  space.addEventListener("mouseenter", setPosition);
}
outlineImage.src = "https://i.stack.imgur.com/so095.png";
&lt;canvas id="space" width="610" height="733"&gt;&lt;/canvas&gt;

【讨论】:

  • 谢谢你,真是太好了!
猜你喜欢
  • 2011-09-04
  • 2013-07-25
  • 1970-01-01
  • 2015-10-14
  • 2016-05-08
  • 2021-11-25
  • 2017-09-01
  • 2017-12-26
  • 2019-05-27
相关资源
最近更新 更多