添加简单的左/右滑动手势

问题描述 投票:0回答:5

我需要添加一个简单的左/右滑动手势,以便在移动设备上滑动时“选定”图像循环,类似于单击英雄组件中的按钮,也类似于按键盘上的左/右箭头键

我对 JavaScript 没有太多经验,所以如果有人能告诉我到底要写什么以及在哪里,以便我可以完全完成这个项目。

这是一个演示:http://nufaith.ca/justinatkins/

代码:

Vue.component('hero-bg', {
  template: `
    <div class="hero-bg">
      <div class="hero">
        <img id="pushed" :src="selected"/>
      </div>
    </div>
    `,
  props: ['selected']
});

Vue.component('hero-bg-empty', {
  template: `
    <div class="hero-bg">
      <div class="hero">
      <span style="display:block;height:100px;"></span>
      </div>
    </div>
    `
});

Vue.component('hero', {
  template: `
    <div>
      <topbar v-if="!gridEnabled"></topbar>
      <topbar2 v-if="gridEnabled"></topbar2>
      <hero-bg :selected="selectedItem.img" v-if="!gridEnabled"></hero-bg>
      <hero-bg-empty v-if="gridEnabled"></hero-bg-empty>
      <div class="hero-container" v-if="!gridEnabled">
        <div class="hero">
          <img :src="selectedItem.img" v-if="thing" alt=""/>
        </div>

        <div class="hero-desc">
          <button class="control left" @click="previous">
            <i class="zmdi zmdi-chevron-left"></i>
          </button>
          <span class="hero-desc-title" v-html="title"></span>
          <button class="control right" @click="next">
            <i class="zmdi zmdi-chevron-right"></i>
          </button>
          <br/>
          <button class="view-all-button" @click="enableGrid">OVERVIEW</button>
        </div>
      </div>
    </div>
    `,
  data() {
    return {
      gridEnabled: false,
      selected: 0,
      thing: true
    };
  },
  computed: {
    selectedItem() {
      return info[this.selected];
    },
    title() {
      const comma = this.selectedItem.title.indexOf(',');
      const len = this.selectedItem.title.length;
      const strBeginning = this.selectedItem.title.substring(comma, 0);
      const strEnd = this.selectedItem.title.substring(comma, len);
      if (this.selectedItem.title.includes(',')) {
        return `<span>${strBeginning}<span class="font-regular font-muted">${strEnd}</span></span>`;
      }
      return this.selectedItem.title;
    },
    maxImages() {
      return info.length - 1;
    }
  },
  created() {
    window.addEventListener('keydown', e => {
      if (e.keyCode === 37) {
        this.previous();
        return;
      }

      if (e.keyCode === 39) {
        this.next();
        return;
      }
    });
    Event.$on('updateImg', index => {
      this.selected = index;
      this.gridEnabled = !this.gridEnabled;
    });
  },
  methods: {
    next() {
      this.selected === this.maxImages ? (this.selected = 0) : (this.selected += 1);
    },
    previous() {
      this.selected === 0 ? (this.selected = this.maxImages) : (this.selected -= 1);
    },
    enableGrid() {
      this.gridEnabled = !this.gridEnabled;
      window.scroll(0, 0);
      Event.$emit('enableGrid');
    }
  }
});
javascript vue.js swipe
5个回答
26
投票

这就是我在我的一个项目中实现一个简单的滑动手势的方式。你可以看看这个。

代码:

touchableElement.addEventListener('touchstart', function (event) {
    touchstartX = event.changedTouches[0].screenX;
    touchstartY = event.changedTouches[0].screenY;
}, false);

touchableElement.addEventListener('touchend', function (event) {
    touchendX = event.changedTouches[0].screenX;
    touchendY = event.changedTouches[0].screenY;
    handleGesture();
}, false);


function handleGesture() {
    if (touchendX < touchstartX) {
        console.log('Swiped Left');
    }

    if (touchendX > touchstartX) {
        console.log('Swiped Right');
    }

    if (touchendY < touchstartY) {
        console.log('Swiped Up');
    }

    if (touchendY > touchstartY) {
        console.log('Swiped Down');
    }

    if (touchendY === touchstartY) {
        console.log('Tap');
    }
}

基本上,这里提到的

touchableElement
,是指将接收触摸事件的
DOM Element
。如果您想在整个屏幕上激活滑动选项,那么您可以使用
body
标签作为可触摸元素。或者,您可以将任何特定的
div
元素配置为可触摸元素,以防您只想在该特定的
div
上进行滑动手势。

在此

