[Improvement] add touch mixin (#869)

This commit is contained in:
neverland 2018-04-13 15:26:41 +08:00 committed by GitHub
parent 7285632c35
commit bd80fe4e05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 66 additions and 100 deletions

View File

@ -23,12 +23,15 @@
<script>
import create from '../utils/create';
import Clickoutside from '../utils/clickoutside';
import Touch from '../mixins/touch';
const THRESHOLD = 0.15;
export default create({
name: 'cell-swipe',
mixins: [Touch],
props: {
onClose: Function,
leftWidth: {
@ -96,9 +99,7 @@ export default create({
startDrag(event) {
this.draging = true;
this.direction = '';
this.startX = event.touches[0].clientX;
this.startY = event.touches[0].clientY;
this.touchStart(event);
if (this.opened) {
this.startX -= this.offset;
@ -106,24 +107,17 @@ export default create({
},
onDrag(event) {
const offsetTop = event.touches[0].clientY - this.startY;
const offsetLeft = event.touches[0].clientX - this.startX;
this.touchMove(event);
const { deltaX } = this;
if ((offsetLeft < 0 && -offsetLeft > this.rightWidth) ||
(offsetLeft > 0 && offsetLeft > this.leftWidth) ||
(offsetLeft > 0 && !this.leftWidth) ||
(offsetLeft < 0 && !this.rightWidth)) {
if ((deltaX < 0 && (-deltaX > this.rightWidth || !this.rightWidth)) ||
(deltaX > 0 && (deltaX > this.leftWidth || deltaX > 0 && !this.leftWidth))) {
return;
}
const y = Math.abs(offsetTop);
const x = Math.abs(offsetLeft);
const swiping = !(x < 5 || (x >= 5 && y >= x * 1.73));
this.direction = this.direction || this.getDirection(event.touches[0]);
if (swiping && this.direction === 'horizontal') {
if (this.direction === 'horizontal') {
event.preventDefault();
this.swipeMove(offsetLeft);
this.swipeMove(deltaX);
};
},
@ -134,12 +128,6 @@ export default create({
};
},
getDirection(touch) {
const offsetX = Math.abs(touch.clientX - this.startX);
const offsetY = Math.abs(touch.clientY - this.startY);
return offsetX > offsetY ? 'horizontal' : offsetX < offsetY ? 'vertical' : '';
},
onClick(position = 'outside') {
if (!this.offset) {
return;

View File

@ -3,7 +3,7 @@
v-show="value"
class="van-image-preview"
@touchstart="onTouchStart"
@touchmove="onTouchMove"
@touchmove.prevent="touchMove"
@touchend="onTouchEnd"
@touchcancel="onTouchEnd"
>
@ -20,11 +20,12 @@ import create from '../utils/create';
import Popup from '../mixins/popup';
import Swipe from '../swipe';
import SwipeItem from '../swipe-item';
import Touch from '../mixins/touch';
export default create({
name: 'image-preview',
mixins: [Popup],
mixins: [Popup, Touch],
components: {
Swipe,
@ -52,23 +53,14 @@ export default create({
methods: {
onTouchStart(event) {
this.touchStartTime = new Date();
this.touchStartX = event.touches[0].clientX;
this.touchStartY = event.touches[0].clientY;
this.deltaX = 0;
this.deltaY = 0;
},
onTouchMove(event) {
event.preventDefault();
this.deltaX = event.touches[0].clientX - this.touchStartX;
this.deltaY = event.touches[0].clientY - this.touchStartY;
this.touchStart(event);
},
onTouchEnd(event) {
event.preventDefault();
// prevent long tap to close component
const deltaTime = new Date() - this.touchStartTime;
if (deltaTime < 100 && Math.abs(this.deltaX) < 20 && Math.abs(this.deltaY) < 20) {
if (deltaTime < 100 && this.offsetX < 20 && this.offsetY < 20) {
this.$emit('input', false);
}
}

View File

@ -2,8 +2,11 @@ import manager from './manager';
import context from './context';
import scrollUtils from '../../utils/scroll';
import { on, off } from '../../utils/event';
import Touch from '../touch';
export default {
mixins: [Touch],
props: {
// whether to show popup
value: Boolean,
@ -42,10 +45,6 @@ export default {
created() {
this._popupId = 'popup-' + context.plusKey('id');
this.pos = {
x: 0,
y: 0
};
},
mounted() {
@ -107,7 +106,7 @@ export default {
context.lockCount--;
if (!context.lockCount) {
document.body.classList.remove('van-overflow-hidden');
off(document, 'touchstart', this.onTouchStart);
off(document, 'touchstart', this.touchStart);
off(document, 'touchmove', this.onTouchMove);
}
}
@ -126,21 +125,11 @@ export default {
}
},
onTouchStart(e) {
this.pos = {
x: e.touches[0].clientX,
y: e.touches[0].clientY
};
},
onTouchMove(e) {
const { pos } = this;
const dx = e.touches[0].clientX - pos.x;
const dy = e.touches[0].clientY - pos.y;
const direction = dy > 0 ? '10' : '01';
this.touchMove(e);
const direction = this.deltaY > 0 ? '10' : '01';
const el = scrollUtils.getScrollEventTarget(e.target, this.$el);
const { scrollHeight, offsetHeight, scrollTop } = el;
const isVertical = Math.abs(dx) < Math.abs(dy);
let status = '11';
@ -154,7 +143,7 @@ export default {
/* istanbul ignore next */
if (
status !== '11' &&
isVertical &&
this.direction === 'vertical' &&
!(parseInt(status, 2) & parseInt(direction, 2))
) {
e.preventDefault();

25
packages/mixins/touch.js Normal file
View File

@ -0,0 +1,25 @@
export default {
methods: {
touchStart(event) {
this.direction = '';
this.deltaX = 0;
this.deltaY = 0;
this.offsetX = 0;
this.offsetY = 0;
this.startX = event.touches[0].clientX;
this.startY = event.touches[0].clientY;
},
touchMove(event) {
const touch = event.touches[0];
this.deltaX = touch.clientX - this.startX;
this.deltaY = touch.clientY - this.startY;
this.offsetX = Math.abs(this.deltaX);
this.offsetY = Math.abs(this.deltaY);
if (!this.direction) {
this.direction = this.offsetX > this.offsetY ? 'horizontal' : this.offsetX < this.offsetY ? 'vertical' : '';
}
}
}
};

View File

@ -31,10 +31,13 @@
<script>
import create from '../utils/create';
import scrollUtils from '../utils/scroll';
import Touch from '../mixins/touch';
export default create({
name: 'pull-refresh',
mixins: [Touch],
props: {
pullingText: String,
loosingText: String,
@ -88,8 +91,7 @@ export default create({
}
if (this.getCeiling()) {
this.duration = 0;
this.startX = event.touches[0].clientX;
this.startY = event.touches[0].clientY;
this.touchStart(event);
}
},
@ -98,8 +100,7 @@ export default create({
return;
}
this.deltaY = event.touches[0].clientY - this.startY;
this.direction = this.getDirection(event.touches[0]);
this.touchMove(event);
if (!this.ceiling && this.getCeiling()) {
this.duration = 0;
@ -157,12 +158,6 @@ export default create({
if (status !== this.status) {
this.status = status;
}
},
getDirection(touch) {
const distanceX = Math.abs(touch.clientX - this.startX);
const distanceY = Math.abs(touch.clientY - this.startY);
return distanceX > distanceY ? 'horizontal' : distanceX < distanceY ? 'vertical' : '';
}
}
});

View File

@ -23,10 +23,13 @@
<script>
import create from '../utils/create';
import Touch from '../mixins/touch';
export default create({
name: 'swipe',
mixins: [Touch],
props: {
autoplay: Number,
loop: {
@ -121,11 +124,8 @@ export default create({
onTouchStart(event) {
clearTimeout(this.timer);
this.deltaX = 0;
this.direction = '';
this.currentDuration = 0;
this.startX = event.touches[0].clientX;
this.startY = event.touches[0].clientY;
this.touchStart(event);
if (this.active <= -1) {
this.move(this.count);
@ -136,19 +136,18 @@ export default create({
},
onTouchMove(event) {
this.direction = this.direction || this.getDirection(event.touches[0]);
this.touchMove(event);
if (this.direction === 'horizontal') {
event.preventDefault();
event.stopPropagation();
this.deltaX = event.touches[0].clientX - this.startX;
this.move(0, this.range(this.deltaX, [-this.width, this.width]));
}
},
onTouchEnd() {
if (this.deltaX) {
this.move(Math.abs(this.deltaX) > 50 ? (this.deltaX > 0 ? -1 : 1) : 0);
this.move(this.offsetX > 50 ? (this.deltaX > 0 ? -1 : 1) : 0);
this.currentDuration = this.duration;
}
this.autoPlay();
@ -202,12 +201,6 @@ export default create({
}
},
getDirection(touch) {
const offsetX = Math.abs(touch.clientX - this.startX);
const offsetY = Math.abs(touch.clientY - this.startY);
return offsetX > offsetY ? 'horizontal' : offsetX < offsetY ? 'vertical' : '';
},
range(num, arr) {
return Math.min(Math.max(num, arr[0]), arr[1]);
}

View File

@ -38,10 +38,13 @@ import { raf } from '../utils/raf';
import { on, off } from '../utils/event';
import VanNode from '../utils/node';
import scrollUtils from '../utils/scroll';
import Touch from '../mixins/touch';
export default create({
name: 'tabs',
mixins: [Touch],
components: {
VanNode
},
@ -148,22 +151,10 @@ export default create({
swipeableHandler(init) {
const swipeableEl = this.$refs.content;
(init ? on : off)(swipeableEl, 'touchstart', this.onTouchStart, false);
(init ? on : off)(swipeableEl, 'touchmove', this.onTouchMove, false);
(init ? on : off)(swipeableEl, 'touchend', this.onTouchEnd, false);
(init ? on : off)(swipeableEl, 'touchcancel', this.onTouchEnd, false);
},
// record swipe touch start position
onTouchStart(event) {
this.startX = event.touches[0].clientX;
this.startY = event.touches[0].clientY;
},
// watch swipe touch move
onTouchMove(event) {
this.deltaX = event.touches[0].clientX - this.startX;
this.direction = this.getDirection(event.touches[0]);
(init ? on : off)(swipeableEl, 'touchstart', this.touchStart);
(init ? on : off)(swipeableEl, 'touchmove', this.touchMove);
(init ? on : off)(swipeableEl, 'touchend', this.onTouchEnd);
(init ? on : off)(swipeableEl, 'touchcancel', this.onTouchEnd);
},
// watch swipe touch end
@ -172,7 +163,7 @@ export default create({
const minSwipeDistance = 50;
/* istanbul ignore else */
if (direction === 'horizontal' && Math.abs(deltaX) >= minSwipeDistance) {
if (direction === 'horizontal' && this.offsetX >= minSwipeDistance) {
/* istanbul ignore else */
if (deltaX > 0 && curActive !== 0) {
this.curActive = curActive - 1;
@ -182,13 +173,6 @@ export default create({
}
},
// get swipe direction
getDirection(touch) {
const distanceX = Math.abs(touch.clientX - this.startX);
const distanceY = Math.abs(touch.clientY - this.startY);
return distanceX > distanceY ? 'horizontal' : distanceX < distanceY ? 'vertical' : '';
},
// adjust tab position
onScroll() {
const scrollTop = scrollUtils.getScrollTop(this.scrollEl);