What’s Spinnin’?

What do you do if you need to tell someone that you’re busy? In the web world, we’ve determined that an indeterminate radial progress indicator is the way to go. What is an “indeterminate radial progress indicator” you ask? Just a fancy way to say “spinner”. You know, one of those little animated spinning things. It lets the user know that 1. we’re busy, 2. we would like for them to wait patiently, 3. we don’t know exactly how long they’ll have to wait.

While developing our Moonstone UI library, we naturally needed to create one of these spinners. This post describes our implementation and what we learned in the process, which we thought might be useful to you as well.

So, let’s get to it!

Requirements

We have an amazing user interface team that produces interaction and visual designs for all of our controls. They came up with a great design for our spinner, but its requirements presented some interesting implementation challenges. The requirements were as follows:

  • The spinner needs to seamlessly overlay on top of any color background.
  • It needs to have at least 60 frames of animation.
  • The full animation is about two (2) seconds long (so 30+ FPS).
  • It needs to animate while the system/browser/CPU is busy.

Implementations

Often times, you’ll see implementations of this using an Animated GIF since it’s quick to load, easy to build, universally supported and highly customizable when you’re designing it. The downsides are that you only get one-bit worth of transparency (the image is either completely opaque or it’s not, no partial transparency), which means it’s harder to overlay it on top of any random thing and have it “just look nice”; you have a limited color palette to work with, since GIFs only get to use a maximum of 256 colors for each frame; their size and load-time can start to become a problem if you want a very smooth animation or have many frames, since each frame is its own rasterized image, they can add up quickly; and once the CPU gets really busy, GIF animations are temporarily halted, which completely negates their purpose for our needs. We need animation while the CPU is busy.

Example moon.Spinner Animated GIF:

GIF Spinner

Alternatively, you’ll see this implemented as a series of PNG images all globbed together in one image file, like a film-strip, which is then shifted around in rapid succession, jumping from one cell to the next, in a frame just large enough for one of the cells to be visible, to create an animation. This is called a sprite image, and sprite animation. This technique does solve some of the problems of animated GIFs, like true translucency (8-bits), and an expanded full 24-bit color, which when combined, create a 32-bit translucent PNG; and sometimes, we can even compress this down to be a little smaller than an animated GIF. But typically, this animation, stepping through the coordinates of each frame, is handled by JavaScript (we’ll discuss alternate methods in a later post). So what’s the problem? Isn’t JavaScript just always running? Well, this is where it gets a little more technical. Sure, JavaScript is (almost) always available, but JavaScript runs on a single thread, a single channel of instructions, one after the other. If something is filling up the pipe, other things can’t just pass it, since there is no fast-lane, just one lane. So if we have an animation that requires some new instructions every 100 milliseconds, like to jump to the next cell, and the CPU is busy, it’s not going to be able to process our animation instructions until it’s unburdened again. The visual effect of this is that our beautiful animation stops, just when we need it the most. This doesn’t suit our needs either.

An Example Sprite Sheet:

Sprite Sheet

After we had implemented both of the previous solutions, we still weren’t satisfied since that last requirement wasn’t met. And after some discussions with our WebKit engineering team, and some brainstorming, we came up with a method that would give us everything we needed and more.

The Solution

What if we could reconstruct the animation that the UI team came up with, using only DOM elements (plain, simple HTML tags), then animate it using CSS keyframe animations, and pass that animation off to the GPU (a separate processing thread that works really fast). We set off to do just that. Based on the level of complexity of the animation, we determined that our animation could be reconstructed using 4 DOM nodes (DIV tags): an outer DIV and 3 DIVs inside it.

First, we break down the animation that the UI team came up with. It’s composed of 61 frames for the complete loop. The keyframe mechanism supports 0% -> 100%, keyframes tied to percentages of the animation; so we’ll have to convert each keyframe to its relative percentage to most accurately reconstruct the animation. We’ll need to take each animation frame number, and divide it by the total number of frames (61). If you want to avoid thinking at all, drop it into a spreadsheet: set the rows from 1-61 in column A, then in column B, set it to column A/61 and “fill down”. You’ll get a little cheat-sheet of frame-numbers to keyframe percentages.

Our spreadsheet, with frame-numbers in the left column and keyframe percentages in the right:

