Thursday, December 29, 2011

osx vs windows redux

Ranting on obscure blogs is a bit like tossing nickels into the Grand Canyon, but... hey, a nickel!

I sometimes jump the gun in criticizing Apple and OSX. Too often that comes from inexperience with OSX. In many cases, a serious criticism of "you can't do this on a Mac" (for example, easily copying the path information from an open Finder window into a "Save As" dialog) runs head on into a "Mac just does it a different way, you Windows-muddled fool" (you can drag the little folder icon on top of the Finder window!) and gets diluted into vaguer criticisms about "UI emphasis" and "potential confusion" (the way that drag and dropping that icon feels too much like a file system manipulation... and darn it, using string-based paths is sensible, if a bit nerdy.)

So once more into the breach...

One thing holding me back from switching to OSX for my work machine is a feeling that the keyboard support isn't up to snuff... specifically on Windows, nearly every text editor I use maps ctrl-left arrow and ctrl-right arrow to jumping words. Now there is some inconsistency to it: some editors think an underscore is a word break, others don't, some jump to the start of the next word immediately, others jump to the end of the current word first. But at least the standard is there, and I don't have to interrupt my typing flow with mouse movements, or play "press and hold the arrow key 'til the cursor finally gets there".

I thought this problem sprung from Apple's pro-mouse, anti-keyboard stance. The original Mac keyboard didn't even have arrow keys! See for yourself:

But of course, I was wrong. I was expecting that all the keys I was looking for would be mapped to cmd-, which is (roughly) the Mac equivalent of "ctrl". On OSX however, the cmd-arrow keys jump either to the beginning/end of the line (left and right) or of the whole document (up and down). However, The "option" key WAS mapped to what I wanted, with the left and right jumping of words.

Arguably, Mac's use of these keys is more efficient and logical than the PC standards. There's an intuitive hook to how cmd-left/right goes to line endings, and cmd-up/down means the whole document. These keys can then play the role of home/end on PCs: home/end = line, ctrl-home,/ctrl-end=whole document. Furthermore home/end are two of the most wandering keys on laptop and compact PC keyboards, there has been no definitive consensus on where they should go, and sometimes they are mapped to special, laptop only "fn-" keys. So points to Apple for battening down the hatches on that.

So I was wrong. Mostly. But can I say Mac has too many of the wrong kind of keys? Look at this:

 "fn" "control" "option" and "command"! 4 different keys that mean roughly the same thing, "make the other key I'm pressing do something else". To make things worse, the little used key "fn" gets the most prime real estate-- the place where Fitt's Law implies the most important key should go. (To be fair, IBM/Lenovo Thinkpads make the same mistake, and it's even worse because a PC's ctrl key is much more important than the Mac's.)

Here's the same image from a typical Windows keyboard:

It's the same number of keys, but I think handled much more gracefully, with better differentiation. "ctrl" and "alt" are far away from each other. Plus in Windows, there's a stronger convention for when which is used: ctrl- combinations tend to be "do something now": copy, paste, save, new, etc. Alt- combinations are mostly used to pull down menus. (Windows used to have greater discoverability of that feature by underlining the accelerator letter on the menubar, e.g. File and Edit, but now (by default) those underlines are hidden until the user holds the alt key.)

The windows-key is special, in most sense of the word: usually it means a quick hop to the start menu (and I love the way they put the cursor in a search box there... windows-key,"program name fragment", return is a very quick way to start a program that is not frequently used enough to merit a pin on the task bar.) The Windows key also has a few obscure key combos that are all OS-wide, like win-m or win-d for hiding all windows and showing the desktop. (Though weirdly, win-d is reversible by hitting again, and the older win-m is not.)

(And it still seems odd to me that Microsoft managed to get their logo on all that hardware by all those manufacturers...)

