// CAN\VAS.js plugin
        // ninivert, december 2016
        (function (window, document) {
            /**
             * CAN\VAS Plugin - Adding line breaks to canvas
             * @arg {string} [str=Hello World] - text to be drawn
             * @arg {number} [x=0]             - top left x coordinate of the text
             * @arg {number} [y=textSize]      - top left y coordinate of the text
             * @arg {number} [w=canvasWidth]   - maximum width of drawn text
             * @arg {number} [lh=1]            - line height
             * @arg {number} [method=fill]     - text drawing method, if 'none', text will not be rendered
             */
            CanvasRenderingContext2D.prototype.drawBreakingText = function (
                str,
                x,
                y,
                w,
                lh,
                method
            ) {
                // local variables and defaults
                var textSize = parseInt(this.font.replace(/\D/gi, ''));
                var textParts = [];
                var textPartsNo = 0;
                var words = [];
                var currLine = '';
                var testLine = '';
                str = str || '';
                x = x || 0;
                y = y || 0;
                w = w || this.canvas.width;
                lh = lh || 1;
                method = method || 'fill';

                // manual linebreaks
                textParts = str.split('\n');
                textPartsNo = textParts.length;

                // split the words of the parts
                for (var i = 0; i < textParts.length; i++) {
                    words[i] = textParts[i].split(&#039; &#039;);
                }

                // now that we have extracted the words
                // we reset the textParts
                textParts = [];

                // calculate recommended line breaks
                // split between the words
                for (var i = 0; i < textPartsNo; i++) {
                    // clear the testline for the next manually broken line
                    currLine = &#039;&#039;;

                    for (var j = 0; j < words[i].length; j++) {
                        testLine = currLine + words[i][j] + &#039; &#039;;

                        // check if the testLine is of good width
                        if (this.measureText(testLine).width > w && j > 0) {
                            textParts.push(currLine);
                            currLine = words[i][j] + &#039; &#039;;
                        } else {
                            currLine = testLine;
                        }
                    }
                    // replace is to remove trailing whitespace
                    textParts.push(currLine);
                }

                // render the text on the canvas
                for (var i = 0; i < textParts.length; i++) {
                    if (method === &#039;fill&#039;) {
                        this.fillText(
                            textParts[i].replace(/((\s*\S+)*)\s*/, &#039;$1&#039;),
                            x,
                            y + textSize * lh * i
                        );
                    } else if (method === &#039;stroke&#039;) {
                        this.strokeText(
                            textParts[i].replace(/((\s*\S+)*)\s*/, &#039;$1&#039;),
                            x,
                            y + textSize * lh * i
                        );
                    } else if (method === &#039;none&#039;) {
                        return {
                            textParts: textParts,
                            textHeight: textSize * lh * textParts.length,
                        };
                    } else {
                        console.warn(&#039;drawBreakingText: &#039; + method + &#039;Text() does not exist&#039;);
                        return false;
                    }
                }

                return {
                    textParts: textParts,
                    textHeight: textSize * lh * textParts.length,
                };
            };
        })(window, document);

        var canvas = document.createElement(&#039;canvas&#039;);
        var canvasWrapper = document.getElementById(&#039;canvasWrapper&#039;);
        canvasWrapper.appendChild(canvas);
        canvas.width = 500;
        canvas.height = 500;
        var ctx = canvas.getContext(&#039;2d&#039;);
        var padding = 15;
        var textTop = &#039;i don\&#039;t always make a meme&#039;;
        var textMiddle = &#039;but when i do, I use ninivert\&#039;s generator&#039;;
        var textBottom = &#039;but when i do, I use ninivert\&#039;s generator&#039;;
        var textSizeTop = 10;
        var textSizeMiddle = 10;
        var textSizeBottom = 10;
        var image = document.createElement(&#039;img&#039;);

        image.onload = function (ev) {
            // delete and recreate canvas to untaint it
            canvas.outerHTML = &#039;&#039;;
            canvas = document.createElement(&#039;canvas&#039;);
            canvasWrapper.appendChild(canvas);
            ctx = canvas.getContext(&#039;2d&#039;);
            document.getElementById(&#039;trueSize&#039;).click();
            document.getElementById(&#039;trueSize&#039;).click();

            draw();
        };

        document.getElementById(&#039;imgURL&#039;).oninput = function (ev) {
            image.src = this.value;
        };

        document.getElementById(&#039;imgFile&#039;).onchange = function (ev) {
            var reader = new FileReader();
            reader.onload = function (ev) {
                image.src = reader.result;
            };
            reader.readAsDataURL(this.files[0]);
        };

        document.getElementById(&#039;textTop&#039;).oninput = function (ev) {
            textTop = this.value;
            draw();
        };

        document.getElementById(&#039;textMiddle&#039;).oninput = function (ev) {
            textMiddle = this.value;
            draw();
        };

        document.getElementById(&#039;textBottom&#039;).oninput = function (ev) {
            textBottom = this.value;
            draw();
        };

        document.getElementById(&#039;textSizeTop&#039;).oninput = function (ev) {
            textSizeTop = parseInt(this.value);
            draw();
            document.getElementById(&#039;textSizeTopOut&#039;).innerHTML = this.value;
        };

        document.getElementById(&#039;textSizeMiddle&#039;).oninput = function (ev) {
            textSizeMiddle = parseInt(this.value);
            draw();
            document.getElementById(&#039;textSizeMiddleOut&#039;).innerHTML = this.value;
        };

        document.getElementById(&#039;textSizeBottom&#039;).oninput = function (ev) {
            textSizeBottom = parseInt(this.value);
            draw();
            document.getElementById(&#039;textSizeBottomOut&#039;).innerHTML = this.value;
        };

        document.getElementById(&#039;trueSize&#039;).onchange = function (ev) {
            if (document.getElementById(&#039;trueSize&#039;).checked) {
                canvas.classList.remove(&#039;fullwidth&#039;);
            } else {
                canvas.classList.add(&#039;fullwidth&#039;);
            }
        };

        document.getElementById(&#039;export&#039;).onclick = function () {
            var img = canvas.toDataURL(&#039;image/png&#039;);
            var link = document.createElement(&#039;a&#039;);
            link.download = &#039;My Meme&#039;;
            link.href = img;
            link.click();

            var win = window.open(&#039;&#039;, &#039;_blank&#039;);
            win.document.write(&#039;<img style="box-shadow: 0 0 1em 0 dimgrey;" src="&#039; + img + &#039;"/>&#039;);
            win.document.write(&#039;<h1 style="font-family: Helvetica; font-weight: 300">Right Click > Save As<h1>&#039;);
            win.document.body.style.padding = &#039;1em&#039;;
        };

        function style(font, size, align, base) {
            ctx.font = size + &#039;px &#039; + font;
            ctx.textAlign = align;
            ctx.textBaseline = base;
        }

        function draw() {
            // uppercase the text
            var top = textTop.toUpperCase();
            var middle = textMiddle.toUpperCase();
            var bottom = textBottom.toUpperCase();

            // set appropriate canvas size
            canvas.width = image.width;
            canvas.height = image.height;

            // draw the image
            ctx.drawImage(image, 0, 0, canvas.width, canvas.height);

            // styles
            ctx.fillStyle = &#039;#fff&#039;;
            ctx.strokeStyle = &#039;#000&#039;;
            ctx.lineWidth = canvas.width * 0.004;

            var _textSizeTop = (textSizeTop / 100) * canvas.width;
            var _textSizeMiddle = (textSizeMiddle / 100) * canvas.width;
            var _textSizeBottom = (textSizeBottom / 100) * canvas.width;

            // draw top text
            style(&#039;Impact&#039;, _textSizeTop, &#039;center&#039;, &#039;bottom&#039;);
            ctx.drawBreakingText(top, canvas.width / 2, _textSizeTop + padding, null, 1, &#039;fill&#039;);
            ctx.drawBreakingText(top, canvas.width / 2, _textSizeTop + padding, null, 1, &#039;stroke&#039;);

            // draw middle text
            style(&#039;Impact&#039;, _textSizeMiddle, &#039;center&#039;, &#039;middle&#039;);
            var height = ctx.drawBreakingText(middle, 0, 0, null, 1, &#039;none&#039;).textHeight;
            console.log(ctx.drawBreakingText(middle, 0, 0, null, 1, &#039;none&#039;));
            ctx.drawBreakingText(middle, canvas.width / 2, canvas.height / 2 - height / 2, null, 1, &#039;fill&#039;);
            ctx.drawBreakingText(middle, canvas.width / 2, canvas.height / 2 - height / 2, null, 1, &#039;stroke&#039;);

            // draw bottom text
            style(&#039;Impact&#039;, _textSizeBottom, &#039;center&#039;, &#039;top&#039;);
            var height = ctx.drawBreakingText(bottom, 0, 0, null, 1, &#039;none&#039;).textHeight;
            console.log(ctx.drawBreakingText(bottom, 0, 0, null, 1, &#039;none&#039;));
            ctx.drawBreakingText(bottom, canvas.width / 2, canvas.height - padding - height, null, 1, &#039;fill&#039;);
            ctx.drawBreakingText(bottom, canvas.width / 2, canvas.height - padding - height, null, 1, &#039;stroke&#039;);
        }

        image.src = &#039;https://imgflip.com/s/meme/The-Most-Interesting-Man-In-The-World.jpg&#039;;
        document.getElementById(&#039;textSizeTop&#039;).value = textSizeTop;
        document.getElementById(&#039;textSizeMiddle&#039;).value = textSizeMiddle;
        document.getElementById(&#039;textSizeBottom&#039;).value = textSizeBottom;
        document.getElementById(&#039;textSizeTopOut&#039;).innerHTML = textSizeTop;
        document.getElementById(&#039;textSizeMiddleOut&#039;).innerHTML = textSizeMiddle;
        document.getElementById(&#039;textSizeBottomOut&#039;).innerHTML = textSizeBottom;

Add a code snippet to your website: www.paste.org