Animations and Gestures in a Windows 8 app using WinJS

Posted by: Admin , on 11/7/2012, in Category DNC Magazine
Views: 19834
Abstract: This article demonstrates gesture recognition and element animations in a Windows 8 application using WinJS, making it intuitive and fun to use

This article was written by Mehfuz Hossain for the DNC Magazine. Subscribe to this .NET magazine for Free.

Windows 8 JavaScript library or WinJS comes with built in support for various gesture effects and element animations that can make your app intuitive and fun to use. In this article, we will create a simple ToDo list (I call it “Tada list”) app and change the way items are added and removed using element list and gesture animation.

Getting Ready

We will skip over the details of data initialization and layout design to look at some quick pointers on wiring things up. The UI is defined in todo.html and the data initialization and actions are implemented in the data.js and todo.js. We’ll go down to the details a little later in the article.

We start at data.js by declaring the data variable that will be used to pull things from local settings. This is the current instance of ApplicationData class that is associated with the app’s app package:

var appData = Windows.Storage.ApplicationData.current

Next, we create the array and add some default todo items. The “data” namespace is declared using WinJS.Namespace.define, which has a binding list and an action method to add new item. This is exposed to the UI.

 

Objects are serialized using JSON.Stringify and de-serialized using JSON.Parse to save and retrieve data from local settings as saving JSON objects directly to roaming / local settings is not supported.

Full code snippet for what we have described so far is shown below:

var todos = [];

todos.push({ title: "Buy surface tablet" });
todos.push({ title: "Buy milk" });

if (!appData.localSettings.values.todos) {
    appData.localSettings.values.todos = JSON.stringify(todos);
}

todos = JSON.parse(appData.localSettings.values.todos);

function insertAtTop(item) {
    if (item.title != null) {
        todos = JSON.parse(appData.localSettings.values.todos);
        todos.splice(0, 0, item);

        appData.localSettings.values.todos = JSON.stringify(todos);

        data.items.splice(0, 0, item);
    }
}

WinJS.Namespace.define("data", {
    items: new WinJS.Binding.List(todos), insertAtTop: insertAtTop
});

List Animation

Before digging deep into the animation, let’s first see how the final UI will look. It is defined in the ‘todo.html’.

TodoList

The definition consists of a simple container div (id =”todoList”). The Title container is defined using the HTML5, ‘header’ tag. We also have an input box for entering new ToDo items.

<header role="main">
    <h1>
        Tada List
    </h1>
</header>

<input class="todo-text" type="text" placeholder="add something" />

<div id="todoList">

</div>

As the data is being inserted, we create the list animation instance using WinJS.UI.Animation.createAddToListAnimation with affected items list and then dynamically create an element in the DOM, insert the new item to the main container (id=”todoList”) and finally execute the animation.

function addNewTodo(todo, prepend) {
    var affectedItems = document.querySelectorAll(".item-container");

    var newItem = document.createElement("div");

    newItem.className = "item-container";
  
    var titleElement = document.createElement("h4");

    titleElement.className = "item-title";
    titleElement.innerHTML = todo;

    newItem.appendChild(titleElement);
    newItem.style.background = listColor();

    ++currentIndex;

    prepareElementForGesture(newItem);

    var addToList = WinJS.UI.Animation.createAddToListAnimation(newItem, affectedItems);

    if (todoList.childElementCount > 0) {
  
        if (prepend)
            todoList.insertBefore(newItem, todoList.childNodes[0]);
        else
            todoList.appendChild(newItem);
    }
    else {
        todoList.appendChild(newItem);
    }
   
    addToList.execute();
}

 

Moreover, we have initialized each element to recognize swipe gesture (which we will cover in next section).

Note that items are inserted from the top, which will create the effect of pushing items down as new ones are inserted. Similarly, for removing items, we have implemented delete list animation:

