Javascript水平拖动变换位置

Javascript horizontal drag transform position

我正在尝试创建一个可以向左/向右拖动的水平滑块,它会相应地更新其转换平移位置。我想尝试在纯 javascript 中解决这个问题,所以请不要使用外部库。

我目前的工作在初始加载时会拖到它的位置,但之后它不会再次更新以继续。

var object = document.querySelector('.js-slider-container'),
initX, firstX;

object.addEventListener('mousedown', function(e) {

  e.preventDefault();
  initX = this.style.transform;
  firstX = e.pageX;

  this.addEventListener('mousemove', dragIt, false);

  console.log(initX);

  window.addEventListener('mouseup', function() {
    object.removeEventListener('mousemove', dragIt, false);
  }, false);

}, false);

object.addEventListener('touchstart', function(e) {

  e.preventDefault();
  initX = this.style.transform;

  var touch = e.touches;
  firstX = touch[0].pageX;

  this.addEventListener('touchmove', swipeIt, false);

  window.addEventListener('touchend', function(e) {
    e.preventDefault();
    object.removeEventListener('touchmove', swipeIt, false);
  }, false);

}, false);

function dragIt(e) {
  this.style.transform = `translate3d(${initX+e.pageX-firstX}px,0,0)`;
}

function swipeIt(e) {
  var contact = e.touches;

  this.style.transform = `translate3d(${initX+contact[0].pageX-firstX}px,0,0)`;
}

这里有一个 jsfiddle 来说明我的意思,它在初始 运行 上工作 - 但不会继续从该点更新其位置。我也不知道如何限制它的左右位置以避免过度滚动。

感谢任何建议,干杯

最初 this.style.transform 的值将是一个空字符串 "",稍后当您拖动它时,它会更新为 translate3d(-578px, 0px, 0px)

您在计算中直接使用了这个字符串值,而没有仅选择 x 值,因此计算失败。

我们可以使用正则表达式来选择 x 值,如下所示,然后在计算中使用它。

 const txMatch = this.style.transform.match(/translate3d\((-?\d+)px,.+\)/);
 initX = txMatch ? +(txMatch[1] || 0) : 0;

var object = document.querySelector('.js-slider-container'),
  initX, firstX;

object.addEventListener('mousedown', function(e) {
  e.preventDefault();
  const txMatch = this.style.transform.match(/translate3d\((-?\d+)px,.+\)/);
  initX = txMatch ? +(txMatch[1] || 0) : 0;
  firstX = e.pageX;
  this.addEventListener('mousemove', dragIt, false);
  window.addEventListener('mouseup', function() {
    object.removeEventListener('mousemove', dragIt, false);
  }, false);
}, false);

object.addEventListener('touchstart', function(e) {
  e.preventDefault();
  const txMatch = this.style.transform.match(/translate3d\((-?\d+)px,.+\)/);
  initX = txMatch ? +(txMatch[1] || 0) : 0;
  var touch = e.touches;
  firstX = touch[0].pageX;

  this.addEventListener('touchmove', swipeIt, false);

  window.addEventListener('touchend', function(e) {
    object.removeEventListener('touchmove', swipeIt, false);
  }, false);

}, false);

function dragIt(e) {
  const maxMove = this.offsetWidth - this.parentElement.offsetWidth;
  const x = initX + e.pageX - firstX;
  if (x >= 0 || x <= -maxMove) {
   return;
  }
  this.style.transform = `translate3d(${x}px,0,0)`;
}

function swipeIt(e) {
  var contact = e.touches;
  this.style.transform = `translate3d(${initX+contact[0].pageX-firstX}px,0,0)`;
}
*,
*:before,
*:after {
  -webkit-box-sizing: inherit;
  box-sizing: inherit;
}

.container_full-vh {
  position: relative;
  height: 100vh;
}

section {
  padding: 400px 0;
}


/* Slider */

.slider {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 9;
  will-change: transform;
  display: flex;
  align-items: center;
  width: 100%;
  height: 100vh;
  overflow-x: hidden;
}

.slider-container {
  position: relative;
  left: 10px;
  display: grid;
  align-items: center;
  grid-template-columns: repeat(7, 33.3333vw);
  grid-column-gap: 4.167vw;
  padding: 0 8.33333vw;
  height: unset;
  cursor: grab;
}

.slider-item {
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  will-change: transform;
  position: relative;
  overflow: hidden;
  opacity: 1;
  visibility: inherit;
}

.slider-item_img-wrap {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  overflow: hidden;
  opacity: 1;
  visibility: inherit;
}

.slider-item:before,
.slider-item_img-wrap:before {
  content: "";
  display: block;
  padding-bottom: calc(100%/0.8);
}

.slider-item_img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  max-width: unset;
  pointer-events: none;
  user-select: none;
  transform-origin: left center;
  transform: scale(1.75);
  will-change: transform;
}

.slider-item_content {
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
  z-index: 1;
  user-select: none;
}

.slider-item_content-heading {
  display: flex;
  overflow: hidden;
}

.slider-item_content-heading h3 {
  pointer-events: none;
  font-size: 7.569vw;
  line-height: 6.944vw;
  color: white;
  text-transform: uppercase;
  transform-origin: left bottom;
  will-change: transform;
}
<div class="container_full-vh">

  <section>
    <div class="js-slider slider">
      <div class="js-slider-container slider-container">

        <div class="slider-item">
          <div class="slider-item_img-wrap">
            <img src="https://images.unsplash.com/photo-1479839672679-a46483c0e7c8?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80&ar=0.8" class="slider-item_img">
          </div>
          <div class="slider-item_content">
            <div class="slider-item_content-heading">
              <h3>Indigo</h3>
            </div>
          </div>
        </div>

        <div class="slider-item">
          <div class="slider-item_img-wrap">
            <img src="https://images.unsplash.com/photo-1566688342604-dbe3e7357104?ixlib=rb-1.2.1&amp;auto=format&amp;fit=crop&amp;w=800&amp;q=80&amp;ar=0.8" class="slider-item_img">
          </div>
          <div class="slider-item_content">
            <div class="slider-item_content-heading">
              <h3>Rouge</h3>
            </div>
          </div>
        </div>

        <div class="slider-item">
          <div class="slider-item_img-wrap">
            <img src="https://images.unsplash.com/photo-1472835560847-37d024ebacdc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80&ar=0.8" class="slider-item_img">
          </div>
          <div class="slider-item_content">
            <div class="slider-item_content-heading">
              <h3>Juane</h3>
            </div>
          </div>
        </div>

        <div class="slider-item">
          <div class="slider-item_img-wrap">
            <img src="https://images.unsplash.com/photo-1541320823636-40247af897bf?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80&ar=0.8" class="slider-item_img">
          </div>
          <div class="slider-item_content">
            <div class="slider-item_content-heading">
              <h3>Orange</h3>
            </div>
          </div>
        </div>

        <div class="slider-item">
          <div class="slider-item_img-wrap">
            <img src="https://images.unsplash.com/photo-1566787020216-3e4f973ec5ec?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80&ar=0.8" class="slider-item_img">
          </div>
          <div class="slider-item_content">
            <div class="slider-item_content-heading">
              <h3>Vert</h3>
            </div>
          </div>
        </div>

      </div>
    </div>
  </section>

</div>