Frontend Development 16 min read

Understanding Mobile Gesture Principles and Their Front-End Implementation

The article explains the mathematical foundations and front‑end implementation of five common mobile gestures—drag, pinch, rotate, single‑finger pinch, and single‑finger rotate—using native touch events, vector calculations, and matrix transformations, and provides a lightweight library that emits incremental gesture events for easy integration.

Meitu Technology
Meitu Technology
Meitu Technology
Understanding Mobile Gesture Principles and Their Front-End Implementation

In the era of touch screens, human‑friendly gesture operations have become integral to everyday applications. Modern apps increasingly focus on user interaction and experience, and gestures provide the most direct and effective way to reduce usage cost and improve usability.

This article analyzes the principles of common mobile gestures from a front‑end perspective, introduces the underlying mathematical concepts, and presents a lightweight gesture library implementation.

1. Introduction

The author notes that existing gesture libraries could not fully meet the needs of several projects, prompting the creation of a custom, easy‑to‑use mobile gesture library. Five gestures are covered:

Drag (drag)

Pinch (double‑finger zoom)

Rotate (double‑finger rotation)

SinglePinch (single‑finger zoom)

SingleRotate (single‑finger rotation)

2. Implementation Principles

All gestures are built on the native browser events touchstart , touchmove , touchend , and touchcancel . An independent callback repository ( handleBus ) receives processed parameters and emits gesture events.

3. Basic Mathematical Functions

The article explains the vector space concepts used in gesture calculations.

Point : a coordinate such as O(0,0) or A(-1,2). Touch points are obtained via event.touches , with the index indicating which finger.

Vector : a directed line segment, e.g., a = (1,1) from O to A. Unit vectors i = (1,0) and j = (0,1) form the basis.

Vector Length (Magnitude) :

function getLength(v) {
  return Math.sqrt(v.x * v.x + v.y * v.y);
}

Dot Product (quantity product):

function dot(a, b) {
  return a.x * b.x + a.y * b.y; // a·b = |a|·|b|·cosθ
}

Collinearity Theorem : Vectors a and b are parallel if a = λb, leading to the condition x1·y2 - y1·x2 = 0 . The sign of this expression determines rotation direction.

Rotation Angle can be derived from the dot product:

function getAngle(a, b) {
  const cosTheta = dot(a, b) / (getLength(a) * getLength(b));
  return Math.acos(cosTheta) * (180 / Math.PI);
}

4. Matrix and Transform

In linear space, vectors describe objects while matrices describe their motion. A 2×2 matrix suffices for 2D transformations, but CSS uses a 3×3 matrix to accommodate 3D contexts.

Example conversion:

transform:translate(-30px,-30px) → matrix(1,0,0,1,30,30);
transform:rotate(θdeg) → matrix(cosθ, sinθ, -sinθ, cosθ, 0, 0);
transform:scale(s) → matrix(s,0,0,s,0,0);

Because getComputedStyle returns a matrix, the library provides a matrixTo function to translate it back to translate/rotate/scale parameters.

5. Gesture Implementations

Drag :

// Get initial point A
let startPoint = getPoint(ev, 0);
// In touchmove, get current point B and compute delta
let curPoint = getPoint(ev, 0);
_eventFire('drag', {
  delta: {
    deltaX: curPoint.x - startPoint.x,
    deltaY: curPoint.y - startPoint.y
  },
  origin: ev
});

Pinch (double‑finger zoom) :

// touchstart: compute initial vector length
let vector1 = getVector(secondPoint, startPoint);
let pinchStartLength = getLength(vector1);
// touchmove: compute current vector length
let vector2 = getVector(curSecPoint, curPoint);
let pinchLength = getLength(vector2);
_eventFire('pinch', {
  delta: { scale: pinchLength / pinchStartLength },
  origin: ev
});

Rotate (double‑finger rotation) :

// Compute vectors for start and move
let vector1 = getVector(secondPoint, startPoint);
let vector2 = getVector(curSecPoint, curPoint);
_eventFire('rotate', {
  delta: { rotate: getAngle(vector1, vector2) },
  origin: ev
});

SinglePinch (single‑finger zoom) requires a base point (the element’s center):

let singleBasePoint = getBasePoint(operator);
let pinchV1 = getVector(startPoint, singleBasePoint);
let pinchStartLength = getLength(pinchV1);
let pinchV2 = getVector(curPoint, singleBasePoint);
let pinchLength = getLength(pinchV2);
_eventFire('singlePinch', {
  delta: { scale: pinchLength / pinchStartLength },
  origin: ev
});

SingleRotate (single‑finger rotation) uses the same base point:

let rotateV1 = getVector(startPoint, singleBasePoint);
let rotateV2 = getVector(curPoint, singleBasePoint);
_eventFire('singleRotate', {
  delta: { rotate: getAngle(rotateV1, rotateV2) },
  origin: ev
});

Because touchmove fires at high frequency, each event provides only an incremental delta. The library accumulates these deltas to maintain the element’s actual position:

// Accumulate translation
let dragTrans = { x: 0, y: 0 };
dragTrans.x += ev.delta.deltaX;
dragTrans.y += ev.delta.deltaY;
set($drag, dragTrans);

When an element already has a CSS transform , the initial position must be extracted via window.getComputedStyle and converted with matrixTo :

let style = window.getComputedStyle(el, null);
let cssTrans = style.transform || style.webkitTransform;
let initTrans = _.matrixTo(cssTrans); // {x:-50, y:-50, scale:2, rotate:45}

6. Conclusion

The article encourages readers to extend the library with additional gestures such as double‑tap, long‑press, three‑finger, or four‑finger operations, further enhancing the human‑centric experience of mobile applications.

frontendMobilejavascriptmatrixVectorGesturetouch
Meitu Technology
Written by

Meitu Technology

Curating Meitu's technical expertise, valuable case studies, and innovation insights. We deliver quality technical content to foster knowledge sharing between Meitu's tech team and outstanding developers worldwide.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.