【问题标题】:When I touch my JavaScript slider on mobile, I can't scroll down the page当我在移动设备上触摸我的 JavaScript 滑块时,我无法向下滚动页面
【发布时间】:2021-02-26 05:13:36
【问题描述】:

我使用 纯 JavaScript 构建了一个滑块。在移动屏幕上,当我触摸滑块时,我只能更改幻灯片,但无法向下滚动页面
当滑块元素被触摸时,会触发一个 "touchstart" 事件,并触发相应的事件处理函数 event.preventDefault() 停止滚动页面,然后当 "touchmove" em> 事件触发,代码使用第一个和新的水平坐标之间的差异和 CSS left 属性来移动滑块。

我在下面做了一个最小的代码。也可以点击see code on online editor

const slides = document.querySelector(".slides");
let posX1, posX2, dX;

slides.addEventListener("touchstart", dragStart);
slides.addEventListener("touchmove", dragAction);

function dragStart(e) {
  e.preventDefault();
  posX1 = e.touches[0].clientX;
}

function dragAction(e) {
  posX2 = e.touches[0].clientX;
  dX = posX2 - posX1;
  posX1 = e.touches[0].clientX;
  slides.style.left = (slides.offsetLeft + dX) + "px";
}
body {
  padding-bottom: 1000px;
}

.slider {
  width: 200px;
  height: 100px;
  margin: 0 auto;
  border: 1px solid black;
  position: relative;
  overflow: hidden;
}

.slides {
  width: 600px;
  height: 100px;
  display: flex;
  position: absolute;
}

.slide {
  width: 200px;
  height: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.slide:nth-child(1) {
  background-color: rgb(200, 200, 200);
}

.slide:nth-child(2) {
  background-color: rgb(150, 150, 150);
}

.slide:nth-child(3) {
  background-color: rgb(100, 100, 100);
}
<!DOCTYPE html>
<html>

<body>
  <div class="slider">
    <div class="slides">
      <div class="slide">Slide 1</div>
      <div class="slide">Slide 2</div>
      <div class="slide">Slide 3</div>
    </div>
  </div>
</body>

</html>

感谢您的宝贵时间:)

【问题讨论】:

  • 大家好,有人在这里吗?!我仍然需要帮助...

标签: javascript carousel touch-event slide preventdefault


【解决方案1】:

我认为除了我之外没有人检查过我的问题,但是,假设有一个假设的人与我有同样的问题,我可以解决这个问题:
我想出了如何使用this post 制作JavaScript 滑块,其中作者在“touchstart” EventListener 中使用了preventDefault(),我坚持使用它,但解决方案是简单地调用preventDefault() "touchmove" 事件本身的方法不是 "touchstart",当然如果你需要(如果用户试图更改幻灯片)。如果用户试图滚动页面,则删除“touchend”EventListener。

const slides = document.querySelector(".slides");
let posX1,
    posX2,
    posY1,
    posY2,
    dX,
    dY,
    dirDetected = false;
    
  //feature detection
  //-------------Note 1-----------//
  let passiveIfSupported = false;
  try {
    window.addEventListener("test", null, Object.defineProperty({}, "passive", {
      get: function() {passiveIfSupported = {passive: false};}
    }));
  } catch(err) {}

slides.addEventListener("touchstart", dragStart, passiveIfSupported);
slides.addEventListener("touchmove", dragAction, passiveIfSupported);
slides.addEventListener("touchend", dragEnd, false);

function dragStart(e) {
  posX1 = e.touches[0].clientX;
  posY1 = e.touches[0].clientY;
}

function dragAction(e) {
  //-------------Note 2-----------//
  e.preventDefault();
  
  posX2 = e.touches[0].clientX;
  posY2 = e.touches[0].clientY;
  dX = posX2 - posX1;
  posX1 = e.touches[0].clientX;
  dY = posY2 - posY1;
  
  if (!dirDetected) {
    if (Math.abs(dY) > Math.abs(dX)) {
      slides.removeEventListener("touchmove", dragAction, passiveIfSupported);
      return;
    }
    dirDetected = true;
  }
    
  slides.style.left = (slides.offsetLeft + dX) + "px";
}

  function dragEnd() {
    if (!dirDetected) {
      slides.addEventListener("touchmove", dragAction, passiveIfSupported);
    }
    dirDetected = false;
  }
body {
  padding-bottom: 1000px;
}

.slider {
  width: 200px;
  height: 100px;
  margin: 0 auto;
  border: 1px solid black;
  position: relative;
  overflow: hidden;
}

