Self-encapsulating mobile touch events

Keywords: less Mobile

Online consulting also refers to a few examples, feeling that some ideas are too cumbersome, and they are also new to the front of the small white (last year), so in order to exercise their own js level, decided to simply encapsulate under their own ideas, including the following functions:

  • Touch Start: Touch Start
  • swipeLeft: Quick left pull
  • swipeRight: Quick pull right
  • swipeUp: Quick pull-up
  • swipeDown: Fast drop-down
  • dragVertical: Slide vertically
  • dragHorizontal: Slide horizontally
  • Drag: drag
  • tag: tap
  • longTag: Long press
  • Touch End: Touch End

Briefly describe the principle

The main purpose is to judge the user's gesture through three major events (touch start, touch move, touch end), and then dispatch the corresponding event handler (custom).First, there are a few questions to be clear:

1. Tapping and long pressing events are not triggered at just one point. Due to different user's operation habits, several pixel offsets may occur when tapping. It seems that some mobile phones still have error values (not tested);
2. Events involving direction need to calculate the angle value, only the horizontal and vertical directions need to be calculated to get other directions.

Angle calculation:

As shown in the figure, the color part is vertical, the other is horizontal, point A is the starting point of touch start, point B is the finger, and x, y is the horizontal and vertical displacement distance (absolute value).To make the calculation very simple, first deal with question 1 above. Since there is an error, let X or y be greater than a value before calculating the angle. This assumes that 4 (the larger the value, the less accurate the problem 1) will occur. When the finger displaces a distance >=4 in one direction, the angle will be calculated immediately. However, the angle is not actually calculated. Right triangle law, X and y are phases.The isochronism is 45 degrees, and the angle is less than 45 degrees when x > y (point B moves down vertically), that is, horizontally, and vice versa.Even if you don't take a 45 degree angle here, you can use the same principle.

//1. Judge the conditions for sliding horizontally across the screen: the x-axis must be shifted.The displacement distance is greater than 4, and at this time x > y

x !== 0 && x >= 4 && x > y
//2. Judge the conditions for sliding vertically across the screen: the y-axis must be shifted.Displacement distance is greater than 4, and Y > x at this time

y !== 0 && y >= 4 && x < y
//3. Judge the conditions for sliding across the screen to the right: when condition 1 is met

A.x - B.x < 0

//4. Judge the conditions for sliding across the screen to the left: when condition 1 is met

A.x - B.x > 0
//5. Judge the conditions for sliding up across the screen: when condition 2 is met

A.y - B.y < 0

//6. Judge the conditions for sliding down the screen: when condition 2 is met

A.y - B.y > 0

Here's the code. I wrote it a long time ago, and I'm lazy - let's not change this obscure code...The first time you write an article, the intersection begins. Preview Address

/*
Use
    DJ.toucher('#div')
    .on('touchStart', function(e) {
        console.log('touchStart');
    })
    .on('swipeLeft swipeRight swipeUp swipeDown', function(e) {
        console.log('...')
    })
    ...
*/
;(function(w, d, factory) {
    var fn = factory(w, d);

    w.DJ = w.DJ || {};

    w.DJ.toucher = w.DJ.toucher || fn;
})(this, document, function(w, d) {
    "use strict";
    function Djswipe(el) {
        this.elem = d.querySelector(el) || {};
        // Custom Event Library
        this._events = this._events || {};
        // Record Vertical or Horizontal Directions
        this.dir = false;
        // Handle long press timer
        this.ltimer = null;
        this.istouched = false;
    }

    Djswipe.prototype = {
        events: ['touchStart', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'dragVertical', 'dragHorizontal', 'touchEnd', 'drag', 'tag', 'longTag'],
        init: function() {
            this.touch();
            return this;
        },
        //Simulate on custom event binding, separated by multiple event spaces
        on: function(evt, handler) {
            var arrevts = evt.split(' '),
                len = arrevts.length,
                isFunction = typeof(handler) === 'function';
            for(var i=0;i<len;i++) {
                this._events[arrevts[i]] = this._events[arrevts[i]] || [];
                isFunction && this._events[arrevts[i]].push(handler);
            }
            return this;
        },
        //Custom event triggers
        trigger: function(evt, e, s) {
            if (!!evt)
                for (var i = 0; evt[i]; evt[i++].call(this.elem, e, s));
        },
        touch: function() {
            var _t = this,
                sx, sy,
                disX, disY;
            this.elem.addEventListener('touchstart', function(e) {
                _t.dir = false;
                _t.istouched = true;
                _t.islongtag = false;
                _t.startTime = new Date();
                sx = e.targetTouches[0].pageX, sy = e.targetTouches[0].pageY;
                // Start touching
                _t.trigger(_t._events.touchStart, e);

                _t.ltimer = setTimeout(function() {
                    // Long press
                    _t.istouched && _t.dir === false && (_t.trigger(_t._events.longTag, e),_t.islongtag = true);
                }, 500);
            }, false);
            this.elem.addEventListener('touchmove', function(e) {
                var mx = e.targetTouches[0].pageX,
                    my = e.targetTouches[0].pageY,
                    x, y;
                disX = mx - sx, disY = my - sy;

                x = Math.abs(disX), y = Math.abs(disY);
                //Coordinates and displacement values, etc., to make it easy to get them directly from the outside and do other operations
                var status = {
                    startx: sx,
                    starty: sy,
                    movex: mx,
                    movey: my,
                    disx: disX,
                    disy: disY
                }

                // level
                if (x !== 0 && x >= 4 && x > y && _t.dir === false)
                    _t.dir = 0;
                // vertical
                if (y !== 0 && y >= 4 && x < y && _t.dir === false)
                    _t.dir = 1;
                // Drag
                _t.dir !== false && _t.trigger(_t._events.drag, e, status);
                // Slide Horizontally and Vertically
                _t.trigger(_t._events[['dragHorizontal', 'dragVertical'][_t.dir]], e, status);
            }, false);
            this.elem.addEventListener('touchend', function(e) {
                _t.istouched = false;
                _t.disTime = new Date() - _t.startTime;
                clearInterval(_t.ltimer);
                if (_t.disTime < 150) {
                    if (_t.dir === 0) {
                        // About
                        disX < 0 && _t.trigger(_t._events.swipeLeft, e);
                        disX > 0 && _t.trigger(_t._events.swipeRight, e);
                    }
                    if (_t.dir === 1) {
                        // Up and down
                        disY < 0 && _t.trigger(_t._events.swipeUp, e);
                        disY > 0 && _t.trigger(_t._events.swipeDown, e);
                    }
                    // Tap
                    _t.dir === false && _t.trigger(_t._events.tag, e);
                } else {
                    // Handle extra gaps in tag, longtag
                    (_t.dir !== false || _t.dir === false && _t.islongtag === false) && _t.trigger(_t._events.touchEnd, e);
                }
            }, false);
        }
    };

    return function(el) {
        return new Djswipe(el).init();
    }
});

Posted by domainshuffle on Thu, 20 Jun 2019 11:06:09 -0700