Example Spreadsheet

Now that we have our cheat-sheet, we can pick out the significant parts of the animation, for a single ball’s complete journey through the animation. Since each ball does the same thing, we can apply the same animation to each one of them, offset by 0, 1/3 and 2/3 respectively. I say “significant”, because we don’t have to keyframe every frame, just the ones where the ball changes direction or speed, because we can let the browser tween everything else. In our animation, the keyframes will be, in order:

  • 0% the first rest state of the first ball
  • 25% the slow-down toward the top
  • 30% the speed-up from the top
  • 33% the impact with the 3rd ball
  • 39%-67% the roll into the second ball slot and wait
  • 72% the impact of the 2nd ball, which pushes our ball past the first resting slot
  • 79%-100% finally a roll back to the initial slot and wait

There’s one last step before we can start writing this as CSS. Since our positioning will be determined by rotating each ball from the center of our container, we must determine the angle that the center of the ball is at, relative to the center of the main container, at each of these keyframes. I just eyeballed it, but you could take the slightly more accurate approach and hold a protractor up to the screen and do some rough measurements.

Angle Measurements

Here’s the result: (written using LESS)

// The width of our ball, in position, measured in degrees.
@moon-spinner-ball-angle: 17deg;

@-webkit-keyframes spinBall {
    0%        { -webkit-transform: rotateZ(@moon-spinner-ball-angle); }
    /* Slow down toward the top */
    15%       { -webkit-transform: rotateZ(160deg); }
    25%       { -webkit-transform: rotateZ(200deg); }
    /* Speed back up as the ball falls */
    30%       { -webkit-transform: rotateZ(225deg); }
    /* Impact at last ball */
    33%       { -webkit-transform: rotateZ(360 - (@moon-spinner-ball-angle * 3)); }
    39%, 67%  { -webkit-transform: rotateZ(360 - @moon-spinner-ball-angle); }
    /* Small bounce forward */
    72%       { -webkit-transform: rotateZ(360 + @moon-spinner-ball-angle + 10); }
    79%, 100% { -webkit-transform: rotateZ(360 + @moon-spinner-ball-angle); }
}

And here’s our HTML

<div class="moon-spinner">
    <div class="moon-spinner-ball moon-spinner-ball1"></div>
    <div class="moon-spinner-ball moon-spinner-ball2"></div>
    <div class="moon-spinner-ball moon-spinner-ball3"></div>
</div>

The rest of the CSS

If we only needed the above, we’d be all set, but we need some additional CSS to do the following: tell each ball how far from the center of the container it is; specify the width of the ball in degrees, with respect to how far away it is from the center (so each ball doesn’t overlap the next); define the size, shape, and color of each ball; and style our container.

I’ve defined some variables to make the later calculations easier. Here are the five we are working with:

Variables

@moon-spinner-time: 1.83s;
@moon-spinner-ball-height: 15%;
@moon-spinner-ball-width: @moon-spinner-ball-height;
@moon-spinner-ball-distance: 20%;
@moon-spinner-ball-angle: 15deg;

You’ll notice everything is measured in percentages; that way, everything is proportional so the spinner can be whatever size it needs to be with no extra CSS. The end result can have its size set via pixels, character height, inches, etc, and it will keep lookin’ good.

Ball CSS

The ball sizing and positioning is a little trickier, because it does the math to make these variables meaningful.

.moon-spinner .moon-spinner-ball {
    position: absolute;
    text-align: center;
    font-size: 80%;
    border-radius: 50%;
    line-height: 0.4em;
    height: @moon-spinner-ball-height;
    width: @moon-spinner-ball-width;
    left: (50% - (@moon-spinner-ball-width / 2));
    bottom: (50% - @moon-spinner-ball-height - @moon-spinner-ball-disatance);
    -webkit-animation: spinBall @moon-spinner-time linear infinite;
    -webkit-transform-origin: center ((@moon-spinner-ball-disatance / @moon-spinner-ball-height) * -100);
}

The Demo

Enough talk, you say? Let’s see where we ended up. We’ve produced two fiddles that demonstrate the final result: one containing the raw HTML / CSS implementation, and another demonstrating the use of the finished Moonstone widget.

First, the raw HTML and CSS: http://jsfiddle.net/Djspaceg/Q4T92/

