Touch.js
5.08 KB
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/**
* @name 下拉刷新
* @template new Touch("#app",{option}).then()
* @param {arguments[0]} String 非必填(建议填如id),下拉动态负载,默认body
* @param {option} Object 非必填
* @param {lazy} Number {lazy:100} 下拉响应惰性值默认 100
* @param {time} Number {time:1000} 数据防抖惰性值默认 1000
* @returns then Function xxx.then(arg=>arg) //下拉刷新后回掉
* @name vue页面注入
* @template { methods: {$$onTouch }}
*/
import Vue, { callHook } from "vue";
let setT, $event = new Vue();
class Touch {
constructor(id, opt = {}) {
this.main();
this.createElement(id);
this.generators = new Set();
this.next = null;
this.status = {};
this.opt = Object.assign({
lazy: 200,//下拉取惰性
time: 1000,//数据防抖动值
filter: []
}, opt)
return this;
}
main() {
this.options = {
start: 0,
move: 0,
end: 0,
isTrue: false,//是否拖动到有效值
}
}
then(fun) {
this.generators.add(fun);
return this;
}
createElement(id) {
const doc = (document.documentElement || document.body);
this.self = id ? document.querySelector(id) : doc;
this.parent = this.self == doc ? this.self : this.self.parentNode;
this.element = document.createElement("div");
Object.assign(this.element.style, {
"textAlign": "center", "height": "0", "transform": "translateY(50%)", "position": "fixed",
"top": "0", "left": "0", "width": "100%", "zIndex": "1", "overflow": "hidden"
})
this.arrow = document.createElement("span");
Object.assign(this.arrow.style, {
display: "inline-block",
borderRadius: "50%",
border: "#c00 solid 2px",
borderTop: "none",
width: "50px",
height: "50px",
transform: "translate3d(0,0,0),rotate(0deg)",
})
this.element.appendChild(this.arrow);
let first = this.parent.children[0];
this.parent.insertBefore(this.element, first);
this.addEvent();
}
//事件绑定
addEvent() {
window.addEventListener("touchstart", this.touchstart.bind(this), false);
window.addEventListener("touchmove", this.touchmove.bind(this), false);
window.addEventListener("touchend", this.touchend.bind(this), false)
}
scrollEvent(event) { }
touchstart(event) {
this.touchend();
let { pageX, pageY } = event.targetTouches[0];
if (this.parent.scrollTop <= 0) {
Object.assign(this.options, {
start: pageY,
touchs: true
})
}
}
touchmove(event) {
let { pageX, pageY } = event.targetTouches[0];
let path = location.hash.replace("#", "");
let check = this.opt.filter.filter(item => {
if (item.length > path.length) {
return item.includes(path)
} else {
return path.includes(item)
}
}).length;
if (!this.options.touchs || check) {
this.options.isTrue = false;
return
}
this.options.move = pageY;
let height = pageY - this.options.start;
if (height < 0) {
this.options.isTrue = false;
this.touchend();
return
}
if (height > this.opt.lazy) {
let _height = height - this.opt.lazy;
this.options.isTrue = true;
this.setTransform(_height);
}
//指针归位
this.next = this.generators.values();
}
touchend(event) {
this.setTransform(0); //位置复位
if (setT) { clearTimeout(setT) }
setT = setTimeout(() => {
if (
event && //用户事件
this.options.isTrue //有效拖动
) {
this.runNext(); //执行回掉
}
}, this.opt.time);
//复位
Object.assign(this.options, {
start: 0,
move: 0,
end: 0,
touchs: false
})
}
runNext(item = this.next, ...res) {
this.options.isTrue = false;
let next = item.next();
if (!next.done) {
let fun = next.value(res); //执行
if (/Promise/ig.test(Object.prototype.toString.call(fun))) {
fun.then((params) => {
this.runNext(item, params);
});//处理promise
} else {
this.runNext(item, fun);//处理普通事件
}
} else {
$event.$emit("$$onTouch", res);//发送事件给组件
//指针归位
this.next = this.generators.values();
}
}
setTransform(height) {
Object.assign(this.self.style, {
transform: height > 0 ? `translateY(${height}px)` : "none"
})
Object.assign(this.element.style, {
height: height >= 100 ? "100px" : "0.1px"
// height:height+"px"
})
Object.assign(this.arrow.style, {
transform: `rotate(${height}deg)`
})
}
}
const listeners = {}
$event.$on("$$onTouch", (arg) => {
for (const key in listeners) {
listeners[key](arg)
}
})
export function install(vue, options) {
vue.mixin({
mounted() {
this.refreshInit && (listeners[this._uid] = this.refreshInit)
},
activated() {
this.refreshInit && (listeners[this._uid] = this.refreshInit)
},
destroyed() {
delete listeners[this._uid]
},
deactivated() {
delete listeners[this._uid]
},
})
}
Vue.use(install)
export default Touch;