.slides {
  width: 600px;
  height: 100px;
  display: flex;
  position: absolute;
}

.slide {
  width: 200px;
  height: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.slide:nth-child(1) {
  background-color: rgb(200, 200, 200);
}

.slide:nth-child(2) {
  background-color: rgb(150, 150, 150);
}

.slide:nth-child(3) {
  background-color: rgb(100, 100, 100);
}
<!DOCTYPE html>
<html>

<body>
  <div class="slider">
    <div class="slides">
      <div class="slide">Slide 1</div>
      <div class="slide">Slide 2</div>
      <div class="slide">Slide 3</div>
    </div>
  </div>
</body>

</html>

注意1.(addEventListener的第三个参数):注意addEventListener()方法的第三个参数。我在this question 的搜索中发现了一些东西。我将在 "touchmove" EventListener 中使用preventDefault(),但在某些版本的 Chrome 和 Firefox 中用于 "touchstart""touchmove" 事件如果你不指定选项对象的被动属性(addEventListener() 的第三个参数),默认值将设置为 true,这不会让 EventListener 调用preventDefault(),所以你必须设置第三个{passive: false} 的参数,但如果加载脚本的浏览器是旧的,需要 addEventListener() 的第三个布尔参数,那么你需要提供一个布尔值而不是对象。所以你可以使用feature detection来提供一个合适的参数。

注意 2. Firefox 和 chrom android 处理 "touchmove" preventDefault() 的方式不同: 这是我发现的另一点 (from this question),如果您在 Chrome Android 上运行上述代码,它运行良好,您可以滚动页面或更改幻灯片,但在 Firefox Android 上您无法滚动。实际上我认为这是 Chrome 的错,因为根据Specs for "touchmove" event,如果第一个 "touchmove" 事件被阻止,那么随后绑定到同一触摸点的 "touchmove" 事件将被阻止在上面的代码中,在 "touchmove" 事件处理函数的第一行,我使用了preventDefault(),所以我需要在 if 块之后调用它,以确保在需要时阻止默认行为。

const slides = document.querySelector(".slides");
let posX1,
    posX2,
    posY1,
    posY2,
    dX,
    dY,
    dirDetected = false;
    
  //feature detection
  let passiveIfSupported = false;
  try {
    window.addEventListener("test", null, Object.defineProperty({}, "passive", {
      get: function() {passiveIfSupported = {passive: false};}
    }));
  } catch(err) {}

slides.addEventListener("touchstart", dragStart, passiveIfSupported);
slides.addEventListener("touchmove", dragAction, passiveIfSupported);
slides.addEventListener("touchend", dragEnd, false);

function dragStart(e) {
  posX1 = e.touches[0].clientX;
  posY1 = e.touches[0].clientY;
}

function dragAction(e) {
  posX2 = e.touches[0].clientX;
  posY2 = e.touches[0].clientY;
  dX = posX2 - posX1;
  posX1 = e.touches[0].clientX;
  dY = posY2 - posY1;
  
  if (!dirDetected) {
    if (Math.abs(dY) > Math.abs(dX)) {
      slides.removeEventListener("touchmove", dragAction, passiveIfSupported);
      return;
    }
    e.preventDefault();
  }
  
  dirDetected = true;
  slides.style.left = (slides.offsetLeft + dX) + "px";
}

  function dragEnd() {
    if (!dirDetected) {
      slides.addEventListener("touchmove", dragAction, passiveIfSupported);
    }
    dirDetected = false;
  }
body {
  padding-bottom: 1000px;
}

.slider {
  width: 200px;
  height: 100px;
  margin: 0 auto;
  border: 1px solid black;
  position: relative;
  overflow: hidden;
}

.slides {
  width: 600px;
  height: 100px;
  display: flex;
  position: absolute;
}

.slide {
  width: 200px;
  height: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.slide:nth-child(1) {
  background-color: rgb(200, 200, 200);
}

.slide:nth-child(2) {
  background-color: rgb(150, 150, 150);
}

.slide:nth-child(3) {
  background-color: rgb(100, 100, 100);
}
<!DOCTYPE html>
<html>

<body>
  <div class="slider">
    <div class="slides">
      <div class="slide">Slide 1</div>
      <div class="slide">Slide 2</div>
      <div class="slide">Slide 3</div>
    </div>
  </div>
</body>

</html>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    • 2016-11-18
    • 1970-01-01
    • 2020-03-29
    相关资源
    最近更新 更多