Saint Robson
Saint Robson

Reputation: 5525

HTML Canvas Refresh Some Part, Not All

I want to create some kind of meme generator using HTML Canvas, which has 2 text inserted from 2 text fields. here's my code :

<body>
    <canvas id="canvas" style="background-color: #ffb515;">
        Sorry, canvas not supported
    </canvas>

    <img id="canvasimg" src="kindle.jpg" style="display:none;"/>

    <input type='text' value='enter some text' id='canvastext-top'/>
    <input type='text' value='enter some text' id='canvastext-bottom'/>

    <script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
    <script>
        var canvas = document.getElementById('canvas');
        ctx = canvas.getContext('2d');

        var deviceWidth = window.innerWidth;;
        canvasWidth = Math.min(500, deviceWidth-20);
        canvasHeight = Math.min(500, deviceWidth-20);

        canvas.width = canvasWidth;
        canvas.height = canvasHeight;

        var img = document.getElementById('canvasimg');

        img.onload = function() {
            x = canvas.width/2 - img.width/2;
            y = canvas.height/2 - img.height/2;
            //ctx.drawImage(img, x, y);
        }

        $("#canvastext-top").keyup(function(){              
            ctx.lineWidth = 8;
            ctx.font = '20pt Verdana';
            ctx.strokeStyle = 'black';
            ctx.fillStyle = 'white';
            ctx.textAlign = 'center';
            ctx.lineJoin = 'round';

            var text = document.getElementById('canvastext-top').value;
            text = text.toUpperCase();
            x = canvas.width/2;
            y = canvas.height - canvas.height/1.2;
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.strokeText(text, x, y);
            ctx.fillText(text, x, y);
        });


        $("#canvastext-bottom").keyup(function(){               
            ctx.lineWidth = 8;
            ctx.font = '20pt Verdana';
            ctx.strokeStyle = 'black';
            ctx.fillStyle = 'white';
            ctx.textAlign = 'center';
            ctx.lineJoin = 'round';

            var text = document.getElementById('canvastext-bottom').value;
            text = text.toUpperCase();
            x = canvas.width/2;
            y = canvas.height - canvas.height/4.5;
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.strokeText(text, x, y);
            ctx.fillText(text, x, y);
        });
    </script>
</body>

now the problem is in this line :

ctx.clearRect(0, 0, canvas.width, canvas.height);

If I'm not refreshing my canvas, the text will look like this :

ugly text without no refresh

but, if I'm using that refresh canvas method, once I type on the second text field, the first text will be refreshed and disappear.

how to still use this refresh but keep the first text on the canvas while editting the second text. and vice versa.

thank you.

PS : here's the fiddle http://jsfiddle.net/robtn532/

Upvotes: 1

Views: 382

Answers (2)

Andy Lewis
Andy Lewis

Reputation: 334

Fiddle here: http://jsfiddle.net/af5jf0ob/

So essentially I moved all of your drawing logic into one function that is called repeatedly. Every time the function is called it reads the value from the textboxes and renders them to the screen in one pass. This is the same as a basic game loop. The code can be tidied up a bit yet but this should get you going.

var text1Y = y = canvas.height - canvas.height/1.2;
var text2Y = y = canvas.height - canvas.height/4.5;
function runLoop(){
    ctx.lineWidth  = 8;
    ctx.font = '20pt Verdana';
    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'white';
    ctx.textAlign = 'center';
    ctx.lineJoin = 'round';

    var text1 = document.getElementById('canvastext-top').value;
    text1 = text1.toUpperCase();


    var text2 = document.getElementById('canvastext-bottom').value;
    text2 = text2.toUpperCase();

    x = canvas.width/2;
    y = canvas.height - canvas.height/4.5;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.strokeText(text1, x, text1Y);
    ctx.fillText(text1, x, text1Y);

    ctx.strokeText(text2, x, text2Y);
    ctx.fillText(text2, x, text2Y);
     window.setTimeout(runLoop, 14);
};
runLoop();

Upvotes: 1

Vlad Zhukov
Vlad Zhukov

Reputation: 143

I think you need 1 function that draws everything which is being called on keyup.

var drawText = function() {
   ctx.lineWidth = 8;
   ctx.font = '20pt Verdana';
   ctx.strokeStyle = 'black';
   ctx.fillStyle = 'white';
   ctx.textAlign = 'center';
   ctx.lineJoin = 'round';

   ctx.clearRect(0, 0, canvas.width, canvas.height);

   var text = document.getElementById('canvastext-top').value;
   text = text.toUpperCase();
   x = canvas.width/2;
   y = canvas.height - canvas.height/1.2;            
   ctx.strokeText(text, x, y);
   ctx.fillText(text, x, y);

   var text = document.getElementById('canvastext-bottom').value;
   text = text.toUpperCase();
   x = canvas.width/2;
   y = canvas.height - canvas.height/4.5;
   ctx.strokeText(text, x, y);
   ctx.fillText(text, x, y);
}

$("#canvastext-top").keyup(function(){              
   drawText();            
});


$("#canvastext-bottom").keyup(function(){               
   drawText();            
});

Upvotes: 1

Related Questions