So wrapping up my arrow key rant, Mac feels a bit klutzy to me, and it's awkward to use and annoying to remember the distinction between "command" and "option" when going back and highlighting and copy words that I just typed. To make the whole scene worse, why isn't the Option (formerly Closed Apple Key) labeled with its icon,  ?(And what kind of symbol is that anyway? To be fair I guess the Option Key has its uses, like for typing letters with accents and the like, but still there are aspects to it that seem half-baked.

Rant over! I'm still on the fence about making the "switch" (and in part because I worry about Apple being such a dominant monoculture of computing) but thinking about the UI/interface it provides makes the potential transition easier for me.

Thursday, December 22, 2011

bonus: fireworks cheatsheet notes

So the designers at my work use a lot of Adobe Fireworks. It's a cool program. Its raw format is .png, but a cranked up .png that holds lots of stuff like layers, alpha transparency, and even vector information. For enginerds like me who tend to think in terms of pixels only (and maybe diving into crazy complexities like "layers") it's a lot to wrap our heads around... and watching a skilled artisan use it, and its ability to treat text and lines and pieces part as objects, even when they're not explicitly set on a different layer... it's eye-opening.

So, as notes to my future self, I thought I'd write out just what I had to go through to make up the basic white-rectangle-with-drop-shadow images... in particular, how to use Fireworks to slice it into the top,middle, and bottom the final example used.

Here are those notes:


  • make a new image: ctrl-n, 500x500...
  • On toolbar stroke would be null (red line X, fill to white...), fill would be white
  • on the toolbar under vector, make the shape tool do rectangles not ellipse tool
  • draw the shape then handfix the W and H under Properties at the bottom (mostly the width)
  • Under Properties|Filters, Shadow and Glow | Drop Shadow
  • This pulls up some Filter properties. (By default the dropshadow is to the Southeast)
    • so Filters is a list of effects added to this selection, you have to be careful not to make extra ones...
    • the arrows is distance, how far away the center of the shadow is from the center of the item... I want this at zero, centered, not off to one side
      • (which means I can ignore the angle for which direction it should go)
    • I set the fuzziness bigger than 4, like 10 or so
    • you don't see changes applied 'til you close the filter mini-properties box
  • Make sure the canvas itself has the null background selected (indicated with the red line) and you can see the gray and white boxes
  • Here I could select the rectangle with the selection tool, ctrl-c copy, ctrl-n (which autodefaults to the size of the thing in the clipboard), paste, then save. But of course I wanted my 3 slices...
  • now we need to use the slicing tool. You draw bounding boxes (including the dropshadow) and rely on the AI thing to find the right edges for you... I draw one for the top, bottom, and middle. At my first attempt I tried to close-crop the top and bottom without interior padding, but that messed up the shading of the corners, and I had to redo it.
  • Then I go to Export... the settings are QUITE a bit fiddly, what the helpful designer helped me figure out I wanted was "Export:Images Only" "HTML: [None]" "Slices:Export Slices" "Pages:Curent Pages" and "Include Areas without Slices" left unchecked
And that was it!

Sometimes I dispair of ever deeply learning Adobe stuff. It seems like such a different, non-engineery, don't-try-to-understand-everything-we're-doing / intuitive system... or maybe the designers are just more used to. (GIMP. in contrast, is pure-Engineer, we-don't-give-you-any-convenient-defaults, no matter how logical it might be.)

ie dropshadows with scale9grid... or not

(This is another one of those "see how the sausages get made", tales-from-the trenches post, vs a bright shining tale of victory and Zenlike CSS perfection.)

So, dropshadows. Designers love'em! And why not, they bring an illusion of depth to the page and help set things apart. But man, they are a pain the butt to code sometimes... at least they are if you want to support IE. (I guess IE9 is starting to support this as well.)

First, a note: the drop shadows I'm aiming for are kind of a fuzzy border all around the div, vs the kind hanging out on one corner (usually the lower-right.)

Anyway, the CSS is still in that funky "each browser uses a prefix" state, so the code is like this:

    box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.80);
    -moz-box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.80);
    -webkit-box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.80);
Not too bad, the result is like:


Hi there!

But of course that does nothing for IE <= 8. I fiddled around with some of IE's filters,

filter:progid:DXImageTransform.Microsoft.dropshadow(OffX=0, OffY=0, Color='gray', Positive='true');
filter: progid:DXImageTransform.Microsoft.Shadow(color='#969696', Direction=135, Strength=3);
but nothing was coming out right, either it made everyting blurry, or it was an old Win3.11 looking flat gray background, or the content of the div was rendering weirdly non-anti-aliased... we ended up going with a variation of this, and for a while letting IE users just hang with a thing gray 1px border.

