Thursday, February 28, 2013

Preloading web fonts for use with html CANVAS

The problem:
Your application makes use of html <canvas> to draw some text to a canvas element when the page loads. You've picked out a cool web font to use but find that it isn't loading in time to be drawn onto the canvas. Unlike DOM elements that automatically update to the correct font when it becomes available ( FOUT ), the canvas is simply drawn with the incorrect font.  Refreshing the canvas or page will probably display the correct font because it has finished loading or has been cached.

There are several creative ways around this. The following one has not been extensively tested but is something I want to experiment with in the future.

I found that while using @font-face to declare fonts in CSS, there was no way to know when the resources requested ( font files ) were loaded. The 'onload' will fire because all of the scripts and stylesheets have loaded, but the files the stylesheets requested could still be in transit.

By embedding the font files in the CSS by base64-encoding them, I was able to verify that the stylesheet ( including the font ) was loaded when the onload event happens. Run this within the <head> tags.

        var fileref = document.createElement("link");
        fileref.setAttribute("rel", "stylesheet");
        fileref.setAttribute("type", "text/css");
        fileref.setAttribute("href", "PATH_TO_CSS_FILE");
        document.getElementsByTagName("head")[0].appendChild(fileref);

Here are some considerations:
This approach will increase the size of your font by 30-40%, but will spare a round trip to the server to fetch additional font files.
This will prevent the page from loading until your whole CSS/font file is loaded. This could be unacceptably long if using a large font, multiple fonts, or browsing on a mobile device.

Now here is something I'm working on that is very untested and crazy:

        var filename = "cssGen.php?font="+fontFile;
        var fileref = document.createElement("link");
        fileref.setAttribute("rel", "stylesheet");
        fileref.setAttribute("type", "text/css");
        fileref.setAttribute("href", filename);
        document.getElementsByTagName("head")[0].appendChild(fileref);

In this case the CSS file being added is actually a PHP script posing as CSS.  The name of the font file is passed into the css/php using the 'font' query parameter.  Then inside the css/php script:

***
<?php
    header("Content-type: text/css; charset: UTF-8");
   
    $font = explode(".",$_GET['font']);
    $fontData = file_get_contents("fonts/".$_GET['font']);
    $encoded = base64_encode($fontData);
?>
@font-face {
    font-family: '<?php print $font[0]; ?>';
    src: url(data:application/x-font-woff;charset=utf-8;base64,<?php print $encoded; ?>) format('woff');
    font-weight: normal;
    font-style: normal;
}

#myCanvas {
    border: 1px dashed #999;
}

body {
    font-family: '<?php print $font[0]; ?>';
}

***
The headers are set so the file is interpreted as text/css. The name of the font family is derived from the filename and the font file is base64 encoded on the fly.
Again, not tested much, but fun to play around with.  I thought the whole idea of executing php inside CSS was worth trying anyway.

Wednesday, February 20, 2013

Check a hex color code using a regular expression

This handy function uses a regular expression to check for a valid 6 or 3-digit hex code beginning with #.

function hexCheck (hex) {
    var re = /^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/;
    return re.test(hex); // returns true if this is a valid hex code
}

This can and should be elaborated into another method for regularizing hex codes. ( Adding #, etc )

Wednesday, February 13, 2013

PHP Control Structure Syntax

This syntax is particularly useful when writing template files. In a template, you may or may not be receiving a piece of data from your CMS, and have to adjust accordingly. If the content isn't there, you'll want to make sure that an ugly error message won't appear and that the template handles the omission gracefully.

The basic concept:
<?php (conditional php statement) : ?>
   <p>some html content</p>
<?php endConditional; ?>


In the example above the HTML markup will only be output to the browser if the conditional statement resolves to true. Below we'll check that the $data has a valid value ( not equal to "" ), before printing it to the screen.

<?php if($data->user != "") : ?>
   <p>Welcome, <?php print $data->user; ?>!</p>
<?php endif; ?>

If all goes well, the result will be:  Welcome, User!
If not, nothing is output.