Experiments
This is my creative lab and interactive playground. It's focused on the exploration of interaction, visual effects and technologies.
CSS3 Scroll Effects
Decided it was time for some CSS tinkering again and ended up creating this set of CSS3 scrolling styles. Not intended for any practical use but the visuals are surprisingly impactful.
This works by applying a future/past class to list items outside of the viewport
as you scroll. Based on this class a variety of transforms are transitioned to via CSS.
Thanks Paul Irish for improving the JavaScript performance!
Recap 2011
It's that time of the year again! In late 2010, having spent five great years working at Fi, I was determined to change up my professional life. After interviewing with Qwiki and accepting the position of Lead Interactive Developer it was decided; I was moving to San Francisco! It took a good few months of hard work to sort out all of the practicalities but it was definitely worth it now that I'm here.
Fortunately I've still been able to keep this site updated and worked on a variety of projects and experiments throughout the year.
The first project to see the light of day was Sketch, a drawing tool that mimics the style of old cartoons. It was refreshing to build something that allows others to be creative. Now – almost a year later – over 78,000 sketches have been saved.
Sketch was followed by a short freelance project which involved building an interactive and animated logo for a Canadian media production company called Meru. Try it out on their site; http://meru.ca/.
Next I stumbled into the land of CSS3 3D transforms and ended up trying them out on two projects; Holobox and CSS3 3D Slideshow (later renamed reveal.js). A few weeks ago, in mid December, I resumed my CSS 3D pursuits by creating a rolling effect for links and building a Christmas tree out of form elements.
Being far from tired of working with <canvas> I also created a new game called
Coil, it's similar in design to Sinuous
but adds a touch of WebGL and perhaps an element of stress to the gameplay. Shortly thereafter I worked on a
tool called Textify.it which allows you to recreate images using thousands
of letters of text. Using Phonegap, I was able to easily port Textify.it to iOS.
It's been really encouraging to see that there's still a lot of activity on sinuousgame.com even though it's been out since 2010 – meaning ancient, in internet-time. In the past year it saw more than 2,000,000 visits.
Now the new year is approaching and with it new adventures. 2012 will start with relocating to NYC and opening up Qwiki's new office. Can't wait to see where it goes from there!
DOM Tree
Happy holidays! I didn't get a pine tree for Christmas this year so I decided to compensate by creating a digital counterpart out of HTML form elements.
The DOM tree is generated via JavaScript every time you visit the page so you'll
never see the same one twice. All of the forms are filled with holiday greetings
in a variety of languages. CSS3 3D transforms are used to position and rotate, via
translate3d() and rotate3d() respectively, the elements
when the page loads. The infinitely looping rotation on the tree is controlled by
an infinitely looping CSS3 animation.
All of the form inputs are interactive so I challenge you to try and select some of
those <input type="radio"> snow flakes!
zoom.js
zoom.js is a small proof of concept JavaScript library for zooming in on DOM
elements or points in a document. It uses CSS3 transitions and 2D transforms (scaling, translation, transform origin)
on the <body> element to achieve animated magnification.
The API is very minimal;
zoom.in({
element: <HTMLElement>
});
zoom.in({
x: 150,
y: 50,
width: 300,
height: 300
});
zoom.out();
reveal.js
Reveal.js, formerly CSS 3D Slideshow, is a tool which allows you to quickly create good looking HTML presentations. Beyond the changed name, the updated slideshow includes a fair amount of new features:
- New and improved style.
- Added controls in bottom right which indicate where you can navigate.
- Reveal views in iteratively by giving them the
.fragmentclass. - Code sample syntax highlighting thanks to highlight.js.
- Transition themes (available via init options) default/concave/linear.
- Initialization options (toggling controls, toggling rolling links, transition theme).
Sphere: Revisited
The next js1k is still ways off but I felt like crunching some
JavaScript so I revisited my Sphere experiment.
I was able to squeeze it down into 317 bytes and that includes the code for creating
and appending the <canvas> element to the body. Here's the full thing:
var a=document,b=a.body.appendChild(a.createElement("canvas")),c=b.getContext("2d"),d=0,e=b.width=innerWidth,f=b.height=innerHeight,g=Math,h=g.cos,j=g.sin,k=g.PI;setInterval(function(){b.width=b.width;d+=0.1;for(i=1E4;i--;)r=(e+f)/2*(h((d+i)*(0.05+0.2*(j(d/1E5)/k)))/k),c.fillRect(j(i)*r+e/2,h(i)*r+f/2,1.5,1.5)},16);
Leave a comment if you can think of more ways to reduce the size!
UPDATE 1: Mathieu 'P01' Henri was able to squeeze it down to 247 bytes http://jsfiddle.net/LBBmM/1/
UPDATE 2: As if 247 wasn't enough, P01's latest update drops the canvas element and hits 222 bytes! http://jsfiddle.net/LBBmM/32/
Rolling Links
Decided to spice up the text links throughout my site by reviving an old Flash classic – the 3D roll! You'll only be able to see the new style if your browser supports CSS 3D transforms, at the time of writing that means Firefox Nightly, Chrome or Safari.
The only HTML required for this effect is a <span> wrapper around the inner HTML of the target anchor node. The :after
pseudo-element, and its content: attr(...) property, is used to create the flip side. The 3D transformation is carried out
on the <span> wrapper since transitions are not possible on pseudo-elements.
If you're interested in the code, it's availalable over at jsFiddle.net for all your forking pleasure.
Origami
Simply a colorful folding doodle on <canvas>. Click anywhere
on the drawing -- or use your keyboard -- to activate different layouts.
Interview: TechRant
I was interviewed by Ben Hutton of TechRant and shared some of my thoughts about the open web, personal projects and professional life.
404
The folks over at .net magazine have decided to spruce up their 404 page with the help of a few guest artists. For my slot I decided to go for a creepy theme inspired by one of my earlier experiments. The animation is entirely code generated and drawn on an HTML5 canvas element.
If you're interested in how this was created, have a look at the source code on GitHub.
Sphere
When bored, I sometimes open a blank JavaScript file and start writing without any clear objective of where I want to take it. This is the result of one such coding session.
The sphere -- actually more of a spiral -- is built out of 10,000 particles and the structure changes over time.
AppView
AppView was created to help iOS app developers track recent reviews in all markets of the App Store without having to use iTunes Connect's cumbersome UI. Reviews can be sorted on date, rating or store and are automatically translated to English via the Google Translate API.
Textify.it for iOS
I was really happy with how the Textify.it web app turned out and decided it was worthwhile creating a version targeted at iOS. I've been curious about the potential of building iOS apps using the standard array of open web technologies.
With the help of PhoneGap, a framework which bridges JavaScript to native functionality, it was incredibly easy to get going. The iOS version of Textify.it is based on the same JavaScript core as the online version. Some code was added to fire up the camera/library as well as for saving images onto the device.
One challenge with any HTML app targeted at iOS and Mobile Safari is rendering performance, particularly so when using the HTML5 canvas element. The mobile version of Textify.it maintains the original resolution of images and those images may well be 2048x1536 pixels large (iPhone 3GS). The most fruitful optimization for this was to use a CSS transform to scale the canvas rather than doing so via its width/height properties. This seems to force the browser to apply a different, faster, image scaling method. Jonas Wagner has written a post about a similar technique for improved performance here.
Textify.it is available for both iPhone and iPad with a $0.99 price tag.
Textify.it
Browser for or drag an image onto the page and watch it be reconstructed purely out of text. The markup for the resulting textual image can be copied and used elsewhere.
There are a lot of settings which allow you to control the characteristics of the text. Even the smallest tweak to the settings can result in a very different output. Beware that using very large amounts of text will cause heavy browser lag.
WebGL Particles
Was curious about how to efficiently render particles with WebGL so I built a tiny demo. Move your mouse to generate particles.
Canvas Optimization
Building Coil presented me with a few interesting technical challenges. Primarily I had a hard time making the game operate at a reasonable framerate since it uses both 2D Canvas and WebGL. Double whammy. Even though I am still not fully satisfied with how the game performs, I wanted to share some of the optimization techniques used.
Redraw Regions
The best canvas optimization technique for animations is to limit the amount of pixels
that get cleared/painted on each frame. The easiest solution to implement is resetting the entire canvas element
and drawing everything anew but that is an expensive operation for your browser to process.
To limit the areas which are cleared in Coil, I keep track of exactly which rectangular regions are being painted in
so that I can then clearRect(x,y,w,h) only those. This results in the following flow:
1. Clear pixels of all redraw regions
2. Reset redraw region list
3. Paint all elements and store their individual redraw regions
Coil has a debug mode in which these redraw regions are displayed as green rectangles, try it out.
Procedural Sprites
Even though I'm an advocate for generating graphics procedurally, sometimes that's not the most efficient approach. If you're drawing simple shapes with solid fills then by all means drawing them procedurally is the way to go. But if you're drawing more detailed entities with strokes, gradient fills and other performance sensitive make-up you'd be better off using image sprites.
In Coil I use a hybrid approach. Graphical entities are generated procedurally on canvas, but
only once as the game starts up. For the rest of the game's lifespan I paint copies of those sprites rather
than repeatedly generate the same drop-shadow, gradient and strokes.
One final tip when working with image sprites is to always draw them on integer x/y coordinates for better performance on OS X browsers. You can read about this in greater detail here.
Computation Distribution
The Chrome Developer Tools profiler is very useful for finding out what your performance bottlenecks are. In my case, for Coil, the two heaviest operations were the discovery of enclosures and rendering of WebGL. Both of these operations were being executed on every frame.
To distribute the processing for these two operations I changed it so that enclosure discovery only occurs on even frames while WebGL only gets rendered on odd frames.
Performance Based Scoring
From a scoring point of view, bad performance can be beneficial when playing a reflex based game since it gives you more time to react. To combat this unfair advantage I scale down the scores by a factor of the current FPS divided by the target FPS.
Another, perhaps more elegant, solution to this problem is to base all game mechanics on time rather than frames.
Coil
While working on Sinuous I had an idea for a gameplay feature that involved drawing circles around your enemies to destroy them. Trying not to add too many features in one game I decided not to implement it at that point and instead revisit it as a separate game.
Much like Sinuous, Coil is a very straight forward game with as few features and gameplay elements as possible.
The objective is to defeat enemies by enclosing them in the trail formed by your tail. Enemies found within those closures are obliterated. There are two types of enemies; the blue kind explodes after time and causes you damage, red enemies on the other hand are obstacles which should never be drawn into the enclosed area as that will also cause you damage.
Determining how to isolate enclosed areas, and enemies therein, was a very interesting challenge. The final implementation is a three-step process. First I check all line segments in the tail for intersections with each other. Once an intersection is discovered, that enclosed area is filled with a unique color. Finally, collisions are found by checking if the color underneath an enemy matches the closure's unique fill color.
CSS3 3D Hologram
After seeing a video demonstration of a holographic effect created with HTML/CSS I was inspired to build something similar. I ended up creating a 3D box which alters perspective depending on device orientation.
CSS3 3D transforms are used to distort HTML elements and create the walls of the box. JavaScript then tracks
the deviceorientation and devicemotion events and updates the 3D perspective
accordingly. The only property that is being changed via JavaScript is the perspective origin, or
-webkit-perspective-origin to be exact.
Note that this requires a webkit browser and has only been tested on iPhone.
WebGL Shaders
WebGL's introduction is very exciting due to the powerful graphical capabilities it enables in the browser context. This power originates from the ability to run highly optimized programs on the GPU via shaders written in the OpenGL Shading Language – or GLSL for short.
There are two types of shaders; vertex shaders which are used to calculate transformations of vertices and fragment shaders which are used to process indiviual pixels.
Aiming to start learning more about the GLSL language I wrote a few abstract fragment shaders. To avoid some of the rudimentary work I used three.js to compile and run my shaders. I've also been referencing the wonderful Shader Toy for learning examples.
CSS3 3D Slideshow
While preparing a presentation on SVG for an upcoming Stockholm Web Monkeys meetup I needed to construct a simple slideshow. Since this would only ever be presented in a controlled environment, I decided to take the opportunity and experiment with CSS 3D transforms.
The transition between slides is made possible by a combination of CSS 3D transforms and transitions. JavaScript is in charge of updating the class names of all slides depending user input and CSS takes it from there. Thanks to the limited logic involved I was also able to avoid using any third party libraries.
Each slide can contain a nested slideshow. The top level slideshow is navigated via keyboard left/right and the nested slideshows are then reached by using the up/down arrows.
Tip: you can improve the rendering performance of transitions/animations in mobile Safari by
applying a dummy CSS 3D transform. For example: -webkit-transform: translate3d(0,0,0).
Note that this requires a browser with support for CSS3 3D transforms, such as Chromium or mobile Safari.
02-08-2011: The slideshow now provides unique URL's per slide which in turn enables support for internal links.
BreakDOM
Ever wondered what it would feel like to attack a bunch of checkboxes with a radio button that's being steered by a scrollbar?
This is a remix of the classic Breakout game except all game elements have been replaced with HTML user interface elements.
Meru Logo Animation
In early 2011 I collaborated with Canadian media production company Meru on a small but very interesting project. The objective was to "...produce a code generated logo that reacts to various inputs..." and works on all platforms. Having looked at the fluid shape in the logo design I felt this would be a lot of fun to take on – and so I did.
I animated the logo using the HTML <canvas> element and created a fallback
with rotating images for sans <canvas> browsers. The animtion consists of a
few core properties of the logo, such as shape and color, changing slowly using a fine
combination of randomness and control. Realizing that it would take some value tweaking for
everyone involved to be satisfied with the look and feel, I provided an easy way for Meru to
configure the logo. If you're curious about how this looks you can view the source of
this page and look for MeruLogo.initialize.
The animation also works with touch input and runs smoothly on most mobile devices. That latter
part is somewhat of a surprise since everything I've done with <canvas> up
till this point has always been dissapointingly slow in those environments. The primary reason
for why it works so well in this case is that it's rendered at a relatively small resolution.
I'm really happy with how this turned out in the end. The organic nature of the animation compliments the logo design very well without sacrificing any of its core visual principles.
Spring Cleaning
Out with the old, in with the new! I finally got around to creating a new site for myself.
Even though it hadn't grown very old, my previous portfolio ended up being a limitation in what type of content I could publish so I decided it was time for a revamp.
I Joined the Qwiki team!
Translating information from a format aimed at computers into a narrated presentation tailored for human beings is a powerful idea. I realized this after discovering Qwiki in late 2010 and couldn't stop playing around with it. Coincidentally I received an email a few weeks late from Doug Imbruce, founder and CEO of Qwiki, asking for a meeting. After that meeting – and many interviews – I was offered a job which I gladly accepted.
Having worked many years in the advertisement industry I'm excited about the move to a product oriented environment. Primarily because I have longed for an opportunity to invest all of my time and mental energy in one product that I personally believe in. I also want to broaden my scope and what better way to do so than diving into the San Francisco startup scene!
20 Things - Page Flip
Following the launch of 20 Things I Learned About Browsers And The Web there was a lot of interest regarding some of the HTML5 techniques empowering the site. In particular, the page flip transition was a hot topic.
To explain how the page flip works, and how to create one of your own, I wrote a tutorial which was published in .net Magazine (issue #211). This tutorial later went on to be available on Google's HTML5Rocks.com as well.
Sketch
Remember those old cartoons where hand drawn lines appeared to vibrate because of differences between frames? That's what this experiment simulates. It also adds a third dimension to your drawings by allowing you to rotate the canvas.
Drawings can be saved and shared in the gallery.
Hakim El Hattab
I'm a web developer and creative programmer from Sweden that is as passionate about working with animation and interactivity as I am technical implementation. My work experience is broad and includes campaign sites in Flash, web apps in HTML, desktop apps in AIR, experimental HTML5 and CSS3 projects as well as mobile development. I used to work at Fi, a digital production agency in Stockholm, but recently moved to New York to take on the role of Lead Interactive Developer at Qwiki.
During my time with Fi I lead the development of both small and large-scale projects for brands such as Google, BBC, Nintendo, Wacom and SAS.
My personal projects and experiments with HTML5, CSS3 and JavaScript have received a resounding amount appreciation and recognition. They have been served to over 5,000,000 people around the globe in the past year alone.
I am also an active part of the web development community and share the source code for most of my work on GitHub.
Here's a list of some selected projects that I've had the pleasure to work on:
Where To Find Me
- Mail:
- hakim
- .
- elhattab
- @
- gmail
- .
- com
- Twitter:
- @hakimel
- GitHub:
- https://github.com/hakimel
- Instagram:
- hakimel
- LinkedIn:
- http://linkedin.com/in/elhattab
- Google+:
- hakim.se/+
- jsdo.it:
- http://jsdo.it/hakim
Pool
This is my first experiment with WebGL. Even though I am very much for the idea of using librares to abstract away some of the rudimentary work involved in programming, I believe it is crucial to understand what happens behind the curtains. With that reasoning in mind, I set off to create this very basic example only so that I would gain an understanding of what makes WebGL tick.
Interested in getting started with WebGL? I highly recommend going through The Lessons on learningwebgl.com.
HTML5 Canvas Tips
As the HTML5 spec is slowly making its way from working draft to recommendation and browser implementations are solidifying – the urge to make use of these new features grows strong.
Coming from a Flash background, and being a sucker for anything that moves or can be interacted with, I am
most excited about the introduction of the <canvas> element which allows for
bitmap drawing through JavaScript. I started creating some visual experiments
using canvas a few months back and have gathered some tips for anyone dabbling in this neck of the woods.
Performance
When working with animation on canvas, performance can be a challenge since bitmap operations are very
processing expensive, especially at high resolutions. One important optimization rule to follow is to reuse
as many pixels as possible between frames. What I mean by that is the fewer pixels that need to be processed
each frame, the faster your program will run. For example, when erasing pixels with the
clearRect(x,y,w,h) method, it is very beneficial to clear and redraw only the pixels
that have changed and not the full canvas. Unlike the Flash Player’s redraw
regions, this management of “dirty rectangles” needs to be done manually for canvas.
State Stack & Transformation
The canvas can be manipulated via transformations such as rotation and scaling, resulting in a change to the
canvas coordinate system. This is where it’s important to know about the state stack for which two methods are
available: context.save() (pushes the current state to the stack) and
context.restore() (reverts to the previous state). This enables you to apply
transformation to a drawing and then restore back to the previous state to make sure the next shape is not
affected by any earlier transformation. The states also include properties such as the fill and stroke colors.
Compositing
A very powerful tool at hand when working with canvas is compositing modes which, amongst other things, allow
for masking and layering. As an example you can check out Bakemono, where composite modes are used to mask
the eye and mouth. There's a wide array of available composite modes and they are all set through the canvas
context's globalCompositeOperation property.
Anti-Aliasing
To allow for sub-pixel drawings, all browser implementations of canvas employ anti-aliasing (although this does not seem to be a requirement in the HTML5 spec). Anti-aliasing can be important to keep in mind if you want to draw crisp lines and notice the result looks blurred. To work around this you will need to either round to integer values or offset by half a pixel depending on if you’re drawing fills or strokes.
Clearing the Canvas
To clear the entire canvas of any existing pixels context.clearRect(x,y,w,h) is
typically used – but there is another option available. Whenever the width/height of the canvas are set, even if they
are set to the same value repeatedly, the canvas is reset. This is good to know when working with a
dynamically sized canvas as you will notice drawings disappearing.
Next Steps
If you’re interested in learning more about canvas, I would suggest getting started by reading through Mark Pilgrim's wonderful Dive Into HTML5 chapter. Once you're up and going this cheat sheet is a great point of reference.
Conclusion
Canvas has been around for quite a while already and is supported by all modern, and some not so modern, browsers. This being the case, I think it’s very much ready to be used for real production. Some suitable places to utilize canvas would be to enrich buttons, charts/data visualization and navigational elements such as a list of thumbnails for an image gallery.
Sinuous on the Google Chrome Web Store
Preceding the release of the Chrome Web Store (CWS) I collaborated with Google to prepare Sinuous as a launch title app. Following the launch in early December 2010, Sinuous saw a major increase in activity and players. In fact, sinuousgame.com has seen over 900,000 visits since its launch and traffic is now resting at about 5k visits/day.
There are two different ways to deploy apps on the CWS:
- Offline apps that are downloaded to the client.
- Online apps that open an existing app URL.
The latter has raised some discussion – and complaints – because it essentially means that the "app" is no more than a bookmark. In some ways I agree with this, but I still picked this route to avoid having to maintain and update separate versions of the game.
If my app is merely a link to the original game, why do I bother to use the CWS at all? One reason: exposure. The CWS is a very powerful promotional channel for finding an audience.
Bacterium
An interactive experiment with bacteria in a playful and dynamic physics world.
20 Things I Learned About Browsers and the Web / Fi
An online book that aims to better people's understanding about the inner workings of browsers and the web. This project was created for the Google Chrome Team while I was working at Fi and my primary responsibility was building the HTML5 front end.
Collaborating with the Google Chrome team on this project was a great experience. The expertise they brought to the table, both in terms of technology but also in general project process and structure, was invaluable.
I'm really proud of the end result. It demonstrates a use of HTML5 that can not be found in many other applications and has therefore shed light on what can actually be accomplished using these technologies.
Created as part of a team while working at Fi.
Core
Sinuous' sibling game. More evil red dots!
Sinuous Won 10k Apart
The 10k Apart competition, organized by MIX Online together with An Event Apart, challenged developers to build web apps in HTML5 using less than 10kb.
In the end 367 applications had been submitted and out of those my game, Sinuous, ended up taking home the grand prize!
BBC - Life Is... / Fi
This site, built entirely in Flash, is used to showcase some of BBC Earth's stunning nature photography. It's centered around a fluid interface that blends organically into the edges of the page so that you can focus on what matters; the content.
Created as part of a team while working at Fi.
Sinuous
A game built on the HTMLCanvas element which will test your mouse pointer reflexes. The
objective is to stay clear of the evil red dots and stay alive as long as possible. Even
though the game play is linear sinusoidal and the graphics are minimalist it can get quite addictive.
Sinuous is the grand prize winner of the 10k Apart competition for best HTML application in under 10 kb and has seen close to one million plays to date. The game was also released, and featured on the Google Chrome Web Store.
Sinuous
A game built on the HTMLCanvas element which will test your mouse pointer reflexes. The
objective is to stay clear of the evil red dots and stay alive as long as possible. Even
though the game play is linear sinusoidal and the graphics are minimalist it can get quite addictive.
Sinuous is the grand prize winner of the 10k Apart competition for best HTML application in under 10 kb and has seen close to one million plays to date. The game was also released, and featured on the Google Chrome Web Store.
Bakemono
A little monster that I brought to life with JavaScript. Bakemono is Japanese for monster.
Keylight
A playhead travels between keys which resonate in sound depending on where they are placed in the room.
Blob
Soft blobby physics. It's like, you know... jelly?
Magnetic
Control and create currents of particles which react to magnetic nodes.
Trail
Particle movement patterns that generate smooth trails.
Particle Depth
Particle positioning patterns using depth.
Wave
A wave with bubbles floating on the surface, the bubbles each represent a tweet with the word "water" in it.
Particles
Particles slide across the screen and grow as they get close to the mouse.
And then?
There's much more to put in here but as it turns out – it takes time to write up descriptions and collect old material. To be continued...