But I remembered this past spring when one of my co-UI guys was really excited about a plugin called scale9grid. It's a pretty sweet of styling a div (as long as you don't mind depending on javascript and non-semantic CSS and images to do so) that can be any width or height, based on using an image as a  model for the borders (an image that presumably has a flat-colored center section where the content actually goes.) So you can have arbitrarily weird corners and sides and this plugin takes care off all the busy work.

So in Fireworks (more on that in a bit) I styled up a nice alpha-channel (transparency) preserving PNG that is shadowboxer.png:

This can be used to make a box of any size. The code for this is pretty simple, in the CSS you need to set the background-image (something the page is a little slow to mention), the dimensions (I think), and some padding, so that your content isn't over the shadow itself:


  background-image:url("/shadowboxer.png");
  padding:12px;

Then in jQuery, probably in the $(document).ready() you tell it how much of the sides of the original image you want to respect and use as the border:
$('#element_id').scale9Grid({top:12,bottom:12,left:12,right:12});

Hi there again!

So, that's kinda nice. The trouble is, the panel we wanted it for was all animated. The width was fixed but the height was changing, and that goes beyond what scale9grid was designed for. It didn't change when the child content did, and you couldn't just reapply once the animation was done.

So to let IE users back in on the fun, I decided to go with the old, slightly-gruesome, tried-and-mostly-true technique for fixed width things with funky borders: a special graphic-only div on top, the main content div with a repeating background, and a graphic-only div on the bottom. Sigh.

The images I made up in Fireworks, and most of the other external files for this blog entry, are at https://kirk.is/m/files/kirkdev/shadowbox/. I imaginatively called them "top" "mid" and "bot", and they can be used like this:


Are we having fun yet?
The CSS then is something like:


.top_box{
  width:398px;
  height:14px;
  background-image:url("top.png");
}
.mid_box{
  width:398px;
  height:218px;
  padding:10px;
  background-image:url("mid.png");
  background-repeat:repeat-y;
}
.bot_box{
  width:398px;
  height:13px;
  background-image:url("bot.png");
}


What can I say, it works, and animates fine. One irritation was I first tried to cut the top and the bottom with no interior white padding, but that messed up the fading on the corners.

It's depressing to get back to such a mundane solution, but at least I've reawakened my awareness of the potential of scale9grid, one more weapon in my UI Engineer arsenal.

Thursday, December 15, 2011

image magick and text macros

After developing professionally for 15 years, I can appreciate when it's time to apply a quick and dirty solution.

Sometimes it's my only option, a way of covering gaps in my knowledge-- for instance, I've never really had the chance to learn any Adobe product deeply, whether it's Flash, Photoshop, or Fireworks. And I've stuck with my manipulating tab-delimited files in Perl where more normal people might cozy up to Excel.

So at http://alleyoop.com/ we had a widget that would display sample math problems for various subtopics. Each image was a 380x136 png, but most had plenty of whitespace:
We decided we didn't want to so much whitespace... but ideally we wouldn't have to have a design person resize all 204 images. What to do?

Enter ImageMagick. This software has been around for a long while I think. A while back I used its Perl module as part of my image upload feature for my personal blog, so I could crop out extra white space on doodles and resize images to be more web-friendly on the server, rather than doing it locally and then reloading. And there's a handy Windows client.

