Mozilla

Demos

Sort by:

View:

  1. The making of a hack – Media Query Mario

    Like any developer, I love any shiny new tech demo that finds its way into my browser; some of the things people are putting together absolutely blows my mind with the level of creativity and technical skill on show.

    After attending WebDevConf 2012 in mid October, I felt the usual heightened sense of inspiration that a good conference gives us all. On my way back to London, I happened to see a tweet about the current Mozilla Dev Derby in my Twitter stream and, still inspired, thought about creating something to enter myself. That something turned into a tech demo called Media Query Mario; a mash up of Media Queries, CSS3 Animations and HTML5 audio.

    Where to start?

    Thinking of the idea came as a result of which new technologies I wanted to experiment with the most at the time. I had been meaning to delve into CSS animation for some time and combining this with media queries – the focus of that months Dev Derby – seemed pretty logical. Letting the CSS fire off the animations instead of needing JavaScript to do this seemed like a very natural fit.

    Choosing Mario 3 for the animation was simply the first thing that popped into my head. I wanted the animation to be a side scrolling 2D affair and being a retro game nerd, Mario instantly came to mind. Anyone with more than a fleeting interest in 2D Mario games would then see that Mario 3 was the only real choice for my animation (although I’m free to argue against any opposing opinions on the ‘best’ 2D Mario game anytime!)

    One question I’ve been asked since putting the demo out is: why choose CSS animations when other technologies may have been more suitable? The main reason is that I simply wanted to see what they could do. There are plenty of demos showcasing just how awesome canvas and SVG are; my demo is by no means meant to advocate the use of CSS animations over those technologies. I just wanted to give a decent benchmark of where CSS animation is at right now, and at least add them to the conversation when people are choosing which technology is right for their project.

    There was only one rule I set myself when starting to put together the demo – I wanted to stick rigidly to animating using CSS wherever possible. If it was possible to do something in CSS, I wanted to use it, irrespective of performance or how fiddly it was to implement. I’ll come back to how I think it performed in retrospect later.

    Push any button to start

    One of the earliest issues I came up against was knowing what width the user would be viewing the animation at. This was not only important in terms of what size to design the animation to, but especially in terms of how much of the level was on show at any one time. The more of the level on show, the more I would need to animate at any one time.

    After a little thought around how Mario 3 itself was presented, it made sense to make use of the original menu screen to help control this. As well as acting as a holding screen while the animation assets loaded, it would ensure the user resized their browser window down to a dimension I could specify, before then allowing the animation to be started. This was controlled by adding a conditional media query hiding the animation start button:

    @media screen and (max-width: 320px), (min-width: 440px) {
        .startBtn {
            display:none;
        }
    }

    Planning the actual animation itself, I wanted to mirror the way the original game would have been played as much as possible. To help with this I found a video clip that traversed through the level at a pace that I could replicate. This helped me plan the image and sound assets I would need, the speed of the animation and started the thinking around how to animate different enemies and power-ups throughout the level.

    With the structure of the demo planned out, I now just needed the assets. As you might expect, you don’t have to search for too long online to find original game images, sprites and sound files. For my demo, I used NESmaps and Mario Mayhem for the level map and character/object sprites and The Mushroom Kingdom for the sound files. I had to do a small amount of image editing myself, but these gave me a really great start.

    You can view the final spritesheet I used for the animation below.

    Letsa Go!

    So I had an idea planned out and had found my assets; I was ready to start putting it all together in code.

    First, I set about learning the specifics of CSS3 animations. A couple of resources really helped me out; MDN is always a great place to start and is no exception for CSS animations. I would also recommend any of these great articles by Peter, Chris or David – all provide an excellent introduction to getting started with CSS3 animations.

    I won’t look to replicate the depth those articles cover, but will highlight the key properties I made use of in the demo. For brevity, I’ll be covering the CSS3 syntax unprefixed, but if trying any of this out for yourself, prefixes should be included in your code to ensure the animations work across different browsers.

    A quick development tip worth mentioning when using newer CSS3 features such as CSS animations, is that using a preprocessor, such as LESS or SASS, is a massive lifesaver and something I’d highly recommend. Creating mixins that abstract the vendor prefixes out of the code you are directly working with helps keep visual clutter down when writing the code, as well as saving a whole load of time when changing CSS property values down the line.

    Before we get into specific techniques used in the demo, we need to understand that an animation consists of two main parts; the animation’s properties and its related keyframes.

    Animation Properties

    An animation can be built up with a number of related properties. The key properties I made use of were:

    //set the name of the animation, which directly relates to a set of keyframes
    animation-name: mario-jump;
     
    //the amount of time the animation will run for, in milliseconds or seconds
    animation-duration: 500ms;
     
    //how the animation progresses over the specified duration (i.e. ease or linear) 
    animation-timing-function: ease-in-out;
     
    //how long the animation should wait before starting, in milliseconds or seconds
    animation-delay: 0s;
     
    //how many times the animation should execute
    animation-iteration-count: 1;
     
    //if and when the animation should apply the rendered styles to the element being animated
    animation-fill-mode: forwards;

    The use of the animation-fill-mode property was especially important in the demo, as it was used to tell the animation to apply the final rendered styles to the element once the animation had finished executing. Without this, the element would revert to it’s pre-animated state.

    So for example, when animating an element’s left position 30 pixels from an initial position of 0px, if no animation-fill-mode is set, the element will return to 0px after animating. If the fill-mode is set to forwards the element will stay positioned at its final position of left: 30px.

    Keyframes

    The Keyframes at-rule lets you specify the steps in a CSS animation. At its most basic level this could be defined as:

    @keyframes mario-move {
        from { left:0px;   }
        to   { left:200px; }
    }

    Where from and to are keywords for 0% and 100% of the animation duration respectively. To show a more complex example we can also code something like this, which, relating back to the demo, animates Mario jumping between several platforms using multiple keyframes:

    @keyframes mario-jump-sequence {
        0% { bottom:30px; left: 445px; }
        20% { bottom:171px; left: 520px; }
        30% { bottom:138px; left: 544px; }
        32% { bottom:138px; left: 544px; }
        47% { bottom:228px; left: 550px; }
        62% { bottom:138px; left: 550px; }
        64% { bottom:138px; left: 550px; }
        76% { bottom:233px; left: 580px; }
        80% { bottom:253px; left: 590px; }
        84% { bottom:273px; left: 585px; }
        90% { bottom:293px; left: 570px; }
        100% { bottom:293px; left: 570px; }
    }

    So if the above animation was 1 second long, Mario would move from position bottom: 30px; left: 445px; at 0 seconds (0% through the animation) to bottom: 138px; left: 520px; during the first 200ms (or 20%) of your animation. This carries on like this throughout the keyframes defined.

    Animating the action

    Considering the above, the type of animations I created in the demo can be broken down into 3 broad categories:

    • Movement such as Mario jumping or a coin appearing out of a question box.
    • Spriting controls the background-image position of characters and objects in the animation.
    • Looping any animation that is to be repeated for x number of milliseconds or seconds.

    Movement

    Movement covers roughly 75% of all of the animations in the demo. For example, this includes character movement (i.e. Mario running and jumping), power-ups appearing and question boxes being hit. What makes each movement animation differ is the animation-timing-function, the animation-duration and the animation-delay properties.

    The animation-timing-function property helps control the speed of the animation over its duration. Wherever possible I used easing, such as ease-in or ease-in-out to save having to be too precise when defining animation keyframes. Where this didn’t create the effect I needed, I resorted to setting the animation-timing-function to linear and using the keyframes to specify the exact movement I required.

    An example a movement animation can be seen by this jump sequence.

    Spriting

    To control the image background-position of the characters and objects in the animation, I used the step-end timing-function:

    .mario {
        animation-timing-function: step-end;
        ...
    }

    Initially, I thought I may need to use JavaScript to control the image spriting by adding and removing classes to my elements. However, after experimenting with how the step-end timing keyword was implemented, I found it perfectly stepped through the keyframes I had defined, one keyframe at a time.

    To show this in action, take a look at the following examples, which show a simple Mario walking animation and Mario transforming after grabbing a power-up.

    Using step-end in this way wasn’t completely pain free however. To my frustration, when these sprite animations were stacked up over multiple media queries, I found that there was a glitch in WebKit that caused the animation to render differently to the keyframes I had defined. Admittedly, the use of CSS animations in this way is an edge case for browser rendering, but I have filed it as a bug in Chromium, and am hopeful this will be looked at in the future and ironed out.

    LOOPING

    Whenever an animation needed to be repeated over a period of time, looping was defined by adjusting the animation-iteration-count:

    //the animation repeats 5 times
    animation-iteration-count: 5;
     
    //the animation repeats infinitely
    animation-iteration-count: infinite;

    An example of this from the demo would be the rotation of the fireball].

    Through these 3 types of animation, the whole demo was constructed. The final layer was to add in the audio.

    Adding Audio

    Although I had previously downloaded all of the sound files I needed in .wav format, I had to convert them into a format that was usable with HTML5 audio; .ogg and .mp3. I used Switch Audio Convertor (on Mac) to do this, but any good audio conversion software should do the job.

    Once I had the converted files, I needed to detect which file type to serve to the browser. This required a couple of lines of JavaScript to detect support:

    var audio = new Audio(); //define generic audio object for testing
    var canPlayOgg = !!audio.canPlayType && audio.canPlayType('audio/ogg; codecs="vorbis"') !== "";
    var canPlayMP3 = !!audio.canPlayType && audio.canPlayType('audio/mp3') !== "";

    I then created a function to set some default audio parameters for each sound, as well as setting the source file based on the format previously detected to be supported by the browser:

    //generic function to create all new audio elements, with preload
    function createAudio (audioFile, loopSet) {
        var tempAudio = new Audio();
        var audioExt;
     
        //based on the previous detection set our supported format extension
        if (canPlayMP3) {
            audioExt = '.mp3';
        } else if (canPlayOgg) {
            audioExt = '.ogg';
        }
     
        tempAudio.setAttribute('src', audioFile + audioExt); //set the source file
        tempAudio.preload = 'auto'; //preload the sound file so it is ready to play
     
        //set whether the sound file would loop or not
        //looping was used for the animations background music
        tempAudio.loop = (loopSet === true ? true : false);
     
        return tempAudio;
    }
    var audioMarioJump = createAudio("soundboard/smb3_jump"); //an example call to the above function

    It was then just a case of playing the sound at the correct time in sync with the animation. To do this, I needed to use JavaScript to listen for the animation events animationstart and animationend – or in WebKit, webkitAnimationStart and webkitAnimationEnd. This allowed me to listen to when my defined animations were starting or ending and trigger the relevant sound to play.

    When an event listener is fired, the event returns the animationName property, which we can use as an identifier to play the relevant sound:

    mario.addEventListener('animationstart', marioEventListener);
     
    function marioEventListener(e) {
        if (e.animationName === 'mario-jump') {
            audioMarioJump.play();
        }
    }

    If you have multiple animationstart events for one element, such as Mario in my demo, you can use a switch statement to handle the animationName that has triggered the event listener.

    Since writing the demo, I have found that you can also target individual keyframes in an animation by using the Keyframe Event JS shim by Joe Lambert, which gives you even more control over when you can hook into your animation.

    Game Complete

    The response to the demo has been more positive than I’d ever hoped for since it was released. Like any hack, there are things I’d like to go back and improve with more time, but I think it’s more valuable to put what I learned into my next project. I think that the demo has shown that CSS animations can be used to create some amazing effects from fairly simple code, but also brought one bigger issue to my mind while putting it together.

    While complex CSS animations actually perform very well, the creation of such an animation is fairly longwinded. Sure, there are tools out there designed to help with this, such as Adobe Edge Animate and Sencha Animator, but both of these output CSS animations wrapped up in JavaScript. This seems a massive shame to me, as the power of CSS animations is surely in the fact that they shouldn’t have to rely on another technology to execute. I’m not sure if there is a potential way around this, other than coding it by hand yourself, but if anyone knows of any I’d be interested to hear of them in the comments.

    Going back to my earlier comment about comparing CSS animations to using canvas and SVG, I think all have a place at the table when discussing what technology to use for animation. However, the sooner the barrier of time spent to craft complex animations like this one can be lowered, the more relevance, and potential use cases, CSS animations will have in the projects that we do.

  2. Using data-* attributes in JavaScript and CSS

    When HTML5 got defined one of the things that was planned for was extensibility in terms of data that should be in the HTML, but not visible. The data-* attributes allow us to store extra information on HTML elements without needing to use a non-semantic element or pollute the class name. In essence this is what we did with custom attributes before.

    These data attributes can be used in many ways, some are a bad idea but others are a good plan. The rule of thumb is that content that should be visible and accessible should not be stored in them. The reason is that assistive technology is not likely to be able to access them and search crawlers don’t index them either.

    The syntax is dead easy. Say you have an article and you want to store some extra information that doesn’t have any visual representation. Just use data attributes for that:

    <article 
      id="electriccars"
      data-columns="3" 
      data-indexnumber="12314" 
      data-parent="cars">
    ...
    </article>

    Reading those out in JavaScript is also very simple. You could use getAttribute to read them but the HTML5 standard defines a simpler way: a DOMStringMap you can read out via a dataset property:

    var article = document.querySelector('#electriccars'),
                  data = article.dataset;
     
    // data.columns -> "3"
    // data.indexnumber -> "12314"
    // data.parent -> "cars"

    Each property is a string (even if you omit the quotes in the HTML) and can be read and written. In the above case setting article.dataset.columns = 5 would change that attribute.

    Now, as data-attributes are plain HTML attributes you can even access them from CSS. For example to show the parent data on the article you can use generated content in CSS:

    article::before {
      content: attr(data-parent);
    }

    You can also use the attribute selectors in CSS to change styles according to the data:

    article[data-columns='3']{
      width: 400px;
    }
    article[data-columns='4']{
      width: 600px;
    }

    You can see all this working together in this JSBin example.

    Data attributes can also be stored to contain information that is constantly changing, like scores in a game. Using the CSS selectors and JavaScript access here this allows you to build some nifty effects without having to write your own display routines. See the following screencast for an example using generated content and CSS transitions:

    The code example shown in the screencast is also on JSBin.

    Issues with data-attributes

    Sadly enough it seems there is nothing that is so simple and useful that doesn’t come with a price. In this case the main issues to consider are that Internet Explorer does not support the dataset but you’d need to read them out with getAttribute() instead. The other issue is that the performance of reading data-attributes compared to storing this data in a JS data warehouse is bad. Using dataset is even slower than reading the data out with getAttribute().

    That said, though, for content that is not to be shown they are a great solution and maybe we can get them into the next IE soon.

  3. Report from San Francisco Gigabit Hack Days with US Ignite

    This past weekend, the Internet Archive played host to a crew of futurist hackers for the San Francisco Gigabit Hack Days.

    The two-day event, organized by Mozilla and the City of San Francisco, was a space for hackers and civic innovators to do some experiments around the potential of community fiber and gigabit networks.

    Kick-off

    The event kicked off Saturday morning with words from Ben Moskowitz and Will Barkis of Mozilla, followed by the Archive’s founder Brewster Kahle. Brewster talked a bit about how the Archive was imagined and built as a “temple to the Internet.”

    San Francisco’s Chief Innovation Officer, Jay Nath, talked about the growing practice of hackdays in the city and the untapped potential of the City’s community broadband network. The SF community broadband network is a 1Gbps network that provides Internet access for a wide range of community sites within San Francisco—including public housing sites, public libraries, city buildings and more.

    These partners are eager to engage with developers to use the network as a testbed for high bandwidth applications, so we quickly broke off to brainstorm possible hacks.

    Among the proposals: an app to aggregate and analyze campaign ads from battleground states; apps to distribute crisis response; local community archives; 3D teleconferencing for education and medicine; “macro-visualization” of video, and fast repositories of 3D content. Read on for more details.

    Hacking

    Ralf Muehlen, network engineer, community broadband instigator, and all-around handyman at the Archive prepared for the event in a few very cool ways—unspooling many meters of gigabit ethernet cable for hackers, and provisioning a special “10Gbps desktop.”

    The 10Gbps desktop in action

     

    The 10Gbps desktop was a server rack with an industrial strength network card, connected to raw fiber and running Ubuntu. While not a very sensible test machine, the 10Gbps desktop was an awesome way to stress the limits of networks, hardware, and software clients. Video hackers Kate Hudson, Michael Dale, and Jan Gerber created a video wall experiment to simultaneously load 100 videos from the Internet Archive, weighing in at about 5Mbps each. On this machine, unsurprisingly, the main bottleneck was the graphics card. Casual testing revealed that Firefox does a pretty good job of caching and loading tons of media where other browsers choked or crashed, though its codec support is not as broad, making these kinds of experiments difficult.

    Demos

    Here are some of the results of the event:

    Macro-visualization of video

    Kate Hudson, Michael Dale, and Jan Gerber created an app that queues the most popular stories on Google News and generates a video wall.

    The wall is created by searching the Archive’s video collection by captions and finding matches. Imagined as a way of analyzing different types of coverage around the same issue, the app has a nice bonus feature: real-time webcam chat, in browser, using WebRTC. If two users are hovered over the same video, they’re dropped into an instant video chat room, ChatRoulette-style.

    The demo uses some special capabilities of the Archive and can’t be tested at home just yet, but we’re looking to get the code online as soon as possible.

    Scalable 3D content delivery

    As Jeff Terrace writes in his post-event blog: “3D models can be quite big. Games usually ship a big DVD full of content or make you download several gigabytes worth of content before you can start playing… [by] contrast, putting 3D applications on the web demands low-latency start times.”

    Jeff and Henrik Bennetsen, who work on federated 3D repositories, wanted to showcase the types of applications that can be built with online 3D repositories and fast connections. So they hacked an “import” button into ThreeFab, the three.js scene editor.

    Using Jeff’s hack, users can load models asynchronously in the background directly from repositories like Open3DHub (CORS headers are required for security reasons). The models are seamlessly loaded from across the web and added into the current scene.

    This made for an awesome and thought-provoking line of inquiry—what kind of apps and economies can we imagine using 3D modeling, manipulation, and printing across fast networks? Can 3D applications be as distributed as typical web applications tend to be?

    Bonus: as a result of the weekend, the Internet Archive is working on enabling CORS headers for its own content, so hopefully we will be able to load 3D/WebGL content directly from the Archive soon.

    3D videoconferencing using point cloud streams

    XB PointStream loads data from Radiohead's House of Cards music video

    Andor Salga, author of an excellent JS library called XB PointStream, wanted to see if fast networks could enable 3D videoconferencing.

    Point clouds are 3D objects represented through volumetric points rather than mesh polygons. They’re interesting to graphics professionals for a number of reasons—for one, they can have very, very high-resolution and appear very life-like.

    Interestingly, sensor arrays like the low-cost Microsoft Kinect can be used to generate point cloud meshes on the cheap, by taking steroscopic “depth images” along with infrared. (It may sound far out, but it’s the basis for a whole new wave of motion-controlled videogames).

    Using Kinect sensors and WebGL, it should be possible to create a 3D videoconferencing system on the cheap. Users on either end would be able to pan around a 3D model of a person they’re connected to, almost like a hologram.

    This type of 3D video conferencing would be able to communicate depth information in a way that traditional video calls can’t. Additionally, these kinds of meetings could be recorded, then played back with camera interaction, allowing users to get different perspectives of the meetings. Just imagine the applications in the health and education sectors.

    For his hack, Andor and a few others wanted to prototype a virtual classroom that would—for instance—enable scientists at San Francisco’s Exploratoreum to teach kids at community sites connected to San Francisco’s community broadband network.

    After looking at a few different ways of connecting the Kinect to the browser, it appeared that startup Zigfu offers the best available option: a browser plugin that provides an API to Kinect hardware. San-Francisco native Amir Hirsch, founder of Zigfu, caught word of the event and came by to help. The plan was to use Websockets to sync the data between two users of this theoretical system. The team didn’t get a chance to complete the prototype by the end of the weekend, but will keep hacking.

    Point clouds are typically very large data sets. Especially if they are dynamic, a huge amount of data must transfer from one system to another very quickly. Without very fast networks, this kind of application would not be possible.

    Other hacks

    Overall, this was a fantastic event for enabling the Internet Archive to become a neighborhood cloud for San Francisco, experimenting on the sharp edges of the internet, and building community in SF. A real highlight was to see 16-year-old Kevin Gil from BAVC’s Open Source track lead a group of teenaged hackers in creating an all-new campaign ad uploader interface for the Archive—quite impressive for any weekend hack, let alone one by a team of young webmakers.

    From left: Ralf Muehlen, Tim Pozar, and Mike McCarthy, the minds behind San Francisco's community broadband network

    Thank everyone for spending time with us on a beautiful SF weekend, and see you next time!

    Get Involved

    If you’re interested in the future of web applications, fast networks, and the Internet generally, check out Mozilla Ignite.

    Now through the end of summer, you can submit ideas for “apps from the future” that use edge web technologies and fast networks. The best ideas will earn awards from a $15k prize pool.

    Starting in September, you can apply into the Mozilla Ignite apps challenge, with $485,000 in prizes for apps that demonstrate the potential of fast networks.

    Check out the site, follow us @mozillaignite, and let us know where you see the web going in the next 10 years!

  4. Click highlights with CSS transitions

    When you watch screencasts from time to time you’ll see that some software adds growing dots to the clicks the person explaining does to make them more obvious. Using CSS transitions this can be done very simply in JavaScript, too.
    click highlighting with CSS

    Check out the following demo on JSFiddle and you see what we mean. When you click on the document a dot grows where you clicked and it vanishes again. If you keep the mouse pressed the dot stays and you can move it around.

    JSFiddle demo.

    Moving the dot

    The code is incredibly simple. We generate a DIV element and move it with the mouse. For this, we need JavaScript. Check the comments to see what is going on:

    (function(){
     
      // create a DIV element, give it an ID and add it
      // to the body
      var plot = document.createElement('div'),
          pressed = false;
      plot.id = 'clickhighlightplot';
      document.body.appendChild(plot);
     
      // define offset as half the width of the DIV 
      // (this is needed to put the mouse cursor in
      // its centre)
      var offset = plot.offsetWidth / 2;
     
      // when the mouse is moved and the mouse button is pressed, 
      // move the DIV to the current position of the mouse cursor
      document.addEventListener('mousemove', function(ev) {
        if (pressed) { moveplot(ev.pageX, ev.pageY); }
      }, false);
     
      // when the mouse button is pressed, add a class called 
      // 'down' to the body of the element and define pressed
      // as true. Then move the DIV to the current mouse 
      // position.
      document.addEventListener('mousedown', function(ev) {
        document.body.classList.add('down');
        pressed = true;
        moveplot(ev.pageX, ev.pageY);
      }, false);
     
      // when the mouse is released, remove the 'down' class 
      // from the body and set pressed to false
      document.addEventListener('mouseup', function(ev) {
        document.body.classList.remove('down');
        pressed = false;
      },  false);
     
      // move the DIV to x and y with the correct offset
      function moveplot(x, y) {
        plot.style.left = x - offset + 'px';
        plot.style.top = y - offset + 'px';
      }
    })();

    This takes care of creating and moving the DIV and also gives us classes on the body element to play with.

    Growing the dot

    The growing of the dot uses CSS transitions. We change the scale of the dot from 0,0 to 1,1 in a certain amount of time. Notice that we need to scale down rather than up as Webkit zooms scaled elements instead of leaving crisp outlines like Firefox does (the first iteration of this script scaled a 10×10 pixel dot upwards and looked horrible).

    #clickhighlightplot {
      cursor: pointer;
      pointer-events: none;
      background: rgba(255, 255, 10, 0.7);
      width:100px;
      height: 100px;
      position: absolute;
      border-radius: 100px;
      -webkit-transition: -webkit-transform 1s;
         -moz-transition: -moz-transform 1s;
          -ms-transition: -ms-transform 1s;
           -o-transition: -o-transform 1s;
              transition: transform 1s;
       -webkit-transform: scale(0, 0);
          -moz-transform: scale(0, 0);
           -ms-transform: scale(0, 0);
            -o-transform: scale(0, 0);
               transform: scale(0, 0);
    }
    .down #clickhighlightplot {
      -webkit-transform: scale(1, 1);
         -moz-transform: scale(1, 1);
          -ms-transform: scale(1, 1);
           -o-transform: scale(1, 1);
              transform: scale(1, 1);
    }

    Fixing the “covered clickable elements” issue

    The main annoyance with the way the script works now is that you cover elements with the growing dot making them effectively unclickable. That might not be what you want which is why we need to make sure the dot covers them but still allows for clicks to go through. The good news is that there is a thing called pointer events for that. This is supported in Firefox and Webkit but sadly enough not in IE and Opera.

    Moving from JS and CSS to pure JS (but using CSS)

    Now, whilst it is cool to be able to maintain all the look and feel in CSS, the issue is that we need to repeat all the vendor prefixes and we run into issues that browsers might not support what we want to do. That’s why sometimes it makes more sense to move the whole functionality into JavaScript as we have the chance to test support there and write less code.

    Clickhighlight.js does all that. Instead of keeping the maintenance in the CSS (and requiring you to add all the vendor prefixes) you can now have the effect by simply adding the script and calling its init() method:

    <script src="clickhighlight.js"></script>
    <script>clickhighlight.init();</script>

    Elements with the class “nohighlight” will not get the effect. You can change the look by passing an initialisation object:

    clickhighlight.init({
      size:        '300px', // the maximum size of the dot
      duration:    '2s',    // duration of the effect (seconds) 
      colour:      'green', // the dot colour - RGBA = transparency 
      nohighlight: 'notme'  // class of elements not highlighted
    });

    You can see it in action in this video on YouTube:

    The next steps could be to add touch support and to turn this into a bookmarklet so you can use it on any page. Any other ideas?

  5. WebRTC efforts underway at Mozilla!

    Last week, a small team from Mozilla attended IETF 83 in Paris, and we showed an early demo of a simple video call between two BrowserID-authenticated parties in a special build of Firefox with WebRTC support. It is still very early days for WebRTC integration in Firefox, but we’re really excited to show you something that works!

    At Mozilla Labs, we’ve been experimenting with integrating social features in the browser, and it seemed like a cool idea to combine this with WebRTC to establish a video call between two users who are signed in using BrowserID (now called Persona). The SocialAPI add-on, once installed, provides a sidebar where web content from the social service provider is rendered. In our demo social service, we show a “buddy list” of people who are currently signed in using Persona.

    The video chat page that is served when the user initiates a video chat uses a custom API intended to simulate the getUserMedia and PeerConnection APIs currently being standardized at the W3C. A <canvas> is used to render both the remote and local videos, though it is also possible to render them in a <video>. We’re working very quickly to implement the standard APIs, and you can follow our progress on the tracker bug.

    A lot of folks burned the midnight oil to get this demo ready before the IETF event, and special thanks are due to Eric Rescorla, Michael Hanson, Suhas Nandakumar, Enda Mannion, Ethan Hugg, the folks behind Spacegoo, and Randell Jesup, in addition to the whole media team here at Mozilla.

    Current development is being done on a branch of mozilla-central called alder. It is going to be an exciting few months ahead as we work towards bringing WebRTC to Firefox. There is a lot of work to do, and if you are interested in contributing, please reach out! Maire Reavy, our product person and project lead for WebRTC would be happy to help you find ways to contribute. Many of us are also usually available in IRC at #media, and we have a mailing list.

    Transcript of screencast:

    Hi, I’m Anant from Mozilla Labs and I’m here at IETF where we are demonstrating a simple video call between two BrowserID-authenticated parties, using the new WebRTC APIs that we are working on.

    This is a special build of Firefox with WebRTC support, and also has the experimental SocialAPI add-on from Mozilla Labs installed. On the right hand side you can see web content served by demosocialservice.org, to which I will sign with BrowserID. Once I’m signed in, I can see all my online friends on the sidebar. I see my friend Enda is currently online, and so I’m going to click the video chat button to initiate a call.

    Here, I see a very early prototype of a video call window served up by our demo social service. Now, I can click the Start Call button to let Enda know that I want to speak with him. Once he accepts the call, a video stream is established between the two parties as you can see. So, that was a video call built entirely using JavaScript and HTML!

    You can check out the source code for this demo, as well as learn how to contribute to the ongoing WebRTC efforts at Mozilla in this blog post. Thanks for watching!

  6. BrowserQuest – a massively multiplayer HTML5 (WebSocket + Canvas) game experiment

    It’s time for some gaming action with a new HTML5 game demo: BrowserQuest, a massively multiplayer adventure game created by Little Workshop (@glecollinet & @whatthefranck) and Mozilla.

    Play the game: browserquest.mozilla.org
    BrowserQuest

    BrowserQuest is a tribute to classic video-games with a multiplayer twist. You play as a young warrior driven by the thrill of adventure. No princess to save here, just a dangerous world filled with treasures to discover. And it’s all done in glorious HTML5 and JavaScript.

    Even better, it’s open-source so be sure to check out the source code on GitHub!

    Watch a screencast:

    A multiplayer experience

    BrowserQuest screenshot

    BrowserQuest can be played by thousands of simultaneous players, distributed across different instances of the in-game world. Click on the population counter at any time to know exactly how many total players are currently online.

    Players can see and interact with each other by using an in-game chat system. They can also team up and fight enemies together.

    BrowserQuest is a game of exploration: the more dangerous the places you go, the better the rewards.

    Powered by WebSockets

    WebSockets are a new technology enabling bi-directional communication between a browser and a server on the web.

    BrowserQuest is a demo of how this technology can be used today to create a real-time multiplayer game in a single webpage. When you start to play, your browser opens up a WebSocket connection to one of several load-balanced game servers. Each server hosts multiple world instances and handles the player synchronization and game logic within all instances. Because the server code is running on Node.js, both the server and client codebases share a small portion of the same JavaScript source code.

    Server code is available on Github.

    BrowserQuest screenshot

    Built on the Web platform

    BrowserQuest makes extensive use of different web technologies, such as:

    • HTML5 Canvas, which powers the 2D tile-based graphics engine.
    • Web workers, allowing to initialize the large world map without slowing down the homepage UI.
    • localStorage, in which the progress of your character is continually saved.
    • CSS3 Media Queries, so that the game can resize itself and adapt to many devices.
    • HTML5 audio, so you can hear that rat or skeleton die!

    Available everywhere

    Since BrowserQuest is written in HTML5/JavaScript, it is available across a lot of different browsers and platforms. The game can be played in Firefox, Chrome and Safari. With WebSockets enabled, it’s also playable in Opera. Moreover, it’s compatible with iOS devices, as well as tablets and phones running Firefox for Android.

    BrowserQuest screenshot

    The mobile versions are more experimental than the desktop experience, which has richer features and performance, but it’s an early glimpse of what kind of games will be coming to the mobile Web in the future. Give it a try with your favorite mobile device!

    Join the adventure

    Want to be part of BrowserQuest? Create your own character and venture into the world. Fight enemies by yourself or with friends to get your hands on new equipment and items. You might even stumble upon a couple of surprises along the way…

  7. Making the Dino roar – syncing audio and CSS transitions

    It started with Brian King setting up our Google+ page using this round MDN logo by John Slater. I thought this looks cool and reminded me of the famous MGM intro so I wondered if I could turn it into an intro for our video tutorials (not sure if we will do that though). And, some photoshop and sound work later and with a sprinkle of HTML5 audio and CSS transitions, here we are (source on GitHub):

    I started with the sound. If you need Creative Commons licensed sounds, Freesound is a good resource. So I took Chinese Fanfare by Nick-Nack and Roar by CGEffex and put them together in Audacity.

    Saving them as OGG and MP3 gave me an audio element that I could tie into. All I needed was to listen to the timeupdate event and compare the currentTime to trigger the animations. The animations (rotation of the dino and opening and closing of the jaw) are CSS transitions triggered by classes on the parent element. The main trick was to store both the dino and the jaw inside a div and transition them separately. The jaw animation also needed a change in transformation origin as we don’t rotate the image around its center.

    If you got seven minutes to spare, here is a blow-by-blow screencast explaining what is going on:

  8. A simple image gallery using only CSS and the :target selector

    Back in the old days of web development and when CSS2 got support I always cringed at “CSS only” demos as a lot of them were hacky to say the least. With CSS growing up and having real interaction features it seems to me though that it is time to reconsider as – when you think about it – visual effects and interactivity should be maintained in the CSS rather than in JavaScript and CSS.

    With the support we have in new browsers it would be a waste not to use what has been put in. If you have to give all the visual candy to IE6, OK, then you’d have to use a library like jQuery for your effects. But you can have your cake and eat it if you don’t give the shiny to the old browsers out there, but give them a simpler interface and make sure they don’t get what they don’t understand.

    So today let’s take a look at an image gallery using the target selector. This has been done before (lightbox example, thumbnail preview example) but I thought it’d be good to explain the details of what is going on.

    So here is a screencast of our “CSS only image gallery” in action and you can see it for yourself.

    Starting with HTML

    We start with HTML that works across all browsers (except for IE < 9, where you need a polyfill to style HTML5 elements):

    <section class="gallery">
      <nav>
        <ul>
          <li><a href="#one">One</a></li>
          <li><a href="#two">Two</a></li>
          <li><a href="#three">Three</a></li>
          <li><a href="#four">Four</a></li>
        </ul>
      </nav>
      <article id="one" class="target">
        <figure>
          <img src="http://placekitten.com/g/300/200" alt="Kitten 1">
        </figure>
      </article>
      <article id="two" class="target">
        <figure>
          <img src="http://placekitten.com/g/300/201" alt="Kitten 2">
        </figure>
      </article>
      <article id="three" class="target">
        <figure>
          <img src="http://placekitten.com/g/301/200" alt="Kitten 3">
        </figure>
      </article>
      <article id="four" class="target">
        <figure>
          <img src="http://placekitten.com/g/301/201" alt="Kitten 4">
        </figure>
      </article>
    </section>

    Without any CSS this would just show all the kitten images in a vertical row and the links would point to them. This works, and should be more than enough for the IE6 users out there.

    For browsers that support newer CSS, however, we can turn this into our gallery in a few easy steps:

    Step 1: Position the articles

    To make sure we don’t give IE older than 9 any CSS it chokes on, we can wrap all the selectors in a simple media query (in this case checking that the window is at least 400 pixels wide):

    @media screen and (min-width: 400px) {
      ... all the good stuff ...
    }

    We then can give the gallery dimensions and an overflow of hidden to make sure that elements positioned outside of it will not be shown. We also position it relative so that every positioned child element will be positioned relatively to it:

    .gallery {
      position: relative;
      height: 280px;
      width: 340px;
      overflow: hidden;
    }

    Then we position all the target elements absolutely in the gallery with 320 pixels to the left. This hides them off screen as we hide the overflow:

    .target {
      position: absolute;
      top: 60px;
      left: -320px;
      height: 220px;
      width: 300px;
    }

    Now in order to show the image when the link to it was clicked we use the :target selector. This one assigns the CSS to the element when it was targeted – either by activating a link to it in the document or from the URL when the page loaded. With this pseudo selector, we override the left setting and move it to 20 pixels, thus showing the image.

    .target:target {
      left: 20px;
    }

    You can try this out for yourself:

    JSFiddle demo.

    To make this smoother, all we need to do is to add a CSS transition to the target styles. Now all the changes to the styles will happen smoothly during a second rather than immediately.

    .target {
      position: absolute;
      top: 60px;
      left: -320px;
      height: 220px;
      width: 300px;
      -webkit-transition: 1s;
         -moz-transition: 1s;
          -ms-transition: 1s;
           -o-transition: 1s;
              transition: 1s;
    }

    Again, see it in action and play with it.

    JSFiddle demo.

    That is all there is to it – the rest of the effects are just different variations of the same trick – animating opacity from 0 to 1 or CSS transitions.

    Target selectors can be a very powerful trick. The main issue they have though is that the page scrolls to the target, so if there is a big distance between the link and the target you’ll get unsightly jumps.

  9. Creating thumbnails with drag and drop and HTML5 canvas

    HTML5 Canvas is a very cool feature. Seemingly just an opportunity to paint inside the browser with a very low-level API you can use it to heavily convert and change image and video content in the document. Today, let’s take a quick look at how you can use Canvas and the FileReader API to create thumbnails from images dropped into a browser document.

    The final code is available on GitHub and you can see an online demo here. There is also a screencast available on YouTube:

    Step 1: Getting the files into the browser

    The first step to resize images in the browser is to somehow get them. For this, we can just add an element in the page and assign drag and drop event handlers to it:

    s.addEventListener( 'dragover', function ( evt ) {
      evt.preventDefault();
    }, false );
    s.addEventListener( 'drop', getfiles, false );

    Notice that we only prevent the default behaviour when we drag things over the element. This is to prevent the browser from just showing the images when we drag them in.

    The getfiles() function then does the hard work of reading all the files in and sending them on to the functions that do the resizing and image generation:

    function getfiles( ev ) {
      var files = ev.dataTransfer.files;
      if ( files.length > 0 ) {
        var i = files.length;
        while ( i-- ) {
          var file = files[ i ];
          if ( file.type.indexOf( 'image' ) === -1 ) { continue; }
          var reader = new FileReader();
          reader.readAsDataURL( file );
          reader.onload = function ( ev ) {
            var img = new Image();
            img.src = ev.target.result;
            img.onload = function() {
            imagetocanvas( this, thumbwidth, thumbheight, crop, background );
            };
          };
        }
      }
      ev.preventDefault();
    };

    The drop event gives us a property called dataTransfer which contains a list of all the files that have been dropped. We make sure that there was at least one file in the drop and then iterate over them.

    If the file type was not an image (or in other words the type property of the file does not contain the string “image”) we don’t do anything with the file and continue the loop.

    If the file is an image we instantiate a new FileReader and tell it to read the file as a Data URL. When the reader successfully loaded the file it fires its onload handler.

    In this handler we create a new image and set its src attribute to the result of the file transfer. We then send this image to the imagetocanvas() function with the parameters to resize (in the demo these come from the form):

    function imagetocanvas( img, thumbwidth, thumbheight, crop, background ) {
      c.width = thumbwidth;
      c.height = thumbheight;
      var dimensions = resize( img.width, img.height, thumbwidth, thumbheight );
      if ( crop ) {
        c.width = dimensions.w;
        c.height = dimensions.h;
        dimensions.x = 0;
        dimensions.y = 0;
      }
      if ( background !== 'transparent' ) {
        cx.fillStyle = background;
        cx.fillRect ( 0, 0, thumbwidth, thumbheight );
      }
      cx.drawImage( 
        img, dimensions.x, dimensions.y, dimensions.w, dimensions.h 
      );
      addtothumbslist( jpeg, quality );
    };

    This function gets the desired thumbnail size and resizes the canvas to these dimensions. This has the added benefit of wiping the canvas so that no old image data would be added to our thumbnail. We then resize the image to fit into the thumbnail using a resize() function. You can see for yourself what this one does in the source code, it just means the image gets resized to fit. The function returns an object with the width and the height of the new image and the x and y position where it should be positioned onto the canvas.

    If we don’t want the full-size thumbnail but instead crop it we resize the canvas accordingly and reset x and y to 0.

    If the user requested a background we fill the canvas with the colour. After that we put the image on the canvas with the x and y coordinates and the new width and height.

    This takes care of creating a new thumbnail on the canvas, but we haven’t got it as an image in the document yet. To this end, we call addtothumbslist():

    function addtothumbslist( jpeg, quality ) {
      var thumb = new Image(),
          url = jpeg ? c.toDataURL( 'image/jpeg' , quality ) : c.toDataURL();
      thumb.src = url;
      thumb.title = Math.round( url.length / 1000 * 100 ) / 100 + ' KB';
      o.appendChild( thumb );
    };

    This one creates a new image and checks if the users wanted a JPG or PNG image to be created. PNG images tend to be better quality but also bigger in file size. If a JPG was requested we call the canvas’ toDataURL() method with two parameters: the requested JPEG mime type and the quality of the image (ranging between 0 and 1 with 1 being best quality). If a PNG is wanted, we can just call toDataURL() without any parameters as this is the default.

    We set the src of the image to the generated url string and add a title showing the size of the image in KB (rounded to two decimals). All that is left then is to add the thumb to the output element on the page.

    That’s it, you can now drag and drop images into the browser to generate thumbnails. Right now, we can only save them one at a time (or if you have some download add-ons all at once). Would be fun to add Zip.js to the mix to offer them as a zip. I dare you! :)

    More reading:

  10. Screencast: 3D CSS rollovers and 3D CSS tester

    CSS 3D transforms as supported in the latest Aurora allow us to do some nice effects that in the past were only possible in Flash or with a lot of trickery using skewing and filters. I was asked to show a small demo the other day and thought it would be fun to spice up the classic image rollover:

    You can see this in action using Chrome, Safari or Firefox Aurora/Nightly. Older browsers should just show a normal roll-over (and yes, the first example looks weird due to the logo transparency but it makes the effect much cooler in supporting browsers).

    As people asked how this is done I thought it easiest to create a testing tool where you can play with 3D CSS yourself. Here’s a screencast where I explain how to use it and how the roll-over effects were done.

    I found a few interesting bugs while creating this and will file them now. This is the benefit of playing with new tech. Enjoy!

    More reading on this: