Blame view

node_modules/zrender/src/core/GestureMgr.ts 3.1 KB
bd028579   易尊强   2/28
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  /**
   * Only implements needed gestures for mobile.
   */
  
  import * as eventUtil from './event';
  import { ZRRawTouchEvent, ZRPinchEvent, Dictionary } from './types';
  import Displayable from '../graphic/Displayable';
  
  interface TrackItem {
      points: number[][]
      touches: Touch[]
      target: Displayable,
      event: ZRRawTouchEvent
  }
  
  export class GestureMgr {
  
      private _track: TrackItem[] = []
  
      constructor() {}
  
      recognize(event: ZRRawTouchEvent, target: Displayable, root: HTMLElement) {
          this._doTrack(event, target, root);
          return this._recognize(event);
      }
  
      clear() {
          this._track.length = 0;
          return this;
      }
  
      _doTrack(event: ZRRawTouchEvent, target: Displayable, root: HTMLElement) {
          const touches = event.touches;
  
          if (!touches) {
              return;
          }
  
          const trackItem: TrackItem = {
              points: [],
              touches: [],
              target: target,
              event: event
          };
  
          for (let i = 0, len = touches.length; i < len; i++) {
              const touch = touches[i];
              const pos = eventUtil.clientToLocal(root, touch, {});
              trackItem.points.push([pos.zrX, pos.zrY]);
              trackItem.touches.push(touch);
          }
  
          this._track.push(trackItem);
      }
  
      _recognize(event: ZRRawTouchEvent) {
          for (let eventName in recognizers) {
              if (recognizers.hasOwnProperty(eventName)) {
                  const gestureInfo = recognizers[eventName](this._track, event);
                  if (gestureInfo) {
                      return gestureInfo;
                  }
              }
          }
      }
  }
  
  function dist(pointPair: number[][]): number {
      const dx = pointPair[1][0] - pointPair[0][0];
      const dy = pointPair[1][1] - pointPair[0][1];
  
      return Math.sqrt(dx * dx + dy * dy);
  }
  
  function center(pointPair: number[][]): number[] {
      return [
          (pointPair[0][0] + pointPair[1][0]) / 2,
          (pointPair[0][1] + pointPair[1][1]) / 2
      ];
  }
  
  type Recognizer = (tracks: TrackItem[], event: ZRRawTouchEvent) => {
      type: string
      target: Displayable
      event: ZRRawTouchEvent
  }
  
  const recognizers: Dictionary<Recognizer> = {
  
      pinch: function (tracks: TrackItem[], event: ZRRawTouchEvent) {
          const trackLen = tracks.length;
  
          if (!trackLen) {
              return;
          }
  
          const pinchEnd = (tracks[trackLen - 1] || {}).points;
          const pinchPre = (tracks[trackLen - 2] || {}).points || pinchEnd;
  
          if (pinchPre
              && pinchPre.length > 1
              && pinchEnd
              && pinchEnd.length > 1
          ) {
              let pinchScale = dist(pinchEnd) / dist(pinchPre);
              !isFinite(pinchScale) && (pinchScale = 1);
  
              (event as ZRPinchEvent).pinchScale = pinchScale;
  
              const pinchCenter = center(pinchEnd);
              (event as ZRPinchEvent).pinchX = pinchCenter[0];
              (event as ZRPinchEvent).pinchY = pinchCenter[1];
  
              return {
                  type: 'pinch',
                  target: tracks[0].target,
                  event: event
              };
          }
      }
  
      // Only pinch currently.
  };