Second HTML5 App Update – Text Arranger 1.2
New Features
- Alpha (transparency) control.
- Shadows, with both horizontal and vertical offsets, can now be applied and adjusted.
- Color gradients, both linear and radial, can be applied to the text. Image gradients, however, are not supported.
- Canvas resizing now supported.
- Image generation, so now you can save whatever you created as an image!
The JavaScript Code
$(document).ready(function() {
// Uses Modernizr.js to check for canvas support
function canvasSupport() {
return Modernizr.canvas;
}
// Once DOM is ready, start the app
canvasApp();
function canvasApp() {
// Check for canvas support
if (!canvasSupport()) {
return;
}
// Grab the canvas and set the context to 2d
var theCanvas = $("#canvasOne");
var context = theCanvas.get(0).getContext("2d");
// Variables for text handling
var message = "";
var fillOutline = "fill"; // set default fill/outline to fill
var fontSize = "50";
var fontFace = "serif";
var fontWeight = "normal";
var fontStyle = "normal";
var textFillColor = "#000000";
var textStrokeColor = "#000000";
var textAlpha = 1; // no transparency by default
var shadowX = 1;
var shadowY = 1;
var shadowBlur = 1;
var shadowColor = "#707070";
var fillType = "colorFill";
var gradientFillColor = "#000000";
// Variables used for positioning
var textBaseline = "middle";
var textAlign = "center";
// Event listeners
$("#textBox").keyup(textBoxChanged);
$("#fillOutline").change(fillOutlineChanged);
$("#textSize").change(textSizeChanged);
$("#textFont").change(textFontChanged);
$("#fontWeight").change(fontWeightChanged);
$("#fontStyle").change(fontStyleChanged);
$("#textFillColor").change(textFillColorChanged);
$("#textStrokeColor").change(textStrokeColorChanged);
$("#textAlpha").change(textAlphaChanged);
$("#shadowColor").change(shadowColorChanged);
$("#shadowBlur").change(shadowBlurChanged);
$("#shadowX").change(shadowXChanged);
$("#shadowY").change(shadowYChanged);
$("#fillType").change(fillTypeChanged);
$("#gradientFillColor").change(gradientFillColorChanged);
$("#canvasWidth").change(canvasSizeChanged);
$("#canvasHeight").change(canvasSizeChanged);
$("#createImageData").click(createImageDataClicked);
// First screen draw
drawScreen();
// Event handler functions
function textBoxChanged(e) {
var target = e.target;
message = target.value;
drawScreen();
}
function fillOutlineChanged(e) {
var target = e.target;
fillOutline = target.value;
drawScreen();
}
function textSizeChanged(e) {
var target = e.target;
fontSize = target.value;
drawScreen();
}
function textFontChanged(e) {
var target = e.target;
fontFace = target.value;
drawScreen();
}
function fontWeightChanged(e) {
var target = e.target;
fontWeight = target.value;
drawScreen();
}
function fontStyleChanged(e) {
var target = e.target;
fontStyle = target.value;
drawScreen();
}
function textFillColorChanged(e) {
var target = e.target;
textFillColor = "#" + target.value;
drawScreen();
}
function textStrokeColorChanged(e) {
var target = e.target;
textStrokeColor = "#" + target.value;
drawScreen();
}
function textAlphaChanged(e) {
var target = e.target;
textAlpha = target.value;
drawScreen();
}
function shadowColorChanged(e) {
var target = e.target;
shadowColor = "#" + target.value;
drawScreen();
}
function shadowBlurChanged(e) {
var target = e.target;
shadowBlur = target.value;
drawScreen();
}
function shadowXChanged(e) {
var target = e.target;
shadowX = target.value;
drawScreen();
}
function shadowYChanged(e) {
var target = e.target;
shadowY = target.value;
drawScreen();
}
function fillTypeChanged(e) {
var target = e.target;
fillType = target.value;
drawScreen();
}
function gradientFillColorChanged(e) {
var target = e.target;
gradientFillColor = "#" + target.value;
drawScreen();
}
function canvasSizeChanged(e) {
var styleWidth = $("#canvasWidth").val();
var styleHeight = $("#canvasHeight").val();
//changing canvas size & resolution - no change in size ofr the drawn elements (manipulating direct html attributes - first remove the css that can get in the way)
/*
theCanvas.width('').get(0).width = styleWidth;
theCanvas.height('').get(0).height = styleHeight;
*/
//changing canvas size but not resolution (manipulating css width/height) - "zooming" at the loss of quality
theCanvas.width(styleWidth);
theCanvas.height(styleHeight);
drawScreen();
}
function createImageDataClicked(e) {
var imageData = theCanvas.get(0).toDataURL();
window.open(imageData, "canvasImage", "left=0, top=0, width=" + theCanvas.width() + ", height=" + theCanvas.height() + ", toolbar=0, resizable=0");
}
// Draws or updates the screen.
function drawScreen() {
// Canvas resets
context.globalAlpha = 1;
context.shadowColor = "#707070";
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlue = 0;
// Background
context.fillStyle = "#ffffff";
context.fillRect(0, 0, theCanvas.get(0).width, theCanvas.get(0).height); //width and height in terms of canvas resolution should be used
// Outside Border
context.strokeStyle = "#000000";
context.strokeRect(5, 5, theCanvas.get(0).width-10, theCanvas.get(0).height-10); //width and height in terms of canvas resolution should be used
// Change global alpha and shadows to whatever the user has set
context.globalAlpha = textAlpha;
context.shadowColor = shadowColor;
context.shadowOffsetX = shadowX;
context.shadowOffsetY = shadowY;
context.shadowBlur = shadowBlur;
// Text
context.font = fontWeight + " " + fontStyle + " " + fontSize + "px " + fontFace;
context.textBaseline = textBaseline;
context.textAlign = textAlign;
// Gradient handling
var metrics = context.measureText(message); // get width of the text; used for the gradients
var textWidth = metrics.width;
var tempColor;
// Variables created in order to center the text on the canvas
var metrics = context.measureText(message);
var textWidth = metrics.width;
var xPosition = (theCanvas.get(0).width/2); //width and height in terms of canvas resolution should be used
var yPosition = (theCanvas.get(0).height/2); //width and height in terms of canvas resolution should be used
// if a gradient is chosen, we add stops at 0% and 60%
if (fillType == "colorFill") {
tempColor = textFillColor;
} else if (fillType == "linearGradient") {
var gradient = context.createLinearGradient(xPosition - textWidth/2, yPosition, xPosition + textWidth/2, yPosition);
gradient.addColorStop(0.0, textFillColor);
gradient.addColorStop(0.6, gradientFillColor);
tempColor = gradient;
} else if (fillType == "radialGradient") {
var gradient = context.createRadialGradient(xPosition, yPosition, fontSize, xPosition + textWidth, yPosition, 1);
gradient.addColorStop(0.0, textFillColor);
gradient.addColorStop(0.6, gradientFillColor);
tempColor = gradient;
} else {
tempColor = textFillColor;
}
// Draw the text differently depending on fill or outline (stroke)
switch(fillOutline) {
case "fill":
context.fillStyle = tempColor;
context.fillText(message, xPosition, yPosition);
break;
case "stroke":
context.strokeStyle = textStrokeColor;
context.strokeText(message, xPosition, yPosition);
break;
case "both":
context.fillStyle = tempColor;
context.fillText(message, xPosition, yPosition);
context.strokeStyle = textStrokeColor;
context.strokeText(message, xPosition, yPosition);
break;
}
}
}
});
The Updated App
This will be the last major update to the app. I could create a website for it and make the interface more intuitive, but since this is just a personal project to work with the canvas text API, I’m not going to do that.
The updated (version 1.2) app can be found here: https://www.zesix.com/html5/textArranger1.2/

Nice, but too much independent functions.
True, but as I mention in the post, this is just a way for me to experiment with the canvas text API. I’m not intending on turning this into an app for market 🙂