├── src
├── finger.js
└── util.js
├── .gitignore
├── package.json
├── README.md
└── index.js
/src/finger.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
--------------------------------------------------------------------------------
/src/util.js:
--------------------------------------------------------------------------------
1 | var hashGen = function(){
2 | return Math.random().toString(36).substr(2, 5)
3 | }
4 | module.exports = {
5 | hashGen:hashGen
6 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-finger",
3 | "version": "0.1.0",
4 | "description": "Vue plugin for supporting touch gesture",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/Muxi-Studio/vue-finger.git"
12 | },
13 | "keywords": [
14 | "vuejs"
15 | ],
16 | "author": "Muxi FE Team",
17 | "license": "MIT",
18 | "bugs": {
19 | "url": "https://github.com/Muxi-Studio/vue-finger/issues"
20 | },
21 | "homepage": "https://github.com/Muxi-Studio/vue-finger#readme"
22 | }
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-finger
2 |
3 | Vue plugin for supporting touch gesture. Support Vue 2.0+.
4 |
5 | Gesture supported:
6 |
7 | + Swipe
8 | + SwipeMove
9 | + Pinch
10 | + Tap
11 | + Double Tap
12 |
13 |
14 | ### Install
15 |
16 | ```
17 | npm install vue-finger --save
18 | ```
19 |
20 | ### Usage
21 |
22 | ```
23 | import vueFinger from "vue-finger"
24 |
25 | Vue.use(vueFinger)
26 |
27 | ```
28 |
29 | in your component
30 |
31 | ```
32 |
33 |
34 | swipe!
35 |
36 |
37 |
38 |
39 |
48 |
49 | ```
50 |
51 |
52 | ### Event
53 |
54 | #### Swipe
55 |
56 | `e.direction`
57 |
58 | the direction of the swipe: "Left", "Right", "Up", "Down".
59 |
60 | `e.deltaX`
61 |
62 | the delta on X axis of the whole swipe.
63 |
64 | `e.deltaY`
65 |
66 | the delta on Y axis of the whole swipe.
67 |
68 | #### SwipeMove
69 |
70 | `e.direction`
71 |
72 | the direction of the swipe: "Left", "Right", "Up", "Down".
73 |
74 | `e.distenceX`
75 |
76 | the cumulate distence on X axis of the swipe.
77 |
78 | `e.distenceY`
79 |
80 | the cumulate distence on Y axis of the swipe.
81 |
82 | #### Pinch
83 |
84 | `e.customScale`
85 |
86 | the difference value between latest scale and last scale
87 |
88 | #### Tap
89 |
90 | no custom event props
91 |
92 | #### doubleTap
93 |
94 | no custom event props
95 |
96 |
97 | ### Contributors
98 |
99 | + [zxc0328](https://github.com/zxc0328)
100 | + [Elegenthus](https://github.com/Elegenthus)
101 |
102 | ### Lisence
103 |
104 | DWTFYW
105 |
106 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var util = require("./src/util.js")
2 |
3 | var vueFingerConstructor = function(el, options) {
4 | this.el = el
5 | // add touch event
6 | this.startCallback = this.start.bind(this)
7 | this.moveCallback = this.move.bind(this)
8 | this.endCallback = this.end.bind(this)
9 | this.cancelCallback = this.cancel.bind(this)
10 |
11 |
12 | this.el.addEventListener("touchstart", this.startCallback, false)
13 | this.el.addEventListener("touchmove", this.moveCallback, false)
14 | this.el.addEventListener("touchend", this.endCallback, false)
15 | this.el.addEventListener("touchcancel", this.cancelCallback, false)
16 |
17 | // init
18 | this.x1 = this.x2 = this.y1 = this.y2 = null
19 | this.swipe = options.swipe
20 | this.swipeMove = options.swipeMove
21 | this.pintch = options.pintch
22 | this.tap = options.tap
23 | this.doubleTap = options.doubleTap
24 | this.pintchDistance = 400
25 | this.tapTimeout
26 | this.mutiTouchWating = true
27 | this.swipeMoveTimeout
28 | this.doubleTapTimeout
29 | // scale
30 | }
31 |
32 | vueFingerConstructor.prototype = {
33 | start: function(e) {
34 | var self = this
35 | console.log("start")
36 | // reset
37 | this.x1 = this.x2 = this.y1 = this.y2 = null
38 |
39 | e.preventDefault()
40 | if (!e.touches) return
41 | this.x1 = e.touches[0].pageX
42 | this.y1 = e.touches[0].pageY
43 | if(e.touches.length > 1){
44 | this.mutiTouchWating = false
45 | this.p1 = e.touches[1].pageX
46 | this.q1 = e.touches[1].pageY
47 | this.pintchDistance1 = Math.sqrt(Math.pow((this.x1-this.p1),2) + Math.pow((this.y1-this.q1),2))
48 | }
49 |
50 | this.previous = {
51 | x1: this.x1,
52 | y1: this.y1
53 | }
54 | e.distanceX = 0
55 | e.distanceY = 0
56 |
57 | // set tap timout
58 | if (this.tap) {
59 | if (e.target !== this.el) {
60 | this.tapTimeout =
61 | setTimeout(this.tap.bind({}, e, Array.prototype.slice.call(this.el.childNodes).indexOf(e.target)),200)
62 | }else {
63 | this.tapTimeout = setTimeout(function(){
64 | if (!self.doubleTapTimeout) {
65 | console.log(self.tap)
66 | self.tap()
67 | }
68 | },200)
69 | }
70 | }
71 |
72 | this.mutiTouchWating = true
73 | setTimeout(function(){
74 | self.mutiTouchWating = false
75 | },40)
76 |
77 | if (this.doubleTap && (e.touches.length == 1)) {
78 | if (this.doubleTapTimeout){
79 | this.doubleTap()
80 | this.doubleTapTimeout = null
81 | }else{
82 | this.doubleTapTimeout = setTimeout(function(){
83 | this.doubleTapTimeout = null
84 | },100)
85 | }
86 | }
87 | },
88 | move: function(e) {
89 | e.preventDefault()
90 | if (this.tapTimeout) {
91 | clearTimeout(this.tapTimeout)
92 | this.tapTimeout = null
93 | }
94 | if (this.doubleTapTimeout) {
95 | clearTimeout(this.doubleTapTimeout)
96 | this.doubleTapTimeout = null
97 | }
98 |
99 | var currentX = e.touches[0].pageX,
100 | currentY = e.touches[0].pageY;
101 |
102 | if(e.touches.length > 1){
103 | var currentP = e.touches[1].pageX,
104 | currentQ = e.touches[1].pageY;
105 | this.p2 = currentP
106 | this.q2 = currentQ
107 | }
108 |
109 | this.x2 = currentX
110 | this.y2 = currentY
111 |
112 | e.distanceX = this.x2 - this.x1
113 | e.distanceY = this.y2 - this.y1
114 | if(e.touches.length > 1){
115 | this.pintchDistance2 = Math.sqrt(Math.pow((this.x2 - this.p2),2) + Math.pow((this.y2 - this.q2),2))
116 | //alert(this.pintchDistance2,this.pintchDistance1)
117 | e.customscale = (this.pintchDistance2 - this.pintchDistance1)/this.pintchDistance
118 | if (this.pintch) {
119 | this.pintch(e)
120 | }
121 | }
122 |
123 |
124 |
125 | e.deltaX = currentX - this.previous.x1
126 | e.deltaY = currentY - this.previous.y1
127 |
128 | this.previous = {
129 | x1: currentX,
130 | y1: currentY,
131 | p1: currentP,
132 | q1: currentQ
133 | }
134 |
135 | if ((currentX && Math.abs(e.distanceX) > 30) ||
136 | (currentY && Math.abs(e.distanceY) > 30)) {
137 | e.direction = this._swipeDirection(this.x1, this.x2, this.y1, this.y2);
138 | if (this.swipeMove && (e.touches.length == 1) && !this.mutiTouchWating) this.swipeMove(e)
139 | }
140 | },
141 | end: function(e) {
142 |
143 |
144 | e.preventDefault()
145 | if ((this.x2 && Math.abs(this.x1 - this.x2) > 30) ||
146 | (this.y2 && Math.abs(this.y1 - this.y2) > 30)) {
147 | e.direction = this._swipeDirection(this.x1, this.x2, this.y1, this.y2);
148 | e.distanceX = this.x2 - this.x1
149 | e.distanceY = this.y2 - this.y1
150 | if (this.swipe) this.swipe(e)
151 | }
152 | },
153 | cancel: function() {
154 |
155 | },
156 | detach: function() {
157 | // remove touch event
158 | this.el.removeEventListener("touchstart", this.startCallback, false)
159 | this.el.removeEventListener("touchmove", this.moveCallback, false)
160 | this.el.removeEventListener("touchend", this.endCallback, false)
161 | this.el.removeEventListener("touchcancel", this.cancelCallback, false)
162 | },
163 | _swipeDirection: function(x1, x2, y1, y2) {
164 | return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')
165 | }
166 | }
167 |
168 | var instancesHash = {}
169 | var vueFinger = {}
170 |
171 | vueFinger.install = function(Vue, options) {
172 |
173 | Vue.directive('finger', {
174 | bind: function(el, binding, vnode, oldVnode) {
175 | if (!el.dataset.vfingerId) {
176 | el.dataset.vfingerId = util.hashGen()
177 | var options = {}
178 | options[binding.arg] = binding.value
179 | var ins = new vueFingerConstructor(el, options)
180 | instancesHash[el.dataset.vfingerId] = ins
181 | }else {
182 | instancesHash[el.dataset.vfingerId][binding.arg] = binding.value
183 | }
184 | },
185 | unbind: function(el) {
186 | var ins = instancesHash[el.dataset.vfingerId]
187 | ins.detach()
188 | ins = null
189 | }
190 | })
191 |
192 | }
193 |
194 | module.exports = vueFinger
195 |
--------------------------------------------------------------------------------