This fiddle includes 4 versions of the spinner: standard, with no background, with descriptive text, and a special bonus huge spinner. Feel free to fiddle with the fiddle and explore some of the capabilities or add your own!

For some extra fun, try uncommenting some of the commented lines in the fiddle to explore the alternate variations. To get a better idea of what each of the ball animations look like individually, try removing balls 2 and 3.

And now, the Moonstone sample: http://jsfiddle.net/Djspaceg/Lmf6V/

As this fiddle demonstrates, you can add a spinner to any Moonstone app by using the moon.Spinner component, like so: {kind: "moon.Spinner"}, or {kind: "moon.Spinner": content: "Loading..."} for a spinner with an integrated label.

That’s it — we hope you enjoyed the spin! Let us know if you have questions, comments, suggestions, or if you want to share your own “indeterminate radial progress indicator” war stories.

Enyo 2.4 General Availability

In February, we pulled the covers off of a huge body of work the Enyo team has been building out over the past year in our Enyo 2.4 preview announcement.  This included a new data layer with two-way bindings, models, collections, sources, and data-aware controls, allowing for fully declarative model-driven views.  The other exciting announcement was around our new TV offerings: a new UI library called Moonstone designed by the vaunted webOS User Experience team specifically for developing immersive lean-back TV experiences, as well as a focus manager called Spotlight, which takes the headache out of developing TV apps that need remote-control based 5-way navigation.

Today, we’re announcing that Enyo 2.4 is now officially released for general availability.  We’ve completed our cross-platform testing of all of the standard Enyo libraries (core, Onyx, layout, etc.) across our Tier 1 platform matrix, which we recently updated to address new devices and platforms released since Enyo 2.2.  For now, the Moonstone library is officially supported only for the LG webOS TV, but we plan to ramp up cross-TV testing of Moonstone, so stay tuned for announcements about expanded TV support in the future.

Two great references for getting started with Enyo 2.4 are a new set of documentation for the data layer, as well as a new tutorial that takes you from soup-to-nuts through developing a data-driven application using the new Moonstone UI library.

For a full set of changes, see the Enyo 2.4 release notes, or head to the download page to grab the code and get started.

Releasing Mochi

Back in January, The Verge published a story called The Lost Secrets of webOS, which lifted the veil on some forward-thinking webOS hardware and software products that unfortunately never saw the light of day. Featured prominently in that article was Mochi, a striking new design language that the webOS UX team had been working on for the next generation of webOS phones and tablets before everything abruptly and famously screeched to a halt.

In the transitional period before we were acquired by LG, our designers continued to work on Mochi. We worked closely with them, implementing many of the Mochi widgets in the form of a new UI library for Enyo 2 — but we had to put this work in progress on the shelf in early 2013 when we shifted our focus to TV and started pouring most of our energy into Moonstone and Spotlight.

When the Verge story hit, however, it understandably sparked some interest in Mochi. While we don’t have any immediate plans to resume our Mochi work, we would be thrilled to see the community pick up where we left off. With that in mind, we showed Mochi off in an online hangout session in January, and since then — in our copious spare time — we’ve been working toward a public release. This work has included lining up community members to act as maintainers, fixing font licensing issues, and gathering up the internal design documents that would let our community developers understand the ideas behind the UI and see what’s yet to be implemented from the original vision.

Today, we’re pleased to announce that Mochi is now open source and available under the Apache 2.0 license, just like the rest of the Enyo source. The Mochi GitHub repo is now public, and we’ve started putting up some documentation in the Mochi wiki. Of particular note is our list of design documents which includes the PDFs and PNGs that were developed internally to guide Mochi’s development. Not only can this guide future work, but it shows just how much thought went into how these widgets work together. It also points to features that are yet to be implemented.

As maintainers for Mochi, we have two members of the webOS Ports community: Herman van Hazendonk (Herrie82) and Tom King (ka6sox). They will be handling reviewing pull requests and maintaining the code, with the Enyo team at LG providing guidance. Thanks, Herman and Tom, for stepping up!

It’s fun to have Mochi out in the open after all this time. Give it a spin, let us know what you think, and — if you’re so inclined — work with Herman and Tom to move it forward.

Enyo meetup