touchableElement
,我们在这里添加 2 个事件监听器:

  1. touchstart
    : 这是用户开始滑动的时间。我们采用初始坐标 (x,y) 和 分别将它们存储到touchstartX、touchstartY中。
  2. touchend
    :这是用户停止滑动的时间。我们获取最终坐标 (x, y) 并将它们分别存储到 touchendX、touchendY 中。

请记住,这些坐标的原点是屏幕的左上角。当您从 从左到右 时,x 坐标会增加,而当您从 从上到下时,y 坐标会增加

然后,在

handleGesture()
中,我们只需比较这两对坐标(touchstartX,touchstartY)和(touchendX,touchendY),以检测不同类型的滑动手势(上,下,左,右):

  • touchendX < touchstartX
    :表示用户开始较高的X值滑动并且停止较低的X值滑动。这意味着,从右向左滑动(向左滑动)。

  • touchendX > touchstartX

    :表示用户
    开始较低的X值滑动并且停止较高的X值滑动。这意味着,从左向右滑动(向右滑动)。

  • touchendY < touchstartY

    :表示用户

    开始
    较高的Y值滑动并且停止较低的Y值滑动。这意味着,从下到上滑动(向上滑动)。

  • touchendY > touchstartY

    :表示用户

    开始
    较低的Y值滑动并且停止较高的Y值滑动。这意味着,从上到下滑动(向下滑动)。

  • 您可以在相应的
if

块上添加这 4 个不同事件(向上/向下/向左/向右滑动)的代码,如代码所示。

    


9
投票

