One of the great recent additions to modern browsers is the
<canvas> element. The
However, a popular misconception1 exists with the
<canvas> graphics are not vector graphics, they’re raster. What does this mean? It means if you’re viewing your beautiful
<canvas> artwork on a device that supports zooming, once you zoom past 100%, your artwork will get pixelated.
So, how do we solve this? As it so happens, this issue was solved several years ago before these zoomable devices were even on the market by none other than the Webkit team:
The img element already supports specifying explicit sizes, and so today you can specify a width and height and if an image is larger it will be downscaled. In a high DPI system where 1 CSS pixel != 1 device pixel, more detail can then be rendered.
In other words how you scale an image is based off comparing device pixels and not CSS pixels. For example, if you have a zoom factor of 2, an img tag that specifies a width and height of 100 CSS pixels, and an image whose intrinsic size is 200×200 device pixels, then that image is not scaled, since 100×2 = 200. However on a lower DPI display that might not have any zoom factor set, the 200×200 image would be properly downscaled to 100×100.
The basic strategy here is two-fold. First, we provide a graphic whose dimensions are greater than the dimension we intend on displaying them at. This means if we want to display a 50x50 pixel image we use a 100x100 or 200x200 pixel image instead. Then, we resize our nice large image back down to 50x50 pixels (using either CSS or the width and height attributes). The net effect here is that when you zoom in on your image, the High DPI display will show all that extra pixel information, while normal displays will be none the wiser.
What does this
<img> magic have to do with our friendly
<canvas> element? As it so happens, we can apply this same exact strategy. If we draw out our
<canvas> larger than we need it to be, then resize it back down, we get nice, crisp artwork even when you right up in its grill. So instead of drawing your 50x50 pixel canvas artwork at 50x50 pixels, try drawing a 100x100 pixel (200x200, 800x800, whatever you please)
<canvas> element and then shrinking it back down to 50x50 pixels in CSS.
You can actually see this at work in the Vimeo video player:
Not so Awesome:
What’s really great about using this technique with the
<canvas> element versus simply linking to a larger image within the
<img> tag is that since graphics are being drawn client-side you’re not loading extra bytes over the network that are potentially 2-4 times larger than you really need2.
I think some of the confusion stems from how the word vector is used in relation to
<canvas>API is “vector” in the mathematical/physical sense, meaning a line is drawn by defining a direction, and a magnitude. It is not vector in the sense that the graphics are re-drawn each time the view updates (ie. when you zoom in). Once
<canvas>graphics are drawn, they exists as rasterized pixels and cannot be manipulated as separate objects, unlike SVG. ↩
Ah yes, there’s always a footnote next to a sentence saying there’s no downside. While it’s true you’re not loading in extra-large artwork, saving you the cost of transferring that over the network, you still are drawing 2-4 times as many pixels on the screen. This can potentially have an effect on drawing speed, memory usage, and animation performance. So just be aware of these caveats and test often. ↩
Over the past few weeks I’ve taken it upon myself to learn Python. Learning a new programming language is fun and all, but it requires a ton of work and a ton of research. All of this research has left me with a lot of open tabs and windows that look a bit like this:
Or if you’re a crazy Chrome user, like this:
Finding a specific tab in that mess is no fun, especially when you have multiple tabs open from the same site, leaving all your tabs looking the exact same, starting with the same words. I thought there must be a better way to handle this when it occurred to me that the same problem exists on your operating system when looking for Apps, and OS makers have come up with some great solutions.
Since this solution is so natural and intuitive, I thought it would be a perfect fit to apply the same idea to searching your browser tabs and windows, and Snipe is the product of that:
To bring up Snipe, you simply press Ctrl + Alt + Space 1 on any open tab2, and up pops the input field. Begin typing and, automagically, results from your open tabs (in any window!) start appearing. Use your keyboard to select which tab you’d like, and Snipe will switch you to that tab and get out of your way. Snipe searches both the title and the url of your tabs, so fear not if you’re looking for your Facebook tab but don’t remember what page it’s on. Also, searching is “fuzzy”, meaning you don’t have to get the content exactly right to get a result, and the results are smartly sorted by which one Snipe thinks is the most relevant based on your key words.
I’ve shared this extension with some people around the office and they really seem to like it. I know I’ve found myself using it constantly throughout the day, so I’m excited to see if other people find Snipe as useful as I do. Check out the download links below to install the extension (Chrome and Safari only) and, like all the projects I post on Reusable Bits, Snipe is also available for you to fork on Github to make your own additions and contributions. I’d love to hear about any feature ideas you have on the extension (there’s already a couple ideas I have in a todo on the Github page) so feel free to leave any brainstorms in the comments.
For Chrome users of Snipe, you have a couple other options as well. Snipe will work as a popup window with the regular Ctrl + Alt + Space shortcut, but it also shows up as a button in your toolbar and clicking that button will invoke the Snipe UI. Also, for the super-savy Chrome users, you can take advantage of Chrome’s Omnibox. Simple type “tabs” into the Omnibox and then hit the TAB key, and begin searching for your tabs as normal. You’ll see your Snipe results show up built right in to Chrome. ↩
After you first install the extension you’ll have to either refresh all of your open tabs or restart your browser to get the keyboard shortcut to work. Sorry, but I don’t think there’s a way around this! ↩
A couple of weeks ago I released a cool little utility called Clamp.js that helps with clamping (ie. adding ellipsis to) long pieces of html text. I was pretty excited about its release, though I stated that one downside was that performance improvements could be made on it since it loops character-by-character through a piece of text, checking to see if it fits each time.
After some really constructive conversations with people on twitter and on this blog, I made some updates to how Clamp.js loops through text looking for a good fit. However, before I go into that, it’s probably constructive to visualize how Clamp.js used to work.