user7946885
user7946885

Reputation:

Using globalCompositeOperation to mask canvas text with an image; how do i mask the text only but not its stroke?

I want a white border/stroke around my canvas text, but i also want the text to have a mask (but not the border). Is this possible?

This is what i am currently getting with the mask + stroke.

This is the code i am currently using:

function wrapText(ctx, text, x, y, maxWidth, lineHeight) {
    var cars = text.split("\n");

    for (var ii = 0; ii < cars.length; ii++) {
        var line = "";
        var words = cars[ii].split(" ");

        for (var n = 0; n < words.length; n++) {
            var testLine = line + words[n] + " ";
            var metrics = ctx.measureText(testLine);
            var testWidth = metrics.width;

            if (testWidth > maxWidth) {
                ctx.fillText(line, x, y);
                line = words[n] + " ";
                y += lineHeight;
            }
            else {
                line = testLine;
            }
        }
        ctx.fillText(line, x, y);
        y += lineHeight;
    }
}

function draw(x) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.save();
    ctx.beginPath();

    // put text on canvas
    var maxWidth = canvas.width - 100;
    var lineHeight = 100;
    var x = (canvas.width - maxWidth) / 2;
    var y = 100;

    ctx.font = "50px crewniverse_font";
    ctx.strokeStyle = 'white';
    ctx.miterLimit = 2;
    ctx.lineJoin = 'circle';
    ctx.lineWidth = 7;
    ctx.strokeText(inputText.value, x, y);
    ctx.lineWidth = 1;

    wrapText(ctx, inputText.value, x, y, maxWidth, lineHeight); //wrap the text

    // draw the mask
    ctx.beginPath();
    ctx.globalCompositeOperation = "source-in";
    ctx.drawImage(img, y * 4, y * 4, img.width, img.height, 0, 0, canvas.width, canvas.height);
    ctx.restore();
}

function init() {
    canvas.width = canvas.height = 1000;

    submitButton = document.getElementById('submit-button');
    submitButton.addEventListener('click', function() {
        draw();
    });
}

And this is what i am getting if i remove the wrapText() function and add the text just with ctx.fillText(inputText.value, canvas.width / 2, 20, canvas.width); instead.

Any idea how to do this?

Upvotes: 0

Views: 1355

Answers (1)

Kaiido
Kaiido

Reputation: 137006

Simply draw your stroke after you've done your compositing.

Simplified code :

var img = new Image();
img.onload = draw;
img.src = "https://upload.wikimedia.org/wikipedia/commons/5/55/John_William_Waterhouse_A_Mermaid.jpg"

var ctx = c.getContext('2d');

function draw() {
  // first fill the text
  ctx.font = '60px Impact';
  ctx.fillText('Hello World', 20, 80);
  // then do the compositing
  ctx.globalCompositeOperation = "source-in";
  ctx.drawImage(this, 0, 0);
  // finally go back to normal gCO
  ctx.globalCompositeOperation = "source-over";
  // and stroke the text
  ctx.strokeStyle = 'green';
  ctx.lineWidth = 2;
  ctx.strokeText('Hello World', 20, 80);

}
<canvas id="c"></canvas>

Upvotes: 3

Related Questions