Touch
Angular Bootstrap 5 Touch
This component allows you to improve the user experience on mobile touch screens by calling methods on the following custom events: pinch, swipe, tap, press, pan and rotate.
Note: Read the API tab to find all available options and advanced customization
Note: This method is intended only for users of mobile touch screens, so it won't work for the mouse or keyboard events.
Configuration
Step 1
Install hammerjs
package.
npm install hammerjs
Step 2
Add HammerModule
to your module imports.
import { HammerModule } from '@angular/platform-browser';
…
@NgModule ({
...
imports: [HammerModule],
...
})
Step 3
Create HammerConfig
and add it to the module providers.
import {
BrowserModule,
HammerGestureConfig,
HammerModule,
HAMMER_GESTURE_CONFIG,
} from '@angular/platform-browser';
...
@Injectable()
export class HammerConfig extends HammerGestureConfig {}
@NgModule ({
...
imports: [HammerModule],
providers: [
{
provide: HAMMER_GESTURE_CONFIG,
useClass: HammerConfig,
},
],
...
})
Press
Press calls the chosen method when the touch event on the element lasts longer than 250 milliseconds.
Hold the button to remove the mask from the image
<div>
<div class="bg-image">
<img src="https://mdbootstrap.com/img/new/standard/city/053.webp" class="img-fluid" />
<div
*ngIf="showMask"
class="mask"
style="background-color: rgba(0, 0, 0, 0.6)"
id="remove-bg"
>
<div class="d-flex justify-content-center align-items-center h-100">
<p id="press-text" class="text-white mb-0">
Hold the button to remove the mask from the image
</p>
</div>
</div>
</div>
<div class="my-3">
<button type="button" class="btn btn-primary btn-press" (press)="onPress()">
Tap & hold to show image
</button>
</div>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
showMask = true;
constructor() {}
onPress() {
this.showMask = false;
}
}
Press duration
To change default press duration, override the press time
value in
HammerConfig
Hold the button for 5s to remove mask from the image
<div>
<div class="bg-image">
<img src="https://mdbootstrap.com/img/new/standard/city/053.webp" class="img-fluid" />
<div
*ngIf="showMask"
class="mask"
style="background-color: rgba(0, 0, 0, 0.6)"
id="remove-bg"
>
<div class="d-flex justify-content-center align-items-center h-100">
<p id="press-text" class="text-white mb-0">
Hold the button for 5s to remove mask from the imag
</p>
</div>
</div>
</div>
<div class="my-3">
<button type="button" class="btn btn-primary btn-press" (press)="onPress()">
Tap & hold to show image
</button>
</div>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
showMask = true;
constructor() {}
onPress() {
this.showMask = false;
}
}
import {
BrowserModule,
HammerGestureConfig,
HammerModule,
HAMMER_GESTURE_CONFIG,
} from '@angular/platform-browser';
...
@Injectable()
export class HammerConfig extends HammerGestureConfig {
overrides = {
'press': { time: 5000 }
}
}
@NgModule ({
...
imports: [HammerModule],
providers: [
{
provide: HAMMER_GESTURE_CONFIG,
useClass: HammerConfig,
},
],
...
})
Tap
The callback on tap event is called with an object containing origin field - the x and y coordinates of the user's touch.
Tap button to change a color
<div>
<div class="bg-image">
<img src="https://mdbootstrap.com/img/new/standard/city/053.webp" class="img-fluid" />
<div class="mask" [ngStyle]="{ 'background-color': background }" id="bg-tap">
<div class="d-flex justify-content-center align-items-center h-100">
<p class="text-white mb-0">Tap button to change a color</p>
</div>
</div>
</div>
<div class="my-3">
<button type="button" class="btn btn-primary btn-tap" (tap)="onTap()">
Tap to change a color
</button>
</div>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
background = 'rgba(0, 0, 0, 0.6)';
constructor() {}
generateColor(): string {
return `rgba(${this.getRandomNumber()},${this.getRandomNumber()},${this.getRandomNumber()},.4)`;
}
getRandomNumber(): number {
return Math.floor(Math.random() * 255) + 1;
}
onTap() {
this.background = this.generateColor();
}
}
Double Tap
Set default taps to touch event.
Change background color with 2 taps
<div>
<div class="bg-image">
<img src="https://mdbootstrap.com/img/new/standard/city/053.webp" class="img-fluid" />
<div class="mask" [ngStyle]="{ 'background-color': background }" id="bg-tap">
<div class="d-flex justify-content-center align-items-center h-100">
<p class="text-white mb-0">Tap button to change a color</p>
</div>
</div>
</div>
<div class="my-3">
<button type="button" class="btn btn-primary btn-tap" (doubleTap)="onTap()">
Tap to change a color
</button>
</div>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
background = 'rgba(0, 0, 0, 0.6)';
constructor() {}
generateColor(): string {
return `rgba(${this.getRandomNumber()},${this.getRandomNumber()},${this.getRandomNumber()},.4)`;
}
getRandomNumber(): number {
return Math.floor(Math.random() * 255) + 1;
}
onTap() {
this.background = this.generateColor();
}
}
Pan
The pan event is useful for dragging elements - every time the user moves a finger on the element to which the directive is attached to, the given method is being called with an argument consisting of two keys: x and y (the values corresponds to the horizontal and vertical translation).
<div>
<div class="bg-image" id="pan">
<img
[ngStyle]="{ transform: panTransform }"
(panstart)="onPanStart()"
(panmove)="onPanMove($event)"
src="https://mdbootstrap.com/img/new/standard/city/053.webp"
class="img-fluid"
id="img-pan"
/>
</div>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
x = 0;
y = 0;
startX = 0;
startY = 0;
panTransform: string;
constructor() {}
onPanStart() {
this.startX = this.x;
this.startY = this.y;
}
onPanMove(event: any) {
event.preventDefault();
this.x = this.startX + event.deltaX;
this.y = this.startY + event.deltaY;
this.panTransform = this.getTransform(this.x, this.y);
}
getTransform(x: number, y: number): string {
return `translate(${x}px, ${y}px)`;
}
}
Pan Left
Pan with only left direction
<div>
<div class="bg-image" id="pan">
<img
[ngStyle]="{ transform: panTransform }"
(panstart)="onPanStart()"
(panLeft)="onPanLeft($event)"
src="https://mdbootstrap.com/img/new/standard/city/053.webp"
class="img-fluid"
id="img-pan"
/>
</div>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
x = 0;
y = 0;
startX = 0;
startY = 0;
panTransform: string;
constructor() {}
onPanStart() {
this.startX = this.x;
this.startY = this.y;
}
onPanLeft(event: any) {
event.preventDefault();
this.x = this.startX + event.deltaX;
this.panTransform = this.getTransform(this.x, 0);
}
getTransform(x: number, y: number): string {
return `translate(${x}px, ${y}px)`;
}
}
Pan Right
Pan with only right direction
<div>
<div class="bg-image" id="pan">
<img
[ngStyle]="{ transform: panTransform }"
(panstart)="onPanStart()"
(panRight)="onPanRight($event)"
src="https://mdbootstrap.com/img/new/standard/city/053.webp"
class="img-fluid"
id="img-pan"
/>
</div>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
x = 0;
y = 0;
startX = 0;
startY = 0;
panTransform: string;
constructor() {}
onPanStart() {
this.startX = this.x;
this.startY = this.y;
}
onPanRight(event: any) {
event.preventDefault();
this.x = this.startX + event.deltaX;
this.panTransform = this.getTransform(this.x, 0);
}
getTransform(x: number, y: number): string {
return `translate(${x}px, ${y}px)`;
}
}
Pan Up/Down
Pan with only up/down direction
<div>
<div class="bg-image" id="pan">
<img
[ngStyle]="{ transform: panTransform }"
(panstart)="onPanStart()"
(panup)="onPanUp($event)"
(pandown)="onPanDown($event)"
src="https://mdbootstrap.com/img/new/standard/city/053.webp"
class="img-fluid"
id="img-pan"
/>
</div>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
x = 0;
y = 0;
startX = 0;
startY = 0;
panTransform: string;
constructor() {}
onPanStart() {
this.startX = this.x;
this.startY = this.y;
}
onPanUp(event: any) {
event.preventDefault();
this.y = this.startY + event.deltaY;
this.panTransform = this.getTransform(0, this.y);
}
onPanDown(event: any) {
event.preventDefault();
this.y = this.startY + event.deltaY;
this.panTransform = this.getTransform(0, this.y);
}
getTransform(x: number, y: number): string {
return `translate(${x}px, ${y}px)`;
}
}
Pinch
The pinch event calls the given method with an object containing two keys - ratio and origin. The first one it the ratio of the distance between user's fingers on touchend to the same distance on touchstart - it's particularly useful for scaling images. The second one, similarly as in doubleTap event, is a pair of coordinates indicating the middle point between the user's fingers.
<div>
<div class="bg-image" id="pan">
<img
[ngStyle]="{ transform: pinchTransform }"
[ngStyle]="{ transformOrigin: pinchTransformOrigin }"
(pinch)="onPinch($event)"
src="https://mdbootstrap.com/img/new/standard/city/053.webp"
class="img-fluid"
/>
</div>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
pinchTransform: string;
pinchTransformOrigin: string;
constructor() {}
onPinch(event: any) {
this.pinchTransform = `scale(${event.ratio})`;
this.pinchTransformOrigin = `translate(${event.origin.x}px, ${event.origin.y}px,)`;
}
}
Swipe Left/Right
The swipe event comes with several modifiers (left, right, up, down) - each of them will ensure that event will fire only on swipe in that particular direction. If the directive is used without any modifier, the callback method will be called each time the swiping occurs, and the string indicating the direction will be passed as an argument.
This example shows example with left and right
Swipe Left-Right to change a color
<div>
<div class="bg-image" (swiperight)="onSwipeRight()" (swipeleft)="onSwipeLeft()">
<img src="https://mdbootstrap.com/img/new/standard/city/053.webp" class="img-fluid" />
<div
class="mask"
[ngStyle]="{ 'background-color': background }"
id="swipe-left-right"
>
<div class="d-flex justify-content-center align-items-center h-100">
<p class="text-white mb-0">Swipe Left-Right to change a color</p>
</div>
</div>
</div>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
background = 'rgba(0, 0, 0, 0.6)';
constructor() {}
generateColor(): string {
return `rgba(${this.getRandomNumber()},${this.getRandomNumber()},${this.getRandomNumber()},.4)`;
}
getRandomNumber(): number {
return Math.floor(Math.random() * 255) + 1;
}
onSwipeLeft() {
this.background = this.generateColor();
}
onSwipeRight() {
this.background = this.generateColor();
}
}
Swipe Up/Down
In order to use (swipeup)
and (swipedown)
events, you need to enable
all swipe directions in the HammerConfig
.
Swipe Up-Down to change a color
<div>
<div class="bg-image" (swipeup)="onSwipeUp()" (swipedown)="onSwipeDown()">
<img src="https://mdbootstrap.com/img/new/standard/city/053.webp" class="img-fluid" />
<div
class="mask"
[ngStyle]="{ 'background-color': background }"
id="swipe-left-right"
>
<div class="d-flex justify-content-center align-items-center h-100">
<p class="text-white mb-0">Swipe Up-Down to change a color</p>
</div>
</div>
</div>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
background = 'rgba(0, 0, 0, 0.6)';
constructor() {}
generateColor(): string {
return `rgba(${this.getRandomNumber()},${this.getRandomNumber()},${this.getRandomNumber()},.4)`;
}
getRandomNumber(): number {
return Math.floor(Math.random() * 255) + 1;
}
onSwipeUp() {
this.background = this.generateColor();
}
onSwipeDown() {
this.background = this.generateColor();
}
}
import {
BrowserModule,
HammerGestureConfig,
HammerModule,
HAMMER_GESTURE_CONFIG,
} from '@angular/platform-browser';
import hammer from 'hammerjs';
...
@Injectable()
export class HammerConfig extends HammerGestureConfig {
overrides = {
swipe: { direction: hammer.DIRECTION_ALL },
};
}
@NgModule ({
...
imports: [HammerModule],
providers: [
{
provide: HAMMER_GESTURE_CONFIG,
useClass: HammerConfig,
},
],
...
})
Rotate
This example shows example with rotate
<div>
<div class="bg-image">
<img
[ngStyle]="{ rotate: rotateTransform }"
src="https://mdbootstrap.com/img/new/standard/city/053.webp"
class="img-fluid"
id="rotate"
(rotate)="onRotate($event)"
/>
</div>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
rotateTransform: string;
constructor() {}
onRotate(event: any) {
this.rotateTransform = `rotate(${event.currentAngle}turn)`;
}
}
Touch - API
Import
import {
BrowserModule,
HammerGestureConfig,
HammerModule,
HAMMER_GESTURE_CONFIG,
} from '@angular/platform-browser';
import hammer from 'hammerjs';
...
@Injectable()
export class HammerConfig extends HammerGestureConfig {
overrides = {
swipe: { direction: hammer.DIRECTION_ALL },
};
}
@NgModule ({
...
imports: [HammerModule],
providers: [
{
provide: HAMMER_GESTURE_CONFIG,
useClass: HammerConfig,
},
],
...
})
Options
Tap
Name | Type | Default | Description |
---|---|---|---|
interval
|
number | 500 |
Set interval to tap |
time
|
number | 250 |
Set delays time to tap event |
taps
|
number | 1 |
Set default value of number for taps |
pointers
|
number | 1 |
Set default value of number for pointers |
Press
Name | Type | Default | Description |
---|---|---|---|
time
|
number | 250 |
Set time delays to take tap |
pointers
|
number | 1 |
Set default value of number for pointers |
Swipe
Name | Type | Default | Description |
---|---|---|---|
threshold
|
number | 10 |
Set distance bettwen when event fires |
direction
|
string | all |
Set direction to swipe. Available options: all, right, left, top, up. |
Rotate
Name | Type | Default | Description |
---|---|---|---|
angle
|
number | 0 |
Set started angle to rotate. |
pointers
|
number | 2 |
Set default value of number for pointers |
Pan
Name | Type | Default | Description |
---|---|---|---|
threshold
|
number | 20 |
Set distance bettwen when event fires |
direction
|
string | all |
Set direction to pan. Available options: all, right, left, top, up. |
pointers
|
number | 1 |
Set default value of number for pointers |
Pinch
Name | Type | Default | Description |
---|---|---|---|
pointers
|
number | 2 |
Option for tap event, set duration to how long it takes to take a tap
|
threshold
|
number | 10 |
Set distance bettwen when event fires |
Outputs
Name | Type | Description |
---|---|---|
tap
|
EventEmitter<void> | This event fires tap touch funcionality. |
press
|
EventEmitter<void> | This event fires press touch funcionality. |
pan
|
EventEmitter<void> | This event fires pan touch funcionality. |
pinch
|
EventEmitter<void> | This event fires pinch touch funcionality. |
swipe
|
EventEmitter<void> | This event fires swipe touch funcionality. |
rotate
|
EventEmitter<void> | This event fires rotate touch funcionality. |
<div>
<div class="bg-image">
<img src="https://mdbootstrap.com/img/new/standard/city/053.webp" class="img-fluid" />
<div
*ngIf="showMask"
class="mask"
style="background-color: rgba(0, 0, 0, 0.6)"
id="remove-bg"
>
<div class="d-flex justify-content-center align-items-center h-100">
<p id="press-text" class="text-white mb-0">
Hold the button to remove the mask from the image
</p>
</div>
</div>
</div>
<div class="my-3">
<button type="button" class="btn btn-primary btn-press" (press)="onPress()">
Tap & hold to show image
</button>
</div>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
showMask = true;
onPress() {
console.log('pressed')
this.showMask = false;
}
}