function deleteTodo(deletedItem) {
var allItems = document.querySelectorAll(".item-container:not([deleting])");

deletedItem.setAttribute("deleting", true);

--currentIndex;

var affectedItems = document.querySelectorAll(".listItem:not([deleting])");

// Create deleteFromList animation.
var deleteFromList = WinJS.UI.Animation.createDeleteFromListAnimation(deletedItem, affectedItems);

// Take deletedItem out of the
//regular document layout flow
//so remaining list items will
//change position in response.
deletedItem.style.position = "fixed";
deletedItem.style.background = "transparent";
deletedItem.style.transform = "translate(100px, 0px)";

deletedItem.style.opacity = 0;

deleteFromList.execute();
}

Gesture animation

We want to delete an item using a left-to-right swipe gesture. So we have to capture and act upon the gesture. Once identified, we have to remove item from the current view and hide it. We have also added a CSS transform animation to move the element to right, which is the effect after someone does a swipe gesture.

After we have the move-to-right effect in place with delete list animation, we also need to make elements (class =”item-container”) respond to gestures.

To implement this, first we need to capture mouse pointer events. More specifically, the following ones:

function prepareElementForGesture(element) {
    element.addEventListener("MSPointerDown", processDownEvent, false);
    element.addEventListener("MSPointerMove", processMoveEvent, false);
    element.addEventListener("MSPointerUp", processUpEvent, false);
    element.addEventListener("MSPointerCancel", processDownEvent, false);
}

Each of these will call the corresponding gesture event. For mouse pointer down / up, it will just be processing the up/down event of gesture recognizer.

function processUpEvent(e) {
    lastElement = e.currentTarget;
    gestureRecognizer.processUpEvent(e.currentPoint);
}

For move event, it is the same. However, instead of single point we need to capture intermediate points collection for the target.

function processMoveEvent(e) {
    lastElement = e.currentTarget;       
    gestureRecognizer.processMoveEvents(e.getIntermediatePoints(e.currentTarget));
}

Next step is to bind mouse events to gesture recognizer (prepareElementForGesture):

gestureRecognizer.gestureSettings = Windows.UI.Input.GestureSettings.crossSlide;
gestureRecognizer.crossSlideHorizontally = true;

var manupulationStarted = false;

gestureRecognizer.oncrosssliding = function (e) {
    deleteTodo(lastElement);
};

var itemsToGestureTrack = document.querySelectorAll(".item-container");

for (var index = 0; index < itemsToGestureTrack.length; index++) {
    prepareElementForGesture(itemsToGestureTrack[index]);
}

Since our use-case was to remove an item if user does a swipe gesture, therefore we have specified a gesture recognizer that will capture only the horizontal cross slide gestures.

Finally, we implement it for all the existing elements (todo items) as well as newly added elements. This is shown in the addNewTodo method above. Now we are all set!

When we run the application (need Win8 RC minimum), it will initially come up with the two default elements. We can add ToDo items but simply typing in the text and hitting enter. To delete an item, on a touch-enabled device, we swipe left to right on the list item we want to delete. For a pointer driven device like the mouse, we do a left mouse button down and move horizontally before mouse up to delete the item.

Conclusion

Creating a todo list and adding custom animation or gesture recognition didn’t require us to call native or COM API. We were easily able to add create / delete list and gesture animation through built in animation library provided by WinJS. These easy to use effects add to the default behavior and help make the app fluid and intuitive to use.

The Windows 8 ListView control already comes with built in list animation. However, if there are cases where you want to implement a custom list view with specific gesture support, the default selection model may not work. In such cases, this article will give you the pointers needed for implementing features as and when you need more control over the experience.

Download the entire souce code on GitHub

Give me a +1 if you think it was a good article. Thanks!
Recommended Articles


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by sachin pethani{Web-Farmer} on Thursday, November 8, 2012 3:47 AM
The link to download source code is broken. Can you please fix it.
Comment posted by Admin on Friday, November 9, 2012 8:22 AM
@sachin: Apologies. The link has been fixed.
Comment posted by vaishnavi on Sunday, November 11, 2012 6:01 AM
very intrestingg article gotta gud knwoledge in win 8
Comment posted by Keith R. on Wednesday, December 12, 2012 1:21 AM
Can't wait to try this out myself. Thanks for the informative post! @blogfreakz

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel