关于如何实现滑动翻页那件事 (vue+ebupjs实现)?

本demo并没有实现css翻页效果。

基础知识

滑动事件主要有三个:

  • touchstart:刚开始滑动触发。
  • touchmove:滑动期间会不断的触发。
  • touchend:滑动结束后触发。

实现滑动翻页

监听滑动

初始化数据

const initialed = ref<boolean>(false); // 用于判断是否已经初始化了。
const startX = ref<number>(0);   // 开始滑动的横坐标位置。
const distance = ref<number>(0); // 计算的滑动距离。

监听开始滑动

为了实现翻页,我们需要判断用户是向左划,还是向右划。所以,我们得保存滑动起点的横坐标方向的位置。

  • const handleTouchStart = (e: TouchEvent) => {
      console.log("start");
      if (initialed.value) return;	// 判断当前滑动是否还未结束
      startX.value = e.targetTouches[0].clientX; // 获取滑动起点位置
      initialed.value = true;
    };
    

监听滑动过程

滑动时会不断触发 touchmove 事件。我们通过不断触发的过程计算滑动距离 distance。通过计算出的 distance 我们就能够,执行相应的逻辑处理。

  • const handleTouchMove = (e: TouchEvent) => {
      console.log("moving")
      if (!initialed.value) return;
      distance.value = startX.value - e.targetTouches[0].clientX; // 计算滑动距离,负数表示向右滑动,正数表示向左滑动
    };
    

监听滑动结束

滑动结束后,我们得到计算出的滑动距离 distance。 通过 distance 的值,来选择我们的处理逻辑。

  • const handleTouchEnd = (e: TouchEvent) => {
      console.log("end");
      initialed.value = false;
      if (Math.abs(distance.value) < 100) return;	// 判断滑动距离是否大于 100, 不大于则不翻页
      if (distance.value < 0) 	// 向右翻页
        bookRef.value?.prev();
      else if (distance.value > 0) // 向左翻页 
        bookRef.value?.next();
    };
    

效果展示

slip

完整代码

<script setup lang="ts">
import { ref, onMounted, onUnmounted} from "vue";
import Ebupjs, {Rendition} from "epubjs";

const bookRef = ref<Rendition | null>(null); 
onMounted(() => {
  const book = Ebupjs("./src/assets/books/books.epub");
  const rendition = book.renderTo("render-book", {width: "100%", height: "100%"});
  
  rendition.on("click", (e: MouseEvent) => {
    console.log(e.target);
  })

  rendition.display();

  bookRef.value = rendition;

});
onUnmounted(() => {
  bookRef.value?.destroy();
  bookRef.value = null;
});


/**
 * 滑动实现翻页
 * 1. 监听开始滑动
 *  1.1 存储开始滑动时的横坐标。
 * 2. 监听滑动过程
 *  2.1 计算距离开始滑动点的距离。
 * 3. 监听滑动结束
 *  3.1 判断滑动距离,是否满足翻页要求。
 *  3.2 判断上一页,还是下一页。
 */
const initialed = ref<boolean>(false); // 用于判断是否已经初始化了。
const startX = ref<number>(0);   // 开始滑动的横坐标位置。
const distance = ref<number>(0); // 计算的滑动距离。

const handleTouchStart = (e: TouchEvent) => {
  console.log("start");
  if (initialed.value) return;
  startX.value = e.targetTouches[0].clientX;
  initialed.value = true;
};

const handleTouchMove = (e: TouchEvent) => {
  console.log("moving")
  if (!initialed.value) return;
  distance.value = startX.value - e.targetTouches[0].clientX;
};

const handleTouchEnd = (e: TouchEvent) => {
  console.log("end");
  initialed.value = false;
  if (Math.abs(distance.value) < 100) return;
  if (distance.value < 0) 
    bookRef.value?.prev();
  else if (distance.value > 0) 
    bookRef.value?.next();
};

</script>

<template>
  <div id="render-book"></div>
  <div id="render-book2" 
    @touchstart="handleTouchStart" 
    @touchmove="handleTouchMove" 
    @touchend="handleTouchEnd">
  </div>

</template>

<style scoped>

#render-book {
  width: 100%;
  height: 50%;
}

#render-book2 {
  width: 100%;
  height: 50%;
  background-color: red;
}

</style>