This tutorial is out of date and no longer maintained.
HammerJS is a popular library that helps you add support for touch gestures (e.g. swipe, pan, zoom, rotate) to your page.
In this article, we will see how easy Angular 2 can work with HammerJS.
We will be building a carousel of avatars. The user can swipe left or swipe right to view each avatar. Test it out yourself here (works best in mobile, but tested on chrome and firefox desktop browser with an emulator).
Live demo with full source code here: https://plnkr.co/plunker/LCsiXOtzSedGZDbGQ3f8?p=preview
Let’s take a look at how our folder structure looks like. We’ll have an app folder that contains our avatar carousel and main.ts
file for bootstrapping our application.
|- app/
|- app.component.html
|- app.component.css
|- app.component.ts
|- app.module.ts
|- main.ts
|- index.html
|- tsconfig.json
Let’s start with our app component. In this component, we will define our list of avatars and handle the swipe event and show/hide an avatar based on the swipe sequence.
// app/app.component.ts
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'my-app',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css']
})
export class AppComponent {
// constant for swipe action: left or right
SWIPE_ACTION = { LEFT: 'swipeleft', RIGHT: 'swiperight' };
// our list of avatars
avatars = [
{
name: 'kristy',
image: 'http://semantic-ui.com/images/avatar2/large/kristy.png',
visible: true
},
{
name: 'matthew',
image: 'http://semantic-ui.com/images/avatar2/large/matthew.png',
visible: false
},
{
name: 'chris',
image: 'http://semantic-ui.com/images/avatar/large/chris.jpg',
visible: false
},
{
name: 'jenny',
image: 'http://semantic-ui.com/images/avatar/large/jenny.jpg',
visible: false
}
];
// action triggered when user swipes
swipe(currentIndex: number, action = this.SWIPE_ACTION.RIGHT) {
// out of range
if (currentIndex > this.avatars.length || currentIndex < 0) return;
let nextIndex = 0;
// swipe right, next avatar
if (action === this.SWIPE_ACTION.RIGHT) {
const isLast = currentIndex === this.avatars.length - 1;
nextIndex = isLast ? 0 : currentIndex + 1;
}
// swipe left, previous avatar
if (action === this.SWIPE_ACTION.LEFT) {
const isFirst = currentIndex === 0;
nextIndex = isFirst ? this.avatars.length - 1 : currentIndex - 1;
}
// toggle avatar visibility
this.avatars.forEach((x, i) => x.visible = (i === nextIndex));
}
}
swipe
.swipe
takes two parameters:
SWIPE_DIRECTION
and the value is swipeleft
or swiperight
.swipe
, swipeleft
, swiperight
, swipeup
, swipedown
. In our case, we just handle swipeleft
and swiperight
.swipe
action later in our HTML view.Here’s our HTML view.
<!-- app/app.component.html -->
<div>
<h4>Swipe Avatars with HammerJS</h4>
<!-- loop each avatar in our avatar list -->
<div class="swipe-box"
*ngFor="let avatar of avatars; let idx=index"
(swipeleft)="swipe(idx, $event.type)" (swiperight)="swipe(idx, $event.type)"
[class.visible]="avatar.visible" [class.hidden]="!avatar.visible">
<div>
<img [src]="avatar.image" [alt]="avatar.name">
</div>
<div>
<a class="header">{{avatar.name}}</a>
</div>
</div>
</div>
avatar
using *ngFor
directive, we declare a local variable idx
to hold the current index of the avatar.swipeleft
and swiperight
event, call the swipe
function that we declared earlier.$event
is the event object. We don’t need the information of the whole $event
object. We need only $event.type
which returns a string of swipeleft
or swiperight
.[class.visible]
or [class.hidden]
. We will add or remove these two CSS classes based on the avatar.visible
property.We can use semantic-ui CSS to ease our styling, but that’s not necessary for our purposes. Apart from that, there are a couple of custom CSS classes that we need to add for our component.
.swipe-box {
display: block;
width: 100%;
float: left;
margin: 0;
}
.visible {
display: block;
}
.hidden {
display: none;
}
.swipe-box
to float all the avatars..visible
and .hidden
are used to show/hide the avatar card.We’re now done with our component. Let’s move on to setting up HammerJS. First, we need to include the HammerJS Javascript file in our main view index.html
file.
<!-- index.html -->
<head>
...
<!-- Hammer JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.js"></script>
....
</head>
By default, the desktop browser doesn’t support the touch event. HammerJS has an extension called touch-emulator.js
that provides a debug tool to emulate touch support in the browser. You can include these lines in the index.html
like this before the HammerJS file:
<!-- index.html -->
<head>
...
<!-- Hammer JS Touch Emulator: Uncomment if for desktop -->
<script src="touch-emulator.js"></script>
<script>
TouchEmulator();
</script>
...
</head>
For details on how the emulator works, please refer to the official documentation.
Because I run this example in Plunker, I just include the HammerJS CDN URL. If you want to manage your package locally, you may run the following command:
- npm install hammerjs --save
Then, include the JS files in your build.
If we do not include HammerJS file, an error message will be thrown: “Hammer.js is not loaded, can not bind swipeleft event”.
By default, if you do not have any custom configuration, you can use HammerJS straight away. Angular2 supports HammerJs out of the box. No need to include anything during application bootstrap. Your application module will look something like this:
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
providers: [ ]
})
export class AppModule { }
What if you would like to apply some custom settings like increasing the velocity
and threshold
?
Quick explanation:
There are other settings you can apply as well. For details, refer to HammerJS documentation.
Angular 2 provides a token called HAMMER_GESTURE_CONFIG
which accepts a HammerGestureConfig
type.
In the simplest way, we can extend HammerGestureConfig
like this:
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HammerGestureConfig, HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';
import { AppComponent } from './app.component';
export class MyHammerConfig extends HammerGestureConfig {
overrides = <any>{
'swipe': {velocity: 0.4, threshold: 20} // override default settings
}
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
providers: [ {
provide: HAMMER_GESTURE_CONFIG,
useClass: MyHammerConfig
} ] // use our custom hammerjs config
})
export class AppModule { }
In our case, we just want to override some default settings of the swipe
action. You may implement the HammerGestureConfig class yourself if you want to have more controls.
Take a look at HammerGestureConfig
not so complicated sourcode or the documentation. The whole class only have two properties (events, overrides) and a function (buildHammer).
Angular 2 makes it really easy to integrate with HammerJS for touch gesture event detection.
That’s it. Happy coding!
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!