Radiac's Blog: javascripthttp://radiac.net/blog/javascript/Posts tagged javascripten-gbMon, 21 Sep 2015 09:51:12 +0000A Tiny Web Font Loaderhttp://radiac.net/blog/2015/09/tiny-web-font-loader/<p>Today I'm releasing <a href="/projects/tinywfl/">TinyWFL</a>, my tiny web font loader which is about 95% smaller than other popular loaders.</p> <p>When web fonts started to gain adoption around 2010, the problem people had was <a href="http://www.paulirish.com/2009/fighting-the-font-face-fout/">FOUT</a> - the flash of unstyled text while you waited for the browser to download the font. I think most people would agree that this has since been solved very comprehensively by <a href="https://github.com/typekit/webfontloader">webfontloader</a> from Google and Typekit, and that it's now the de-facto standard loader - but back in 2010 or 2011 FOUT was still an issue, which is why I wrote my own.</p> <p>To be accurate, my loader doesn't actually load anything - it's more of a anti-FOUT aid. The idea behind avoiding FOUT is simple enough: characters are very rarely exactly the same size in different fonts, so if we put a few of them together in an HTML element and then measure its width we should get different values depending on which font it's using. If we measure the width for a font we know they'll have (ie a default font like <code>serif</code>), we can then compare that to the width of the web font we want to use; if they match, the web font hasn't loaded, so we use <code>setTimeout</code> to wait a bit, then we check again. Once we know they're loaded we can either fire off JavaScript functions, or set a CSS class somewhere which can be used by CSS rules to only show the font once it has loaded.</p> <p>This weekend I wanted to add a 2KB reduced character set font to a site, and thought about replacing my 5 year old code with webfontloader - but that's when I looked at the file sizes. The minified version of webfontloader that's currently on their git master is 11.5KB, and the version on Google's CDN is 16.6KB. Of course those sizes aren't huge, but a loader here and a polyfill there is how you end up with big slow pages. Besides, it seems silly to use a library that is 8x larger than the font it's trying to help show - at best it'll still be 50-100% of your average web font.</p> <p>By comparison TinyWFL is just 852 bytes. The reason it manages such a big difference is that it leaves out a bunch of features you won't need in most circumstances - and if you do need them, we've already got webfontloader.</p> <p>You can find <a href="https://github.com/radiac/tinywfl">TinyWFL on github</a></p> <p>As a reward for reading this far, have a couple of useful web font-related links:</p> <ul> <li><a href="http://www.fontsquirrel.com/tools/webfont-generator">Font Squirrel web font generator</a> - upload a font and they'll generate an excellent optimised web font for you to use with TinyWFL.</li> <li><a href="https://icomoon.io/app">IcoMoon app</a> - upload vector images (or pick from their selection) to generate an icon font. It probably doesn't make much sense to use TinyWFL for icon fonts, but it's still a great service.</li> </ul>Mon, 21 Sep 2015 09:51:12 +0000http://radiac.net/blog/2015/09/tiny-web-font-loader/Canvas bezier curveshttp://radiac.net/blog/2013/12/canvas-bezier-curves/<p>The new Christmas design for this site uses bezier curves on canvas elements to generate random snowdrifts behind the header. Drawing a <a href="http://en.wikipedia.org/wiki/B%C3%A9zier_curve">bezier curve</a> is pretty simple, so seems like a reasonable place to start my new blog. First you need a canvas and a context:</p> <pre><code class="language-html">&lt;canvas id=&quot;myCanvas&quot; width=&quot;400&quot; height="200"&gt;&lt;/canvas&gt; &lt;script&gt; var canvas = document.getElementById('myCanvas'), context = canvas.getContext("2d"); ; &lt;/script&gt; </code></pre> <aside class="code"> <h1>Think Turtles</h1> <p>A quick aside for those who haven't used the canvas before: a canvas element has a context property, which is what you draw on. Context methods to draw lines take destination coordinates, and draw them from the current position - think of <em>pen up</em> in Logo's <a href="http://en.wikipedia.org/wiki/Turtle_graphics">turtle graphics</a>, only with absolute positioning.</p> <p>The canvas equivalent of <em>pen up</em> is <code>context.moveTo(x, y)</code>, so to draw a line from <code>(50, 50)</code> to <code>(150, 50)</code>, you would say:</p> <pre><code class="language-js">context.beginPath(); context.moveTo(50, 50); context.lineTo(150, 50); c.strokeStyle = '#000'; c.stroke(); </code></pre> <p>You'll notice I added some extra bits there - <code>beginPath()</code> says we're starting a new path, and <code>stroke()</code> draws it using the current style. Call <code>beginPath()</code> whenever you're about to change the style.</p> </aside> <p>The canvas bezier curve takes 6 arguments; two sets of control points, and an end point:</p> <pre><code class="language-js">context.bezierCurveTo(c1x, c1y, c2x, c2y, ex, ey); </code></pre> <p>Here's an example:</p> <pre><code class="language-js">context.beginPath(); context.moveTo(50, 50); context.bezierCurveTo(50, 150, 250, 150, 350, 50); context.strokeStyle = '#00d'; context.stroke(); </code></pre> <canvas id="bezier-eg" width="400" height="200"></canvas> <script> $(function () { var c = $('#bezier-eg')[0].getContext("2d"), d = 3 ; // Guides function cross(x, y) { c.beginPath(); c.moveTo(x-d, y-d); c.lineTo(x+d, y+d); c.moveTo(x-d, y+d); c.lineTo(x+d, y-d); c.strokeStyle = '#d00'; c.stroke(); } c.beginPath(); c.moveTo(50, 50); c.lineTo(50, 150); c.moveTo(350, 50); c.lineTo(250, 150); c.strokeStyle = '#bbb'; c.stroke(); // The bezier line itself c.beginPath(); c.moveTo(50, 50); c.bezierCurveTo(50, 150, 250, 150, 350, 50); c.strokeStyle = '#00d'; c.stroke(); // Markers c.font="10px Arial"; cross(50, 50); c.fillText("(50, 50)", 35, 35); cross(350, 50); c.fillText("(350, 50)", 335, 35); cross(50, 150); c.fillText("(50, 150)", 35, 165); cross(250, 150); c.fillText("(250, 150)", 235, 165); }); </script> <p>I've added some grey lines and red markers to show what's going on. First we <code>moveTo(50, 50)</code>, then call <code>bezierCurveTo</code> with the two control points <code>(50, 150)</code> and <code>(250, 150)</code>, and the end point <code>(350, 50)</code>. The result is a line from the current position to the end point, pulled out of place by the control points.</p> <p>Once you've got that far, building a randomly-generated snowdrift is trivial - a bit of <code>Math.random()</code>, and instead of <code>context.stroke()</code> use <code>context.fillStyle</code> and <code>context.fill()</code>.</p> <p>To finish the effect, I'm drawing two background snowdrifts on one canvas element, and a foreground snowdrift on a second, with snowflakes falling in between - although I cheated there and used an animated gif which I had rendered earlier. Your CPU thanks me.</p>Mon, 09 Dec 2013 11:42:11 +0000http://radiac.net/blog/2013/12/canvas-bezier-curves/TCMI 2.0http://radiac.net/blog/2013/12/tcmi-20/<p>I am very proud to announce my finest work to date - the Tacky Christmas Music Interface 2.0!</p> <p>The old TCMI played midi files, but most browsers seem to struggle with those these days, and even when it did work, modern soundfonts made the experience quite variable. To get around this, the new version of TCMI now uses HTML5 audio to play MP3 or OGG files (depending on browser support).</p> <p>This also means that if you've got the relevant PPL/PRS license, you can now play non-tacky music to your visitors! Although I'm not quite sure what the point of that would be.</p> <p>The old version also ran in an iframe, which made front page SEO and deep-linking difficult for 1/12th of the year. This version therefore has the option to use AJAX loads and <code>history.pushState</code>, with the controls in a styleable <code>&lt;div&gt;</code> overlay.</p> <p>There's also a new cleaner design, but those who want a tacky UI to go with the tacky music can opt to use the classic design.</p> <p>You can find out more on the <a href="/projects/tcmi/">TCMI project page</a>, where you can also download some of the old TCMI midis which I've converted into MP3s and OGGs. Improvements welcome on <a href="https://github.com/radiac/tcmi">github</a>.</p>Tue, 03 Dec 2013 13:19:05 +0000http://radiac.net/blog/2013/12/tcmi-20/