export default class TouchEvent { static SWIPE_THRESHOLD = 50; // Minimum difference in pixels at which a swipe gesture is detected static SWIPE_LEFT = 1; static SWIPE_RIGHT = 2; static SWIPE_UP = 3; static SWIPE_DOWN = 4; constructor(startEvent, endEvent) { this.startEvent = startEvent; this.endEvent = endEvent || null; } isSwipeLeft() { return this.getSwipeDirection() == TouchEvent.SWIPE_LEFT; } isSwipeRight() { return this.getSwipeDirection() == TouchEvent.SWIPE_RIGHT; } isSwipeUp() { return this.getSwipeDirection() == TouchEvent.SWIPE_UP; } isSwipeDown() { return this.getSwipeDirection() == TouchEvent.SWIPE_DOWN; } getSwipeDirection() { if (!this.startEvent.changedTouches || !this.endEvent.changedTouches) { return null; } let start = this.startEvent.changedTouches[0]; let end = this.endEvent.changedTouches[0]; if (!start || !end) { return null; } let horizontalDifference = start.screenX - end.screenX; let verticalDifference = start.screenY - end.screenY; // Horizontal difference dominates if (Math.abs(horizontalDifference) > Math.abs(verticalDifference)) { if (horizontalDifference >= TouchEvent.SWIPE_THRESHOLD) { return TouchEvent.SWIPE_LEFT; } else if (horizontalDifference <= -TouchEvent.SWIPE_THRESHOLD) { return TouchEvent.SWIPE_RIGHT; } // Vertical or no difference dominates } else { if (verticalDifference >= TouchEvent.SWIPE_THRESHOLD) { return TouchEvent.SWIPE_UP; } else if (verticalDifference <= -TouchEvent.SWIPE_THRESHOLD) { return TouchEvent.SWIPE_DOWN; } } return null; } setEndEvent(endEvent) { this.endEvent = endEvent; } }

如何使用

只需向其提供来自

touchstart

touchend
的事件:
import TouchEvent from '@/TouchEvent'

let touchEvent = null;

document.addEventListener('touchstart', (event) => {
    touchEvent = new TouchEvent(event);
});

document.addEventListener('touchend', handleSwipe);

function handleSwipe(event) {
    if (!touchEvent) {
         return;
    }

    touchEvent.setEndEvent(event);

    if (touchEvent.isSwipeRight()) {
        // Do something
    } else if (touchEvent.isSwipeLeft()) {
        // Do something different
    }

    // Reset event for next touch
    touchEvent = null;
}



5
投票
Hammer.JS

的工作,除非你想避免依赖。他们有很好的文档和示例来帮助入门 我的 Vue 知识几乎一无所知,所以我很担心这会成为盲人引导盲人的场景,但你要做的第一件事就是使用 npm 或 YARN 添加依赖项 - 然后将其添加到顶部您的文件使用

import Hammer from 'hammerjs'

尝试在此行上方添加以下代码:

Event.$on('updateImg', index => {

const swipeableEl = document.getElementsByClassName('.hero')[0]; this.hammer = Hammer(swipeableEl) this.hammer.on('swipeleft', () => this.next()) this.hammer.on('swiperight', () => this.previous())

如果它不起作用,您必须检查开发人员工具/控制台日志以查看是否记录了任何有用的错误。

这个

codepen

也可能是一个有用的资源: 祝你好运。


1
投票

import { onMounted, Ref } from 'vue' export type SwipeCallback = (event: TouchEvent) => void; export type SwipeOptions = { directinoal_threshold?: number; // Pixels offset to trigger swipe }; export const useSwipe = (touchableElement: HTMLElement = null, options: Ref<SwipeOptions> = ref({ directinoal_threshold: 10 })) => { const touchStartX = ref(0); const touchEndX = ref(0); const touchStartY = ref(0); const touchEndY = ref(0); onMounted(() => { if (!touchableElement) touchableElement = document.body; touchableElement.addEventListener('touchstart', (event) => { touchStartX.value = event.changedTouches[0].screenX; touchStartY.value = event.changedTouches[0].screenY; }, false); touchableElement.addEventListener('touchend', (event) => { touchEndX.value = event.changedTouches[0].screenX; touchEndY.value = event.changedTouches[0].screenY; handleGesture(event); }, false); }); const onSwipeLeft: Array<SwipeCallback> = []; const onSwipeRight: Array<SwipeCallback> = []; const onSwipeUp: Array<SwipeCallback> = []; const onSwipeDown: Array<SwipeCallback> = []; const onTap: Array<SwipeCallback> = []; const addEventListener = (arr: Array<SwipeCallback>, callback: SwipeCallback) => { arr.push(callback); }; const handleGesture = (event: TouchEvent) => { if (touchEndX.value < touchStartX.value && (Math.max(touchStartY.value, touchEndY.value) - Math.min(touchStartY.value, touchEndY.value)) < options.value.directinoal_threshold) { onSwipeLeft.forEach(callback => callback(event)); } if (touchEndX.value > touchStartX.value && (Math.max(touchStartY.value, touchEndY.value) - Math.min(touchStartY.value, touchEndY.value)) < options.value.directinoal_threshold) { onSwipeRight.forEach(callback => callback(event)); } if (touchEndY.value < touchStartY.value && (Math.max(touchStartX.value, touchEndX.value) - Math.min(touchStartX.value, touchEndX.value)) < options.value.directinoal_threshold) { onSwipeUp.forEach(callback => callback(event)); } if (touchEndY.value > touchStartY.value && (Math.max(touchStartX.value, touchEndX.value) - Math.min(touchStartX.value, touchEndX.value)) < options.value.directinoal_threshold) { onSwipeDown.forEach(callback => callback(event)); } if (touchEndY.value === touchStartY.value) { onTap.forEach(callback => callback(event)); } } return { onSwipeLeft: (callback: SwipeCallback) => addEventListener(onSwipeLeft, callback), onSwipeRight: (callback: SwipeCallback) => addEventListener(onSwipeRight, callback), onSwipeUp: (callback: SwipeCallback) => addEventListener(onSwipeUp, callback), onSwipeDown: (callback: SwipeCallback) => addEventListener(onSwipeDown, callback), onTap: (callback: SwipeCallback) => addEventListener(onTap, callback) } }

使用示例:

const { onSwipeLeft, onSwipeRight } = useSwipe(document.body); onSwipeLeft((e:TouchEvent) => { //logic });



0
投票
phoenix

答案进行修改: function registerTouchEvent(element, callback) { const THRESHOLD = 50 // Minimum difference in pixels at which a swipe gesture is detected let startEvent, endEvent element.addEventListener('touchstart', event => startEvent = event) element.addEventListener('touchend', event => { endEvent = event; callback(getSwipeDirection()) }) function getSwipeDirection() { if (!startEvent.changedTouches || !endEvent.changedTouches) return let start = startEvent.changedTouches[0] let end = endEvent.changedTouches[0] if (!start || !end) return let horizontalDifference = start.screenX - end.screenX let verticalDifference = start.screenY - end.screenY // Horizontal difference dominates if (Math.abs(horizontalDifference) > Math.abs(verticalDifference)) { if (horizontalDifference >= THRESHOLD) return 'left' if (horizontalDifference <= -THRESHOLD) return 'right' return null } // Vertical or no difference dominates if (verticalDifference >= THRESHOLD) return 'up' if (verticalDifference <= -THRESHOLD) return 'down' return null } }

使用方法:

registerTouchEvent(document, callback)

callback

将收到一个字符串 left/right/up/down

    

© www.soinside.com 2019 - 2024. All rights reserved.