The syntax is a little strange, but for trimming the file "Volume.png" I'd just do
convert Volume.png -trim Volume.png
I chose the same file name for the output as the input (Weirdly, if I didn't specify the destination filename it would give me a file name "-trim".)

So far, so good. But what' the easiest way to apply this command to all 204 files?

I'm on Windows, and haven't bothered with CygWin, so I've learned a few coping tricks... like "dir /b" gives you a "bare" directory listing of just the filenames. I run the following command:
dir /b *.png > trim.bat
So now I have trim.bat, a flat file of filenames. Then I pull up trim.bat in an editor* and ran a macro that:
  • home to to the start of the line and started the macro recording
  • shift-select to the end of the line
  • ctrl-x to cut the filename
  • type 'convert "'
  • ctrl-v to paste the filename
  • type '" -trim "'
  • ctrl-v to paste the filename
  • type '"'
  • down arrow to the next line, then home to jump to the start of it
  • end macro
Then just hold down the macro replay key, and BAM, I have my ready to run batch file. Run it and my job here is done. (Macros are great, super fast to make with almost nothing to learn, just sometimes you have to think about the general case of what you're trying to do. Every developer should intimately know at least one editor with one button macro playback as well as a small set of text manipulation tools, like either Perl or awk and sed.)

* on editors... lately I've been using Komodo Edit, despite its surprisingly long loading times. I kept my ancient copy of TextPad handy though, in part because its macro recording and playback was rock-solid and I sometimes had issues in Komodo Edit. But now it looks like Notepad++ is what the cool kids are using, at least the ones not "cool" enough for developing on Mac. Can I say though, that given most Mac laptop's half-assed keyboard support (the lack of equivalents, or at least general obscurity, of simple keystrokes for Home, End, and ctrl-arrow to jump words) that I find this kind of thing much easier to do on Windows, and it's yet another reason I'm unlikely to switch, at least for my work stuff...



Monday, December 12, 2011

animation nation part 2: introduction to raphael.js

So the other day I was talking about making an animation for my company's registration process.

I quickly put together an animation proof-of-concept in ProcessingJS. I didn't go too far with it in part because IE is still in our target browsers, and ProcessingJS relies on the canvas object, so we couldn't use the result on the site.

My thoughts turned to RaphaĆ«l in part because I knew it would work with IE. Superficially, Raphael is very similar to canvas-based APIs (in fact I thought it used a "shim" to let older versions of IE do canvas things) but really it's profoundly different... rather than a canvas of pixels, Raphael deals with SVG (Scalable Vector Graphics) vector objects. These objects are great because they deal with twisty lines and curves rather than squares, and you can scale them to any size without them getting pixel-y.

Vector graphics require a different mindset than "regular". Specifically, Raphael is object oriented and once you've created your "paper" you add shapes and lines to it. Those shapes and lines then have attributes, similar to CSS attributes, that you can modify. The examples on the Raphael homepage are impressive, and it's easy to make juicy effects, especially in terms of bouncy scaling and rotation.

I wasn't crazy about the homepage's boilerplate for two reasons: one is I prefer something I can copy and paste into a blank document and hit the ground running. Here's some code that let me do that (once I pulled down a local copy of raphael-min.js)
<head>
<script src="raphael-min.js"></script>
<script>
window.onload = function(){
  var paper = Raphael("thepaper", 320, 200);
  var circle = paper.circle(50, 40, 10);
  circle.attr("fill", "#f00");
  circle.attr("stroke", "#fff");
}
</script>
<body>
<div id="thepaper"></div>
</body>

The second improvement I made was to use a name div as a canvas, rather than ask Raphael to provide the div and position it absolutely... I think it's more common that people will be embedding a bit of Raphael in a larger webpage, so an id'd div seems the way to go for that. However, that meant I couldn't let Raphael just run as commands directly in the script tags, I had to wrap it as a window.onload function (obviously, $(document).ready(); is even a better bet if you're already using jQuery, I just wanted to remove the dependency.)

The Raphael documentation is a reference, not a tutorial, so you have to poke around... it probably helps if you know some of the basics of SVG. 

In processing, I had made up a sine wave as a serious of short line segments. In Raphael, I figure I'd want a Path: a path is a series of line and curve segments. Entertainingly, you define a path via a string, and a series of text commands. It reminded me of drawing with the language Logo and its turtle graphics in my youth. 

So to see a Path in action, you can add this line to the boilerplate, which will draw a rotated chunky path.
var p = paper.path("M50,50 L100,50 L100,100 L150,100 L150,50").rotate(45,50,50);
Some things to note:
  • Raphael uses the same kind of command chaining as jQuery, so I added the rotate command to the end. 
  • You can use commas or spaces as delimiters between commands and the arguments.
  • I used capital letters, so all the coordinates were absolute... if I had used lowercase, they would be relative to where we last drew.
  • By default angles are in degrees (i.e. 360 = circle). 
  • If I didn't specify the coordinates to rotate around, the Path would have rotated around its own center.
  • Raphael uses "painter order" rather than Z-indexing... the last thing you add to the Paper is what appears at front.
Once I was here, it still wasn't clear how to go forward in terms of making the animation I wanted. There's a pretty extensive set of animation features, but I couldn't figure out if there was a way to make the minor adjustments to the Path. (In fact, it turns out I can't even rotate a Path as an animation! Hmm.) So while I thought it would be "more Raphaelish" to make the objects once and then animate their attributes, it turned out I was going to have to do it similarly to the Processing version, and constantly create and destroy my path objects each tick.

