Как добавить плавность к перетаскиванию - PullRequest
0 голосов
/ 12 октября 2019

У меня есть горизонтальная область прокрутки, которую можно также перетаскивать. Я хотел бы добавить плавность к этому перетаскиванию и прокрутке, я хочу, чтобы он продолжал двигаться по оси x после того, как я оставлю перетаскивание и остановлюсь медленно.

Вот небольшой фрагмент всей сцены, который работает сейчас без «плавности»

const slider = document.querySelector(".wrapper");
      const preventClick = (e) => {
        e.preventDefault();
        e.stopImmediatePropagation();
      }
      let isDown = false;
      var isDragged = false;
      let startX;
      let scrollLeft;

      slider.addEventListener("mousedown", e => {
        isDown = true;
        slider.classList.add("active");
        startX = e.pageX - slider.offsetLeft;
        scrollLeft = slider.scrollLeft;
      });

      slider.addEventListener("mouseleave", () => {
        isDown = false;
        slider.classList.remove("active");
      });

      slider.addEventListener("mouseup", e => {
        isDown = false;
        const elements = document.getElementsByClassName("book");
        if(isDragged){
            for(let i = 0; i<elements.length; i++){
                  elements[i].addEventListener("click", preventClick);
            }
        }else{
            for(let i = 0; i<elements.length; i++){
                  elements[i].removeEventListener("click", preventClick);
            }
        }
        slider.classList.remove("active");
        isDragged = false;
      });

      slider.addEventListener("mousemove", e => {
        if (!isDown) return;
        isDragged =  true;
        e.preventDefault();
        const x = e.pageX - slider.offsetLeft;
        const walk = (x - startX) * 2;
        slider.scrollLeft = scrollLeft - walk;
      });

      document.getElementsByClassName("book").ondragstart = function() {
        console.log("Drag start");
      };
.wrapper {
        position: relative;
        display: -webkit-box;
        display: -webkit-flex;
        display: -ms-flexbox;
        display: flex;
        overflow: auto;
        min-width: 100%;
      }

      .book {
        width: auto;
        height: 100vh;
        min-width: 50vw;
      }

      .one {
        background-color: #d07fe0;
      }

      .two {
        background-color: #808888;
      }

      .three {
        background-color: #83e7dc;
      }

      .four {
        background-color: #edf7a8;
      }

      .five {
        background-color: #e9d98f;
      }

      .six {
        background-color: #fdd;
      }
<body>
      <div class="wrapper">
        <a href="https://stackoverflow.com/" class="book one"></a>
        <a href="https://stackoverflow.com/" class="book two"></a>
        <a href="https://stackoverflow.com/" class="book three"></a>
        <a href="https://stackoverflow.com/" class="book four"></a>
        <a href="https://stackoverflow.com/" class="book five"></a>
        <a href="https://stackoverflow.com/" class="book six"></a>
      </div>
    </body>

Буду признателен за любую помощь, спасибо, nir

1 Ответ

1 голос
/ 12 октября 2019

Вы можете добавить переменную velocity, которая сообщает, сколько пикселей прокручивается в каждом кадре:

let velocity = 0;
slider.addEventListener("mousemove", e => {
        if (!isDown) return;
        isDragged =  true;
        e.preventDefault();
        let lastX = slider.scrollLeft;
        const x = e.pageX - slider.offsetLeft;
        const walk = (x - startX) * 2;
        slider.scrollLeft = scrollLeft - walk;

        velocity = lastX - slider.scrollLeft;
      });

Затем вы можете добавить функцию для продолжения перемещения содержимого после того, как использование прекратит нажимать:

function smooth() {
              console.log(velocity);
          if (Math.abs(velocity) > 0) {
              if (Math.abs(velocity) < 2) {
                  velocity = 0;
              }
              if (velocity > 0) {
                velocity  -= 2;
              }
              else {
                velocity += 2;
              }
              slider.scrollLeft -= velocity;
              requestAnimationFrame(smooth);
          }
      }

После этого вызовите функцию onmouseup:

    slider.addEventListener("mousemove", e => {
        if (!isDown) return;
        isDragged =  true;
        e.preventDefault();
        let lastX = slider.scrollLeft;
        const x = e.pageX - slider.offsetLeft;
        const walk = (x - startX) * 2;
        slider.scrollLeft = scrollLeft - walk;

        velocity = lastX - slider.scrollLeft;
      });

Полный код ниже

const slider = document.querySelector(".wrapper");
          const preventClick = (e) => {
            e.preventDefault();
            e.stopImmediatePropagation();
          }
          let isDown = false;
          var isDragged = false;
          let startX;
          let scrollLeft;
		  let velocity = 0;

          slider.addEventListener("mousedown", e => {
            velocity = 0; // Cancel previous velocity
            isDown = true;
            slider.classList.add("active");
            startX = e.pageX - slider.offsetLeft;
            scrollLeft = slider.scrollLeft;
          });

          slider.addEventListener("mouseleave", () => {
            isDown = false;
            slider.classList.remove("active");
          });

          slider.addEventListener("mouseup", e => {
            isDown = false;
            const elements = document.getElementsByClassName("book");
            if(isDragged){
                for(let i = 0; i<elements.length; i++){
                      elements[i].addEventListener("click", preventClick);
                }
            }else{
                for(let i = 0; i<elements.length; i++){
                      elements[i].removeEventListener("click", preventClick);
                }
            }
            slider.classList.remove("active");
            isDragged = false;
			requestAnimationFrame(smooth);
          });

          slider.addEventListener("mousemove", e => {
            if (!isDown) return;
            isDragged =  true;
            e.preventDefault();
			let lastX = slider.scrollLeft;
            const x = e.pageX - slider.offsetLeft;
            const walk = (x - startX) * 2;
            slider.scrollLeft = scrollLeft - walk;

			velocity = lastX - slider.scrollLeft;
          });

          document.getElementsByClassName("book").ondragstart = function() {
            console.log("Drag start");
          };

		  function smooth() {
			  if (Math.abs(velocity) > 0) {
        // Change the 2s here to change how quickly the scrolling stops
				  if (Math.abs(velocity) < 2) {
					  velocity = 0;
				  }
				  if (velocity > 0) {
					velocity  -= 2;
				  }
				  else {
					velocity += 2;
				  }
        		  slider.scrollLeft -= velocity;
				  requestAnimationFrame(smooth);
			  }
		  }
    .wrapper {
    	position: relative;
    	display: -webkit-box;
    	display: -webkit-flex;
    	display: -ms-flexbox;
    	display: flex;
    	overflow: auto;
    	min-width: 100%;
    }

    .book {
      	width: auto;
      	height: 100vh;
      	min-width: 50vw;
    }

    .one {
      	background-color: #d07fe0;
    }

    .two {
     	 background-color: #808888;
    }

    .three {
     	 background-color: #83e7dc;
    }

    .four {
     	 background-color: #edf7a8;
    }

    .five {
     	 background-color: #e9d98f;
    }

    .six {
     	 background-color: #fdd;
    }
<div class="wrapper">
        <a href="https://stackoverflow.com/" class="book one"></a>
        <a href="https://stackoverflow.com/" class="book two"></a>
        <a href="https://stackoverflow.com/" class="book three"></a>
        <a href="https://stackoverflow.com/" class="book four"></a>
        <a href="https://stackoverflow.com/" class="book five"></a>
        <a href="https://stackoverflow.com/" class="book six"></a>
      </div>
...