-1

I have a HTMLCanvasElement which already has stuff drawn on it, and I need to make areas of it transparent. I do not know coordinates of that area, so I cannot use paths, but I know the color I want to get rid of.

Specifically, I have a html element containing text stoked as advised here: https://css-tricks.com/adding-stroke-to-web-text/ and I draw it on a canvas element, as advised here: Rendering HTML elements to <canvas>.

The problem is, that I want to make the white core of my text transparent on the resulting canvas element before using it further. So that only the text's stroke would remain.

Why don't I stroke text directly on the canvas? The reason is that I need to adjust letter spacing, and only CSS styling can do that.

The code snippet is a bit unreadable because in reality it's generated by compiling C# with Bridge.Net, but should give the general idea what I'm trying to do:

ConstructLabel$1: function (toWrite, font, letterSpacing, labelConstructed) {
            if (toWrite == null || Bridge.referenceEquals(toWrite, "")) {
                return null;
            }
            var canvas = document.createElement("canvas");
            var textElement = document.createElement("div");
            textElement.style.width = "auto";
            textElement.style.position = "absolute";
            textElement.style.whiteSpace = "nowrap";
            textElement.style.letterSpacing = letterSpacing;
            textElement.style.font = font;

            //make the storking of text
            textElement.style.color = "white";
            textElement.style.textShadow = "-1px -1px 0 #000,1px -1px 0 #000,-1px 1px 0 #000,1px 1px 0 #000";

            textElement.textContent = toWrite;

            //ToCanvas is my wrapper that takes a HTML element and returns a new canvas that
            //will draw a 1:1 representation of that element on it. It executes
            //the callback after it being drawn.
            return Utility.ToCanvas(textElement, function (drawnCanvas) {
                var ctx = drawnCanvas.getContext("2d");
                //ctx.ClearColor("white"); <----- how to do this?
                labelConstructed(drawnCanvas);
            });
        }
dukc
  • 121
  • 1
  • 9
  • 1
    I recommend updating your question with a [mcve] demonstrating the problem, ideally a **runnable** one using Stack Snippets (the `[<>]` toolbar button; [here's how to do one](https://meta.stackoverflow.com/questions/358992/ive-been-told-to-do-a-runnable-example-with-stack-snippets-how-do-i-do-tha)). That will make it crystal clear what the problem is without people having to follow links off-site, and will make it easier for them to show you solutions. – T.J. Crowder Apr 19 '18 at 12:47
  • I cannot make it runnable, but example snippet coming anyway – dukc Apr 19 '18 at 12:59
  • Um....why not? There's no problem uses `canvas` in snippets. Also note that what you've posted isn't, remotely, an MCVE. Please read the linked page for details. – T.J. Crowder Apr 19 '18 at 13:08
  • Because this IS minimal compared to what it would be if I included Utility.ToCanvas() to make it runnable. – dukc Apr 19 '18 at 13:15

1 Answers1

0

I finally found an answer here: https://gamedev.stackexchange.com/questions/19257/how-do-i-make-magenta-in-my-png-transparent-in-html5-canvas-js which applied here is:

ConstructLabel$1: function (toWrite, font, letterSpacing, labelConstructed) {

            [code here as earlier]

            return Utility.ToCanvas(textElement, function (drawnCanvas) {
                var ctx = drawnCanvas.getContext("2d");
                var matrix = ctx.getImageData(0, 0, drawnCanvas.width, drawnCanvas.height);
                var data = matrix.data;
                for (var i = 0; i < data.length; i = (i + 4) | 0) {
                    if (((((data[i] + data[((i + 1) | 0)]) | 0) + data[((i + 2) | 0)]) | 0) === 765) {
                        data[((i + 3) | 0)] = 0;
                    }
                }
                ctx.putImageData(matrix, 0, 0);
                labelConstructed(drawnCanvas);
            });
        },

This does leave some roughly-white pixels at inner sides of the text due to aliasing, but it can be corrected by changing the pixel condition if needed.

Result of doing filtering like this should be cached as it is a long loop to do stuff pixel-by-pixel.

dukc
  • 121
  • 1
  • 9