以与 mousedown/mousemove/mouseup 相同的方式处理 touchstart/touchmove/touchend
Handling touchstart/touchmove/touchend the same way as mousedown/mousemove/mouseup
我正在尝试在我的应用程序中添加触摸和拖动功能,但到目前为止没有成功。
想法如下:
- 用户触摸一个元素来激活它
- 他将手指移过元素的兄弟元素以同时激活它们
- 如果他移开手指,所有元素都将停用
我可以让它完美地处理鼠标事件,但触摸事件的工作方式似乎不同。我认为这是因为一旦触发了 touchstart,其他触摸事件就会绑定到相同的初始目标。在这里打磨我的装备的是 touchend 可以绑定到父元素并且可以工作...
这是一个示例代码。你可以看到它在鼠标事件上按预期工作,但如果你模拟触摸,它就不再工作了。
Vue.component('to-press', {
template: `<span class="col-3 p-2 bg-light border" :class="{ 'bg-dark': isActive }" @mousedown="emitPanMode()" @touchstart="emitPanMode()" @mousemove="setActive()" @touchmove="setActive()"> </span>`,
props: ['isPan'],
data() {
return {
isActive: false,
}
},
methods: {
emitPanMode() {
this.isActive = true;
this.$emit('on-pan');
},
setActive() {
this.isActive = this.isPan;
}
},
watch: {
isPan(val) {
if (!val) {
this.isActive = false;
}
}
}
})
const app = new Vue({
el: "#app",
data() {
return {
panMode: false,
};
},
methods: {
togglePanMode(val) {
this.panMode = val;
}
}
})
* {
-webkit-touch-callout: none;
/* iOS Safari */
-webkit-user-select: none;
/* Safari */
-khtml-user-select: none;
/* Konqueror HTML */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* Internet Explorer/Edge */
user-select: none;
/* Non-prefixed version, currently
supported by Chrome and Opera */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div id="app" class="container py-4" @mouseup="togglePanMode(false)" @touchend="togglePanMode(false)">
<div class="row">
<to-press v-for="i of 12" :key="i" @on-pan="togglePanMode(true)" :is-pan="panMode" />
</div>
<p>Click/touch a rectangle, hold and drag accross</p>
</div>
任何关于如何以与鼠标相同的方式处理触摸的见解?有什么我想念的吗?
看来我们必须从父组件处理touchmove
。
看这个例子
Vue.component('to-press', {
template: `<span class="col-3 p-2 bg-light border" :class="{ 'bg-dark': isActive }" @mousedown="emitPanMode()" @touchstart="emitPanMode()" @mousemove="setActive()" @touchmove="setActive()"> </span>`,
props: ['isPan'],
data() {
return {
isActive: false,
}
},
methods: {
emitPanMode() {
this.isActive = true;
this.$emit('on-pan');
},
setActive() {
this.isActive = this.isPan;
}
},
watch: {
isPan(val) {
if (!val) {
this.isActive = false;
}
}
}
})
const app = new Vue({
el: "#app",
data() {
return {
panMode: false,
};
},
methods: {
togglePanMode(val) {
this.panMode = val;
},
move(e) {
let p = e.touches[0];
let el = document.elementFromPoint(p.clientX, p.clientY);
let cmp = this.$children.find(c => c.$el === el);
if (cmp) {
cmp.setActive()
}
}
}
})
* {
-webkit-touch-callout: none;
/* iOS Safari */
-webkit-user-select: none;
/* Safari */
-khtml-user-select: none;
/* Konqueror HTML */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* Internet Explorer/Edge */
user-select: none;
/* Non-prefixed version, currently supported by Chrome and Opera */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div id="app" class="container py-4" @mouseup="togglePanMode(false)" @touchend="togglePanMode(false)" @touchmove.passive="move">
<div class="row">
<to-press v-for="i of 12" :key="i" @on-pan="togglePanMode(true)" :is-pan="panMode" />
</div>
<p>Click/touch a rectangle, hold and drag accross</p>
</div>
我正在尝试在我的应用程序中添加触摸和拖动功能,但到目前为止没有成功。
想法如下:
- 用户触摸一个元素来激活它
- 他将手指移过元素的兄弟元素以同时激活它们
- 如果他移开手指,所有元素都将停用
我可以让它完美地处理鼠标事件,但触摸事件的工作方式似乎不同。我认为这是因为一旦触发了 touchstart,其他触摸事件就会绑定到相同的初始目标。在这里打磨我的装备的是 touchend 可以绑定到父元素并且可以工作...
这是一个示例代码。你可以看到它在鼠标事件上按预期工作,但如果你模拟触摸,它就不再工作了。
Vue.component('to-press', {
template: `<span class="col-3 p-2 bg-light border" :class="{ 'bg-dark': isActive }" @mousedown="emitPanMode()" @touchstart="emitPanMode()" @mousemove="setActive()" @touchmove="setActive()"> </span>`,
props: ['isPan'],
data() {
return {
isActive: false,
}
},
methods: {
emitPanMode() {
this.isActive = true;
this.$emit('on-pan');
},
setActive() {
this.isActive = this.isPan;
}
},
watch: {
isPan(val) {
if (!val) {
this.isActive = false;
}
}
}
})
const app = new Vue({
el: "#app",
data() {
return {
panMode: false,
};
},
methods: {
togglePanMode(val) {
this.panMode = val;
}
}
})
* {
-webkit-touch-callout: none;
/* iOS Safari */
-webkit-user-select: none;
/* Safari */
-khtml-user-select: none;
/* Konqueror HTML */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* Internet Explorer/Edge */
user-select: none;
/* Non-prefixed version, currently
supported by Chrome and Opera */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div id="app" class="container py-4" @mouseup="togglePanMode(false)" @touchend="togglePanMode(false)">
<div class="row">
<to-press v-for="i of 12" :key="i" @on-pan="togglePanMode(true)" :is-pan="panMode" />
</div>
<p>Click/touch a rectangle, hold and drag accross</p>
</div>
任何关于如何以与鼠标相同的方式处理触摸的见解?有什么我想念的吗?
看来我们必须从父组件处理touchmove
。
看这个例子
Vue.component('to-press', {
template: `<span class="col-3 p-2 bg-light border" :class="{ 'bg-dark': isActive }" @mousedown="emitPanMode()" @touchstart="emitPanMode()" @mousemove="setActive()" @touchmove="setActive()"> </span>`,
props: ['isPan'],
data() {
return {
isActive: false,
}
},
methods: {
emitPanMode() {
this.isActive = true;
this.$emit('on-pan');
},
setActive() {
this.isActive = this.isPan;
}
},
watch: {
isPan(val) {
if (!val) {
this.isActive = false;
}
}
}
})
const app = new Vue({
el: "#app",
data() {
return {
panMode: false,
};
},
methods: {
togglePanMode(val) {
this.panMode = val;
},
move(e) {
let p = e.touches[0];
let el = document.elementFromPoint(p.clientX, p.clientY);
let cmp = this.$children.find(c => c.$el === el);
if (cmp) {
cmp.setActive()
}
}
}
})
* {
-webkit-touch-callout: none;
/* iOS Safari */
-webkit-user-select: none;
/* Safari */
-khtml-user-select: none;
/* Konqueror HTML */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* Internet Explorer/Edge */
user-select: none;
/* Non-prefixed version, currently supported by Chrome and Opera */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div id="app" class="container py-4" @mouseup="togglePanMode(false)" @touchend="togglePanMode(false)" @touchmove.passive="move">
<div class="row">
<to-press v-for="i of 12" :key="i" @on-pan="togglePanMode(true)" :is-pan="panMode" />
</div>
<p>Click/touch a rectangle, hold and drag accross</p>
</div>