Continuing our renewed outreach to the Enyo community the Developer Relations and the Enyo teams hosted our inaugural Enyo JS meetup at LG’s-Silicon Valley Lab in Santa Clara on wednesday night.

With LG’s new webOS TV’s (powered by Moonstone, Enyo’s new “made for TV” UI) released, this was a great opportunity for the core engineering to share with the community the hard work that has been done and discuss the road ahead.

We had a good turn out of both experienced Enyo developers and novices, making for a fun and lively exchange of Q&A’s. Some of which came from our youngest attendee who at 13 had some great questions and made the Enyo team earn their pizza! It was great to see some new faces and we hope to continue growing the community as we do more of these meetups in the coming months,

If there are any topics you would like to go over, or any questions, send us a message to meetups@enyojs.com .  We are also thinking about hosting a meetup in the San Francisco area or in other cities.  Give a shout out and gather a crowd and let’s get another one going in a city near you!

See you soon!

Bay Area Enyo JS Meetup on March 26th

If you’re in the SF Bay Area, you’re invited to a in-person meetup for Enyo developers featuring many of the engineers at LG Electronics who work on the framework and support it with the development community. It’s at the LG Silicon Valley Lab office near Great America in Santa Clara, California starting at 5:30PM on Wednesday, March 26th.

Pizza and drinks are provided, and there should be some nice show-and-tell of the work that we’ve been doing over the last year.

Details and RSVP at http://www.meetup.com/Enyo-Meetup/events/170075182/.

Guest Post: Greenius Web App - Enyo and Clojure Stack integration

From time to time we come across an app built with Enyo that piques our interest. When we heard about Greenius and read a little bit about how it was put together we definitely wanted to know more. We reached out to the team at Greenius and asked if they could talk a little more about how they used Enyo with their back-end systems. They are very enthusiastic about Enyo and Greenius’ Aseir Galdos happily prepared this guest post. Take it away, Aseir:

Greenius is a smart platform that brings together people who love growing their food in their gardens, farms or balconies.

More and more people are getting into fresh and local food (farm to table movement, organic farming, slow food) for health and ethical reasons, and many of them grow their own food. These tech-savvy and connected gardeners want to learn more or share their experience about the passionate process of growing their own food. Greenius gives them an easy, fast and cool platform to connect to other gardeners and farmers.

image

The underlying technology we use for Greenius is built with Enyo and Pure on the client side and the “Clojure Stack” on the server side: Clojure language, Ring and Compojure libraries, and the time-based immutable Datomic database.

Enyo offers us a cross-platform, extensible, lightweight and fast JavaScript framework, and with Clojure we can leverage the benefits of functional, dynamic programming and data immutability, as well as Java’s robust runtime and libraries (it is hosted on the JVM). 

So, how is all this technology wired?

Communication is an exchange of pure data structures between both sides, client and server, using JSON format. In Enyo we submit web requests using the Ajax wrapper; in Clojure we use Ring for request and response plumbing and Compojure for routing.

In Greenius, gardeners can follow and be followed by other users, as in a social network. Let’s dive into the client/server communication paradigm with the example of the “Follow” function:

image

First, we create a Kind (i.e.: onyx.Button) that ‘ontap’ triggers the Ajax call to the server:

 new enyo.Ajax({
            url: '/api/follow',
            method: 'PUT',
            contentType: 'application/json',
            cacheBust: false,
            postBody: {
                action: action,
                user: “Mike”,
                followee: “Sarah”
            }
        }).go();

On the server, we have composed hierarchies of routes with Compojure, one of them being ‘/api/follow’, so now we can handle it as follows:

(defroutes api-routes
 (PUT "/api/follow" {:keys [params db conn]}
    (follow params db conn)))

Ring represents the request as the following Clojure map:

