UNPKG

4.78 kBJavaScriptView Raw
1
2!function(Event, document) {
3 var firstEl, lastDist, lastAngle, pinchThreshhold, mode
4 , TOUCH_FLAG = "-tf"
5 , MOVE = "pointermove"
6 , START = "start"
7 , END = "end"
8 , MS_WHICH = [0, 1, 4, 2]
9 , fixEv = Event.fixEv
10 , fixFn = Event.fixFn
11 , pointers = []
12 , firstPos = {}
13
14 // tap
15 // swipe + left/right/up/down
16
17 "pan pinch rotate".split(" ").map(function(name) {
18 fixEv[name] = fixEv[name + START] = fixEv[name + END] = ""
19 fixFn[name] = setup
20 })
21
22 function down(e, e2) {
23 var len = e ? pointers.push(e) : pointers.length
24 firstPos.cancel = false
25
26 if (len === 0) {
27 if (mode) {
28 El.emit(firstEl, mode + END, e2, firstPos, firstEl)
29 mode = null
30 }
31 firstEl = null
32 }
33 if (len === 1) {
34 if (e) {
35 firstEl = e.currentTarget || e.target
36 if (El.matches(e.target, "INPUT,TEXTAREA,SELECT,.no-drag")) return
37 } else {
38 e = pointers[0]
39 }
40 firstPos.X = e.clientX
41 firstPos.Y = e.clientY
42 savePos("left", "offsetWidth")
43 savePos("top", "offsetHeight")
44 moveOne(e)
45 }
46 if (len === 2) {
47 pinchThreshhold = firstEl.clientWidth / 10
48 lastDist = lastAngle = null
49 moveTwo(e)
50 }
51 El[len === 1 ? "on" : "off"](document, MOVE, moveOne)
52 El[len === 2 ? "on" : "off"](document, MOVE, moveTwo)
53 return Event.stop(e)
54 }
55
56 function moveOne(e) {
57 // In IE9 mousedown.buttons is OK but mousemove.buttons == 0
58 if (pointers[0].buttons && pointers[0].buttons !== (e.buttons || MS_WHICH[e.which || 0])) {
59 return up(e)
60 }
61 firstPos.leftPos = e.clientX - firstPos.X + firstPos.left
62 firstPos.topPos = e.clientY - firstPos.Y + firstPos.top
63 if (!mode) {
64 mode = "pan"
65 El.emit(firstEl, mode + START, e, firstPos, firstEl)
66 }
67 El.emit(firstEl, "pan", e, firstPos, firstEl)
68 if (!firstPos.cancel) {
69 if (firstEl.getBBox) {
70 firstEl.setAttributeNS(null, "x", firstPos.leftPos)
71 firstEl.setAttributeNS(null, "y", firstPos.topPos)
72 } else {
73 firstEl.style.left = firstPos.leftPos + "px"
74 firstEl.style.top = firstPos.topPos + "px"
75 }
76 }
77 }
78
79 function moveTwo(e) {
80 pointers[ pointers[0].pointerId == e.pointerId ? 0 : 1] = e
81 var diff
82 , x = firstPos.X - pointers[1].clientX
83 , y = firstPos.Y - pointers[1].clientY
84 , dist = Math.sqrt(x*x + y*y) | 0
85 , angle = Math.atan2(y, x)
86
87 if (lastDist !== null) {
88 diff = dist - lastDist
89 if (diff) El.emit(firstEl, "pinch", e, diff, angle)
90 // GestureEvent onGestureChange: function(e) {
91 // e.target.style.transform =
92 // 'scale(' + e.scale + startScale + ') rotate(' + e.rotation + startRotation + 'deg)'
93 diff = angle - lastAngle
94 if (diff) El.emit(firstEl, "rotate", e, diff * (180/Math.PI))
95 }
96
97 lastDist = dist
98 lastAngle = angle
99 }
100
101 function wheel(e, diff) {
102 // IE10 enabled pinch-to-zoom gestures from multi-touch trackpad’s as mousewheel event with ctrlKey.
103 // Chrome adapted this in Chrome M35 and Mozilla followed up with Firefox 55.
104 if (e.ctrlKey && !pointers[0]) {
105 if (El.emit(e.currentTarget || e.target, "pinch", e, diff, 0)) {
106 return Event.stop(e)
107 }
108 }
109 }
110
111 function up(e) {
112 for (var i = pointers.length; i--; ) {
113 if (pointers[i].pointerId == e.pointerId) {
114 pointers.splice(i, 1)
115 break
116 }
117 }
118 down(null, e)
119 }
120
121 function savePos(name, offset) {
122 var val = (
123 firstEl.getBBox ?
124 firstEl.getAttributeNS(null, name == "top" ? "y":"x") :
125 firstEl.style[name]
126 )
127 firstPos[name] = parseInt(val, 10) || 0
128 if (val && val.indexOf("%") > -1) {
129 firstPos[name] *= firstEl.parentNode[offset] / 100
130 }
131 }
132
133 function setup(el) {
134 if (!el[TOUCH_FLAG]) {
135 el.style.touchAction = el.style.msTouchAction = "none"
136 El.on(el, "pointerdown", down)
137 El.on(el, "pointerup pointercancel", up)
138 El.on(el, "wheel", wheel)
139 el[TOUCH_FLAG] = 1
140 }
141 }
142
143 /*
144 .
145 https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent
146 https://developer.apple.com/ios/3d-touch/
147 https://developer.mozilla.org/en-US/docs/Web/API/Force_Touch_events
148 https://github.com/stuyam/pressure/
149 // should be either "stylus" or "direct"
150 console.log(evt.touches[0].touchType)
151 stylus (Apple Pencil) or direct (finger)
152 iOS 10 + Safari + Apple Pencil
153 You can check the touch force with:
154 e.touches[0].force;
155 But it works also for 3DTouch on iPhone 6s.
156 Only Apple Pencil events and touches events on iPhone 6s have .force
157 This is hacky, but checking for
158 var isiPad = (navigator.userAgent.match(/iPad/i) != null);
159 and the existence of force on the touch event
160 seems to be the only way to tell whether it's the Apple Pencil.
161 supportsTouch = 'ontouchstart' in window.document && supportsTouchForce;
162 supportsMouse = 'onmousemove' in window.document && !supportsTouch;
163 supportsPointer = 'onpointermove' in window.document;
164 supportsTouchForceChange = 'ontouchforcechange' in window.document;
165 */
166}(Event, document)
167
168