Time for action – adding a text tool

Let's start by adding a new item to the Tool drop-down menu for the text tool:

<li data-value="text">Text</li>

Next, we'll add a drawText() method to the Canvas2D object. It will take the text to draw, a point from where to draw the text, and a Boolean value indicating whether to fill the text or just outline it. If fill is true, it uses fillText() to draw the text, otherwise it uses strokeText():

this.drawText = function(text, point, fill)
{
    if (fill)
    {
        context.fillText(text, point.x, point.y);
    }
    else
    {
        context.strokeText(text, point.x, point.y);
    }
};

Now we need a way to allow the user to enter the text that he/she wants to draw. We will need a text input field that we will keep hidden until the user wants to add some text. When the user selects the text tool and clicks on the canvas, we will position the text field where he/she clicked on and wait for him/her to enter the text. When the user presses the Enter key, we will hide the text field and draw the text to the canvas.

To make it seem like the user is typing on the canvas, we need to set a couple more properties in the canvas context for the font. We will set the font and textBaseline properties in the constructor. The baseline tells the context where to draw the text relative to the position. We will set it to "top" so it will draw the top of the text at the y position, which is the same place our text field will be. Other common baseline values are "bottom" and "middle":

context.font = "24px Verdana, Geneva, sans-serif";
context.textBaseline = "top";

Now we need a text field for the user to enter text. Let's add it to the bottom of our HTML file, after the footer element:

<div id="text-input">
    <input type="text" />
</div>

Next let's go into our CSS and define the style for the text-input element. We will set display to none, so that it is hidden, and set position to absolute, so that we can position it wherever we want to on the page. We will also change the size of the font to 24 pixels because that's what we set for our font size in the context:

#text-input
{
    display: none;
    position: absolute;
    width: 8em; 
}
#text-input>input
{
    font-size: 24px;
}

Now let's add some JavaScript code to the penDown() method in CanvasPadApp so that when the user clicks the mouse it shows the text input field:

function penDown(pageX, pageY)
{
    if (curTool == "text")
    {
        // Check if it's already visible
        if ($("#text-input").is(":visible")) return;
        showTextInput(pageX, pageY);
    }
    else
    {
        drawing = true;
    }

    // code not shown...
}

First it checks the current tool. If it is the text tool, it checks to see if the text field is already visible and if so, there's no need to continue. Otherwise it calls showTextInput() passing in the mouse coordinates. Notice that we don't set drawing to true in this case because we don't need to track the mouse.

The showTextInput() method takes the mouse coordinates and moves the text-input element to the point where the user clicked the mouse on the canvas:

function showTextInput(pageX, pageY)
{
    $("#text-input").css("top", pageY)
                    .css("left", pageX)
                    .fadeIn("fast");
    $("#text-input input").val("").focus();
}

First we set the top and left CSS properties to move the element over to where the user clicked on and then fade it in. Then it resets the value of the text field and sets the focus on it so the user can start typing. This will make it appear that the user is typing on the canvas.

When the user is done typing, he/she can press the Enter key to finish the text. We need to add a keydown event handler to the text field to check for this. We will add that in the start() method:

$("#text-input input").keydown(function(e) { 
    checkTextInput(e.which);
});

The handler calls checkTextInput(), passing in the key code of the key that was pressed. The key code is found in the which field of the event object:

function checkTextInput(key)
{
    if (key == 13) // Enter key
    {
        curAction.text =  $("#text-input input").val();
        $("#text-input").hide();
        redraw();
    }
    else if (key == 27) // Escape
    {
        actions.pop();
        $("#text-input").hide();
    }
}

The checkTextInput() method looks at the key code to see what to do. If the user pressed the Enter key, which is key code 13, it will set the text into the current action object, hide the text input, and then call redraw(). If the key code is 27, which is the Escape key,it will cancel the text by removing the action and then hiding the text input.

The final piece to implement is the change to redraw(). We need to add the text action to our switch statement. It passes in the text, the position to draw it, and whether to fill it or not:

switch (action.tool)
{
    // code not shown...
    case "text":
        canvas2d.drawText(action.text, action.points[0],
            action.fill);
        break;
}

What just happened?

We added a Text tool to our application that allows the user to type text on the canvas and draw it filled or outlined.

Have a go hero

Try adding a toolbar menu for the user to select different font sizes. You will need to change the font size in the canvas context as well as the text input field's style.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.252.140