{:keys [{"followee" "Sarah", "user" "Mike", "action" "follow"} datomic.db.Db@2066c0a4 #<Connection {:db-id "greenius-29bc7792-ccdf-4597-abf5-85d91d54b58d", :unsent-updates-queue 0, :pending-txes 0, :next-t 1931, :basis-t 1930, :index-rev 0}>]}

- “params” represents the postBody of the enyo Ajax call

- “db” represents the Datomic database

- “conn” represents a specific Datomic database connection

Then, we process the Follow action with a private function and we return a Ring response with a given body (in this case a boolean) and no headers to the client, so that Enyo can handle this response.

(defn- follow
  [{:strs [action user followee]} db conn]
  (if (= action "follow")
    (response (success (social/follow-user db conn user followee)))
    (response (success (social/unfollow-user db conn user followee)))))

And this is the gist of it. No added complexity, just pure data structure exchange.

It has been and is being truly exciting to build Greenius with this technology stack, as we can achieve the scalability, flexibility and simplicity we need to minimize risks and maximize results. It has allowed us to focus on the core business problems and -we hope!- build a useful and elegant Web App that will foster the green lifestyle for present and future generations.

image

Enyo at Apps World Hackathon

A few weeks ago, we unveiled the upcoming Enyo 2.4 release and the new Moonstone and Spotlight libraries, setting the stage for developers to create next-generation apps for smart TVs.

The backdrop for our announcement was the Apps World conference at Moscone Center in San Francisco. We had a full contingent in attendance to meet developers and spread the word about Enyo. We had a booth on the exhibition floor, gave a talk and joined in on a great panel discussion — but undoubtedly one of the highlights of our Apps World experience was our participation in the two-day hackathon.

image

Kevin Schaaf, one of the leaders of the Enyo team, kicked off the event by introducing Enyo, Moonstone and Spotlight. During the event Enyo and DevRel engineers were on hand to answer questions and help the teams.

image

The response was amazing! In total there were 5 projects featuring Moonstone presented to the judges at the end of the event. After conferring, the judges unanimously agreed that Learn TV, one of the Moonstone projects, was the winner. Learn TV is a brilliant concept requiring adolescent viewers to earn “credit” before gaining access to TV content. Credit is earned by completing academic exercises within the app. The app also looked beautiful, showcasing the strength of Moonstone’s elegant UI and design patterns.

As well as taking the hackathon’s top prize, LearnTV also won Enyo’s sponsor prize and will be able to view their app on one of the first LG webOS TV’s to roll off the production line.

Also collecting Enyo prizes for their Moonstone apps were mobiTV who won an LG GPad for their parental Monitor and notification app and BetTV who picked up an LG G2 for their social betting app.

Congratulations to Learn TV and everyone that took part! We look forward to seeing the completed apps on our TVs in the future.

image

A lot of hard work went into developing Moonstone and the Enyo team really enjoyed mingling with developers and seeing first hand the fruits of their labor. Stay tuned for more events; we’re working on putting together an Enyo meetup for the near future.

Introducing Moonstone, Spotlight and Enyo 2.4

It has been an exciting few months for the Enyo team. First, late last year, we broke a long silence with the public release of Enyo 2.3.0-pre.10. Then, in January we celebrated the unveiling of the webOS-powered 2014 LG Smart TV at CES. Today, we’re thrilled to finally give everyone a closer look at what we’ve been working on for the last year.

Moonstone

image

In conjunction with the rebirth of webOS as a platform for smart TV, we’ve built Moonstone: an innovative, beautiful, full-featured UI library for building TV apps. Moonstone features a comprehensive set of UI widgets optimized for TV and a fresh take on the panel-based navigation that has been a hallmark of Enyo since Enyo 1. Moonstone panels support two distinct user interaction patterns — an “always viewing” pattern for lean-back experiences, and an “activity” pattern for more active engagement with an app. Moonstone comes out of the box with light and dark themes and is easily customized to make your app stand out. It also has robust support for internationalization, including widgets that work in both left-to-right and right-to-left contexts.

Spotlight

To go along with Moonstone, we’ve developed Spotlight, a library enabling apps to support key-based navigation — a must for TV, where users often have nothing more than simple up-down-left-right controls. Spotlight uses a nearest-neighbor algorithm to automatically determine where to move focus each time the user presses a key, minimizing developer effort. That said, it’s fully customizable, giving you fine-grained control over how users interact with your app. Spotlight switches seamlessly between pointer-based and key-based navigation, ensuring that users have the best possible experience on devices that support both modes. Spotlight support is baked into Moonstone widgets, but Spotlight has been designed to work with any Enyo UI library.

Cross-Platform and Open-Source

Moonstone and Spotlight will of course power the core apps for the next generation of LG Smart TVs and be the centerpiece of the forthcoming webOS TV SDK — but they’re not just for LG or webOS. In keeping with our deep commitment to supporting cross-platform development, Moonstone and Spotlight are open-source and available for use on any platform.

With CES behind us, today we’ve made the GitHub repositories for Moonstone and Spotlight public. Continuing work on Moonstone and Spotlight will be done in full view, just as it is for Enyo and its other libraries. We’ve not yet had a chance to do extensive testing or optimization on non-webOS platforms, but we’ve been developing with cross-platform support in mind and are excited to see Moonstone apps running on all types of big screens.

Enyo 2.4

In addition to flipping the GitHub repos public, we’ve prepared another pre-release (version 2.4.0-pre.1) of Enyo and its libraries so that you can easily explore docs and samples on the Enyo site. We’ve also updated our Bootplate starter kit and created a Moonstone-specific version of it, so you can grab a mobile-centric or a TV-centric Enyo distribution directly from the site if you’re so inclined.

While Moonstone and Spotlight are certainly highlights of Enyo 2.4, you may be just as interested in the robust new data-layer support you’ll find in this release. Enyo 2.4 has support for observers, one- and two-way bindings, computed properties, models and collections, and a set of new data-aware UI controls.

Astute observers will note that we’ve skipped straight from a 2.3 pre-release to a 2.4 pre-release. Moonstone, Spotlight and the new data-layer support will technically debut in Enyo 2.3, which is in its final release-candidate stage as we speak — but the schedule for Enyo 2.3 is tightly bound to the release and production schedule for the LG webOS TV and therefore has a life of its own. As we continue to shepherd Enyo 2.3 through this process, we’ve decided to move forward with Enyo 2.4 and make that release our primary focus for the cross-platform Enyo community.

We hope you’ll be as excited as we are about Enyo 2.4, Moonstone and Spotlight, and we’re eager to get your feedback. Here are some quick links for exploring what’s new:

If you’re in the San Francisco area today or tomorrow, be sure to stop by Apps World at Moscone Center West and say hello. You’ll find us alongside our webOS colleagues in the LG booth.

MoDevEast 2013

Closing out this year’s Enyo events, members of the team attended the MoDevEast Conference last week in beautiful McLean, VA. The two day event coincided with the release of 2.3 RC2, giving us the opportunity to discuss the latest additions to the framework with our ever growing community of cross-platform developers.

A slow first day gave way to a packed and very busy second day. The Enyo booth in the exhibitor hall was well-attended and had a steady stream of excited developers, many curious about the Enyo roadmap for the near future. More on that next month!

On stage, our own celebrity author Roy Sutton gave a comprehensive talk, for roughly 90 minutes, covering the history of Enyo as well as the development of a simple to-do application using the new data-binding tools in Enyo 2.3. Capping off the talk was preview of the Ares IDE, which is under active open source development. While Roy’s talk was not filmed, his slides are online, along with all the source code if you would like to check it out yourself

Later in the day, during lunch, Roy signed copies of his book, Enyo: Up and Running, courtesy of O’Reilly Media.

image

To close out the event, the MoDev organizers came by and gave Enyo, along with all other sponsors, a box of cupcakes from Georgetown Cupcakes. We enjoyed the cupcakes, as did the developers who were participating in the MoDev hackathon.

image

We appreciate all your support this year and look forward to unveiling some of the new and exciting features we’ve been working on in the New Year.

Happy holidays! See you in 2014.

HTML5 Developer Conference 2013

The HTML5 Developer Conference took place this past week in San Francisco. Our own Senior Developer Relations Engineer, Dave Freeman, was there to present the latest features from the newly released Enyo 2.3.0-pre.10.

The focus of Dave’s energetic talk was on the new data-driven features of Enyo. After giving an overview of the new enyo.Model and enyo.Collection kinds, Dave walked through a college football demo app which binds the data in its models and collections with data aware controls.

Dave also touched on other new features in Enyo, such as the new enyo.Application kind, the enyo.ready() function, and application routing with enyo.Router.

Finally, Dave compared and contrasted some of Enyo’s new features with similar functionality in other frameworks such as Backbone, Angular and Ember.

Check out the Enyo 2.3.0-pre.10 blog post to learn more about the new features in Enyo!

image