To cut to the chase, here's what I ended up with, click kick to see it with some inertia, or just spin for a constant rotation:
You can go to the webpage to view the source though it's a bit hacky and ugly...
So comparing that animation to the original graphic:
It's not 100%, but with the tweaking I did it's not bad. Our art guy was very pleased with the result.
As the animation works, you can see where I had to add in additional "crossbeams" - the 2D original didn't have to worry about that. Also I couldn't quite figure out how to duplicate the "over under" cheat in the original, where they put a break in the underlying squiggle, so working with our art guy we decided to color one of the squiggles a bit darker.

The thing is the animation flickered a bit on IE, and even on Firefox the constant motion was pushing the CPU to around 7-10%. I decided to punt-- I added a step button to move the animation one frame at a time, and then I laboriously constructed an animated GIF:

Neat! Not quite as 3D as the Processing version, alas. (And since I was "cheating" and making a GIF anyway, I could have stuck with Processing.... in fact I might go and try that, since it's more powerful, and easier to push out a series of TIFs (rather than relying on screenshots like I did))

Finally, we were looking for the animation to run for a bit, then stop, then restart. I made the GIF animate once, and then used jQuery like this when we wanted to see it spin:

//first set up an offscreen image with the animated GIF:
this.dnaImg =  new Image();
this.dnaImg.src = '/components/onboarding/images/DNAIconAnimate.gif';
//later when we want it to animate, (re)set the 
//src of the onscreen image to the offscreen one:
$('.dnago').attr('src',this.dnaImg.src);

Easy-peasy, and it added a lot of visual pizazz to that part of the site.

Wednesday, December 7, 2011

animation nation part 1: processing.js


At work we thought it might be cool if we could jazz up the following bit of pseudo DNA (using Alleyoop's colors as the crossbars) that we are using during our signup process.

I wondered if we could get a nice little 3D-ish effect by treating the helix strands as sin curves and then animating them by increasing the angle (Hey remember the into to Superman II ?  Around 9 seconds in, the awesome spinning prison rings are actually 2 rings permanently welded together and then rotated as single unit... an awesome economical visual effect.)

My goto language for this kind of thing is Processing. Processing is a little Java IDE and API that makes making applets really easy, and lets me leverage my 10-odd years of Java experience in a way that works on most any browsers to make gamejam games and my own toys. (With applet supporting waning over the years, I'm happy to see stuff like Minecraft exercising Java as a viable game platform.)

An applet would be overkill for the task (not to mention raising the spectre of Content-y and plugin warnings) so I turned to Processing's little brother Processing.js. It's an HTML5, javascript/canvas based version of Processing. It has 2 modes: one where it can (try to) run the exact same ".pde" files as the Java version, and another where it acts as a highpowered API to the canvas object for more traditional javascript code. I knew Processing.js might not be acceptable for use on our actual site, since it depends on the canvas object that is only now getting support by IE, but I decided to give it a whirl anyway.

The pde "run the java code" mode is in preferred, but for my money it's not ready for prime time. It is essentially using a preprocessor to translate Java code into javascript, and the results aren't always pretty, especially for stuff involving classes and collections of mixed object types. The error messages are often extremely opaque or absent altogether.

Despite the problems, Processing.js is still a lot of fun, especially with one of the inbrowser IDEs like sketchpad.cc. You can type code and almost instantly see results, part of the charm of both versions of Processing.

Nearly every Processing program has two main parts: setup(), where one time activities are performed, and draw() which is called every frame. Most Processing programs (at least the ones I've written) clear the background every frame and draw the entire frame from scratch, but some just keep drawing on the same canvas.

Here's what I came up with. Apologies for the code that follows -- it's mostly hacking around proof-of-concept stuff, and there are a lot of "magic numbers" there I tweaked to make it look good... not exactly like the model, but enough to see that a spinning 3D effect could emerge from a sine wave fragment place against the flipped version of itself and constantly having its starting angle increased. Essentially the variable x1 runs through the horizontal values, x2 is the next value (for drawing line segments) and we get the two y values by running the sin() function. And then at certain x1 values, we draw the cross pieces.


void setup() {
    size(200, 200); 
    smooth();
    frameRate(30);
    strokeWeight(10);
} 
float off = 0;
void draw() {  
background(255);
pushMatrix();
translate(120,0);
rotate(3.14 / 4);

off += .1;
for(float x1 = 0; x1 < 120; x1++){
    float x2 = x1 + 1;
    float a1 = off + x1 / 40;
    float a2 = off + x2 / 40;
    float y1 = 20 * sin(a1);    
    float y2 = 20 * sin(a2);    
 
    if((x1 +1) % 31 == 0){
       stroke(255,0,0);
       line(x1,100,x2,y2+100);
       line(x1,100,x2,-y2+100);
    }
    stroke(128);
    line(x1,y1+100,x2,y2+100);
    line(x1,-y1+100,x2,-y2+100);
}
popMatrix();
 
}


Here's the result (IE users are out of luck, in this way and in so many others...)


Not half bad if I do say so myself! The effect was very sensitive to little tweaks.

Next up: the same idea in Raphael.js... a very different tool that works on all the major browsers.

Monday, December 5, 2011

worthy read

Ask Tog about Search vs Browser on iOS. I need to figure out how to push my self ever more firmly into the "HCI expert" camp.

I have an ancient copy of "Tog on Interface" on my bookshelf, I should dust it off and give it a browse. (Or a search.)

Friday, December 2, 2011

javadvent 2011 and processing

So, some years I make an Advent Calendar, with a different unique miniature videogame or virtual toy for every day of December up 'til Christmas... for this year it's at http://kirk.is/java/advent2011/

It's a fun exercise in UI design, trying to come up with 25 fun but fairly intuitive interactions. (I still provide instructions, but I kind of wish I didn't have to.) Also, the style of Advent Calendars, with a small distinct treat every day, makes a kind of delightful "interface". The calendar itself is basically a copy and paste of the 2009 Edition (except I made it so only one entry is visible at a time, multiple instances open tends to bog down machines.) It's HTML and CSS and Perl from when I didn't know any jQuery, and it kind of shows, though I think it gets the job done, and is fairly sophisticated at making it difficult to peek ahead.

They entries themselves are written in a Java IDE/library called processing. I love keeping my Java chops maintained a bit, and these little bite sized morels were perfect to code on the subway, to and from work. Unfortunately, Java applet support seems to get shakier and shakier as time goes on...

There is a javascript version called processing.js which in theory runs the same programs, is all HTML5-y, and works natively in browsers. It has some awesome things like in-browser IDEs (http://sketchpad.cc/ was my favorite) There are some drawbacks though: it doesn't support IE (at least before 9? Not sure) and it's far from 100% code compatible with the Java verison.

But Processing is a fun language especially for fun and impressive prototyping. I also use it for the 2 hour "Klik of the Month" game jams at Glorious Trainwrecks, and even for the longer 48 hour "Global Game Jams". You can see some of both at my portfolio site alienbill.com.

Thursday, December 1, 2011

preload your images


Sometimes when building a dynamic site, you might want to load some images after the page has loaded but before the images are shown so that when they do show the appear instantly.

I forget where I found this paradigm, probably somewhere on stackoverflow, but it seemed to work a treat:
function preload(sources, prefix)
{
  var images = [];
  for (var i = 0; i < sources.length; ++i) {
    images[i] = new Image();
var src = sources[i];
if(prefix != undefined){
 src = prefix + src;
}
    images[i].src = src;
  }
}

(Ha, I can tell it's not all my code, I never do "++i".) Sources is an array of image names, prefix is an optional parameter that might contain the URL for the directory where the images are located, so you don't have to include the path on each image name. Then when you actually show the image it should be ready to go, instantly.