Skip to content

Commit 3f95aaa

Browse files
committed
feat: "touch-pan" and "touch-swipe" directives - dropping Hammerjs and Vue-Touch soon
1 parent 6c9f85d commit 3f95aaa

File tree

5 files changed

+348
-0
lines changed

5 files changed

+348
-0
lines changed

src/install.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import directiveGoBack from './vue-directives/go-back'
88
import directiveScrollFire from './vue-directives/scroll-fire'
99
import directiveScroll from './vue-directives/scroll'
1010
import directiveTooltip from './vue-directives/tooltip'
11+
import directiveTouchPan from './vue-directives/pan'
12+
import directiveTouchSwipe from './vue-directives/swipe'
1113

1214
import Checkbox from './vue-components/checkbox/checkbox.vue'
1315
import Chips from './vue-components/chips/chips.vue'
@@ -61,6 +63,8 @@ function registerDirectives (_Vue) {
6163
_Vue.directive('scroll-fire', directiveScrollFire)
6264
_Vue.directive('scroll', directiveScroll)
6365
_Vue.directive('tooltip', directiveTooltip)
66+
_Vue.directive('touch-pan', directiveTouchPan)
67+
_Vue.directive('touch-swipe', directiveTouchSwipe)
6468
}
6569

6670
function registerComponents (_Vue) {

src/themes/core/touch.styl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.quasar-touch
2+
user-select none
3+
user-drag none
4+
-khtml-user-drag none
5+
-webkit-user-drag none
6+
.quasar-touch-x
7+
touch-action pan-x
8+
.quasar-touch-y
9+
touch-action pan-y

src/utils/event.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ export function position (e) {
2222
if (e.touches && e.touches[0]) {
2323
e = e.touches[0]
2424
}
25+
else if (e.changedTouches && e.changedTouches[0]) {
26+
e = e.changedTouches[0]
27+
}
2528

2629
if (e.clientX || e.clientY) {
2730
posx = e.clientX

src/vue-directives/touch-pan.js

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
import Utils from '../utils'
2+
3+
let
4+
data = {}
5+
6+
function getDirection (el, mod) {
7+
if (Object.keys(mod).length === 0) {
8+
return {
9+
horizontal: true,
10+
vertical: true
11+
}
12+
}
13+
14+
let dir = {}
15+
16+
;['horizontal', 'vertical'].forEach(direction => {
17+
if (mod[direction]) {
18+
dir[direction] = true
19+
}
20+
})
21+
22+
return dir
23+
}
24+
25+
function updateClasses (el, dir) {
26+
el.classList.add('quasar-touch')
27+
28+
if (dir.horizontal && !dir.vertical) {
29+
el.classList.add('quasar-touch-y')
30+
el.classList.remove('quasar-touch-x')
31+
}
32+
else if (!dir.horizontal && dir.vertical) {
33+
el.classList.add('quasar-touch-x')
34+
el.classList.remove('quasar-touch-y')
35+
}
36+
}
37+
38+
function processChanges (evt, ctx, isFinal) {
39+
let
40+
direction,
41+
position = Utils.event.position(evt),
42+
distX = position.left - ctx.event.x,
43+
distY = position.top - ctx.event.y,
44+
absDistX = Math.abs(distX),
45+
absDistY = Math.abs(distY)
46+
47+
if (ctx.direction.horizontal && !ctx.direction.vertical) {
48+
direction = distX < 0 ? 'left' : 'right'
49+
}
50+
else if (!ctx.direction.horizontal && ctx.direction.vertical) {
51+
direction = distY < 0 ? 'up' : 'down'
52+
}
53+
else if (absDistX >= absDistY) {
54+
direction = distX < 0 ? 'left' : 'right'
55+
}
56+
else {
57+
direction = distY < 0 ? 'up' : 'down'
58+
}
59+
60+
return {
61+
evt,
62+
position,
63+
direction,
64+
isFirst: ctx.event.isFirst,
65+
isFinal: Boolean(isFinal),
66+
duration: new Date().getTime() - ctx.event.time,
67+
distance: {
68+
x: absDistX,
69+
y: absDistY
70+
},
71+
delta: {
72+
x: position.left - ctx.event.lastX,
73+
y: position.top - ctx.event.lastY
74+
}
75+
}
76+
}
77+
78+
function shouldTrigger (ctx, changes) {
79+
if (ctx.direction.horizontal && ctx.direction.vertical) {
80+
return true
81+
}
82+
if (ctx.direction.horizontal && !ctx.direction.vertical) {
83+
return Math.abs(changes.delta.x) > 0
84+
}
85+
if (!ctx.direction.horizontal && ctx.direction.vertical) {
86+
return Math.abs(changes.delta.y) > 0
87+
}
88+
}
89+
90+
export default {
91+
bind (el, binding) {
92+
let ctx = {
93+
handler: binding.value,
94+
direction: getDirection(el, binding.modifiers),
95+
96+
mouseStart (evt) {
97+
document.addEventListener('mousemove', ctx.mouseMove)
98+
document.addEventListener('mouseup', ctx.mouseEnd)
99+
ctx.start(evt)
100+
},
101+
start (evt) {
102+
let position = Utils.event.position(evt)
103+
ctx.event = {
104+
x: position.left,
105+
y: position.top,
106+
time: new Date().getTime(),
107+
detected: false,
108+
prevent: ctx.direction.horizontal && ctx.direction.vertical,
109+
isFirst: true,
110+
lastX: position.left,
111+
lastY: position.top
112+
}
113+
},
114+
mouseMove (evt) {
115+
ctx.event.prevent = true
116+
ctx.move(evt)
117+
},
118+
move (evt) {
119+
if (ctx.event.prevent) {
120+
evt.preventDefault()
121+
let changes = processChanges(evt, ctx, false)
122+
if (shouldTrigger(ctx, changes)) {
123+
ctx.handler(changes)
124+
ctx.event.lastX = changes.position.left
125+
ctx.event.lastY = changes.position.top
126+
ctx.event.isFirst = false
127+
}
128+
return
129+
}
130+
if (ctx.event.detected) {
131+
return
132+
}
133+
134+
ctx.event.detected = true
135+
let
136+
position = Utils.event.position(evt),
137+
distX = position.left - ctx.event.x,
138+
distY = position.top - ctx.event.y
139+
140+
if (ctx.direction.horizontal && !ctx.direction.vertical) {
141+
if (Math.abs(distX) > Math.abs(distY)) {
142+
evt.preventDefault()
143+
ctx.event.prevent = true
144+
}
145+
}
146+
else {
147+
if (Math.abs(distX) < Math.abs(distY)) {
148+
evt.preventDefault()
149+
ctx.event.prevent = true
150+
}
151+
}
152+
},
153+
mouseEnd (evt) {
154+
document.removeEventListener('mousemove', ctx.mouseMove)
155+
document.removeEventListener('mouseup', ctx.mouseEnd)
156+
ctx.end(evt)
157+
},
158+
end (evt) {
159+
if (!ctx.event.prevent || ctx.event.isFirst) {
160+
return
161+
}
162+
163+
ctx.handler(processChanges(evt, ctx, true))
164+
}
165+
}
166+
167+
data[el] = ctx
168+
updateClasses(el, ctx.direction)
169+
el.addEventListener('touchstart', ctx.start)
170+
el.addEventListener('mousedown', ctx.mouseStart)
171+
el.addEventListener('touchmove', ctx.move)
172+
el.addEventListener('touchend', ctx.end)
173+
},
174+
update (el, binding) {
175+
if (binding.oldValue !== binding.value) {
176+
data[el].handler = binding.value
177+
}
178+
},
179+
unbind (el, binding) {
180+
let ctx = data[el]
181+
el.removeEventListener('touchstart', ctx.start)
182+
el.removeEventListener('mousedown', ctx.mouseStart)
183+
el.removeEventListener('touchmove', ctx.move)
184+
el.removeEventListener('touchend', ctx.end)
185+
}
186+
}

src/vue-directives/touch-swipe.js

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import Utils from '../utils'
2+
3+
let data = {}
4+
5+
function getDirection (el, mod) {
6+
if (Object.keys(mod).length === 0) {
7+
return {
8+
left: true, right: true, up: true, down: true, horizontal: true, vertical: true
9+
}
10+
}
11+
12+
let dir = {}
13+
14+
;['left', 'right', 'up', 'down', 'horizontal', 'vertical'].forEach(direction => {
15+
if (mod[direction]) {
16+
dir[direction] = true
17+
}
18+
})
19+
if (dir.horizontal) {
20+
dir.left = dir.right = true
21+
}
22+
if (dir.vertical) {
23+
dir.up = dir.down = true
24+
}
25+
if (dir.left || dir.right) {
26+
dir.horizontal = true
27+
}
28+
if (dir.up || dir.down) {
29+
dir.vertical = true
30+
}
31+
32+
return dir
33+
}
34+
35+
function updateClasses (el, dir) {
36+
el.classList.add('quasar-touch')
37+
38+
if (dir.horizontal && !dir.vertical) {
39+
el.classList.add('quasar-touch-y')
40+
el.classList.remove('quasar-touch-x')
41+
}
42+
else if (!dir.horizontal && dir.vertical) {
43+
el.classList.add('quasar-touch-x')
44+
el.classList.remove('quasar-touch-y')
45+
}
46+
}
47+
48+
export default {
49+
bind (el, binding) {
50+
let ctx = {
51+
handler: binding.value,
52+
direction: getDirection(el, binding.modifiers),
53+
54+
start (evt) {
55+
let position = Utils.event.position(evt)
56+
ctx.event = {
57+
x: position.left,
58+
y: position.top,
59+
time: new Date().getTime(),
60+
detected: false,
61+
prevent: ctx.direction.horizontal && ctx.direction.vertical
62+
}
63+
document.addEventListener('mousemove', ctx.move)
64+
document.addEventListener('mouseup', ctx.end)
65+
},
66+
move (evt) {
67+
let
68+
position = Utils.event.position(evt),
69+
distX = position.left - ctx.event.x,
70+
distY = position.top - ctx.event.y
71+
72+
if (ctx.event.prevent) {
73+
evt.preventDefault()
74+
return
75+
}
76+
if (ctx.event.detected) {
77+
return
78+
}
79+
80+
ctx.event.detected = true
81+
if (ctx.direction.horizontal && !ctx.direction.vertical) {
82+
if (Math.abs(distX) > Math.abs(distY)) {
83+
evt.preventDefault()
84+
ctx.event.prevent = true
85+
}
86+
}
87+
else {
88+
if (Math.abs(distX) < Math.abs(distY)) {
89+
evt.preventDefault()
90+
ctx.event.prevent = true
91+
}
92+
}
93+
},
94+
end (evt) {
95+
document.removeEventListener('mousemove', ctx.move)
96+
document.removeEventListener('mouseup', ctx.end)
97+
98+
let
99+
direction,
100+
position = Utils.event.position(evt),
101+
distX = position.left - ctx.event.x,
102+
distY = position.top - ctx.event.y
103+
104+
if (distX !== 0 || distY !== 0) {
105+
if (Math.abs(distX) >= Math.abs(distY)) {
106+
direction = distX < 0 ? 'left' : 'right'
107+
}
108+
else {
109+
direction = distY < 0 ? 'up' : 'down'
110+
}
111+
112+
if (ctx.direction[direction]) {
113+
ctx.handler({
114+
evt,
115+
direction,
116+
duration: new Date().getTime() - ctx.event.time,
117+
distance: {
118+
x: Math.abs(distX),
119+
y: Math.abs(distY)
120+
}
121+
})
122+
}
123+
}
124+
}
125+
}
126+
127+
data[el] = ctx
128+
updateClasses(el, ctx.direction)
129+
el.addEventListener('touchstart', ctx.start)
130+
el.addEventListener('mousedown', ctx.start)
131+
el.addEventListener('touchmove', ctx.move)
132+
el.addEventListener('touchend', ctx.end)
133+
},
134+
update (el, binding) {
135+
if (binding.oldValue !== binding.value) {
136+
data[el].handler = binding.value
137+
}
138+
},
139+
unbind (el, binding) {
140+
let ctx = data[el]
141+
el.removeEventListener('touchstart', ctx.start)
142+
el.removeEventListener('mousedown', ctx.start)
143+
el.removeEventListener('touchmove', ctx.move)
144+
el.removeEventListener('touchend', ctx.end)
145+
}
146+
}

0 commit comments

Comments
 (0)