I'm currently using HTML5's canvas to render a number of strings using the fillText method. This works fine, but I'd also like to give each string a 1px black outer stroke. Unfortunately the strokeText function seems to apply an inner stroke. To counter this, I've written a drawStrokedText function that achieves the effect I'm after. Unfortunately it's horrible slow (for obvious reasons).
Is there a fast, cross-browser way of achieving a 1px outer stroke using native canvas functionality?
drawStrokedText = function(context, text, x, y)
{
context.fillStyle = "rgb(0,0,0)";
context.fillText(text, x-1, y-1);
context.fillText(text, x+1, y-1);
context.fillText(text, x-1, y);
context.fillText(text, x+1, y);
context.fillText(text, x-1, y+1);
context.fillText(text, x+1, y+1);
context.fillStyle = "rgb(255,255,255)";
context.fillText(text, x, y);
};
Here's an example of the effect at work:
Simon's answer is a good solution, yet it may have mitering glitches in some cases, especially with capital 'M', 'V', & 'W':
http://jsfiddle.net/hwG42/1/
In this case, it's best to utilize:
http://jsfiddle.net/hwG42/3/
Best of luck!
For a smooth shadow you can try this
The above answers are great, using some of these solutions* and some of my own ideas, I made a quick reference and some creative alternatives in the below fiddle.
*All credits given where due in the fiddle code
https://jsfiddle.net/vtmnyea8/
Output of the fiddle:
What it supports:
Some performance metrics:
Considering using this in a game or at high frame rates? Check out this jsperf using the above methods.
https://jsperf.com/various-text-effects-html5-2d-context
What's wrong with stroke? Since half the stroke will be outside of the shape, you can always draw the stroke first with a line width of double what you want. So if you wanted a 4px outer stroke you could do:
Which makes:
live fiddle here: http://jsfiddle.net/vNWn6/
IF that happens to not look as accurate at smaller text rendering scales, you can always draw it large but scale it down (in the above case you'd do
ctx.scale(0.25, 0.25)
)