水平平滑动量滚动

Posted

技术标签:

【中文标题】水平平滑动量滚动【英文标题】:Horizontal Smooth Momentum Scrolling 【发布时间】:2021-03-23 21:53:15 【问题描述】:

问题:我需要应用一些鼠标滚轮平滑水平滚动到此布局:https://jsfiddle.net/38qLnzkh/。

替代方案:我发现这个脚本完全符合我的要求,但它似乎只能垂直工作:Butter.js。如果你能让它横向工作,它可能会解决我所有的问题。

重要提示:

1.应根据屏幕宽度和触摸设备禁用脚本。

2. 它应该在您在小提琴中看到的所有内容之上提供一个菜单。

提前谢谢你。

编辑: 如果不清楚我需要什么,这里有两个我正在寻找的效果示例:

https://nemesiscorporation.com/

https://www.tentwenty.me/about-us


我的布局:

html

<main class="outer-wrapper">
    <div class="wrapper">
        <article class="section" id="a"><h2>01</h2></article>
        <article class="section" id="b"><h2>02</h2></article>
        <article class="section" id="c"><h2>03</h2></article>
        <article class="section" id="d"><h2>04</h2></article>
        <article class="section" id="e"><h2>05</h2></article>
        <article class="section" id="f"><h2>06</h2></article>
    </div>
</main>

CSS:

.outer-wrapper 
  width: auto;
  height: 100vw;
  transform: rotate(-90deg) translateX(-100vh);
  transform-origin: top left;
  overflow-y: scroll;
  overflow-x: hidden;
  position: absolute;
  scrollbar-width: none;
  -ms-overflow-style: none;

::-webkit-scrollbar 
  display: none;


.wrapper 
  display: flex;
  flex-direction: row;
  width: auto;
  transform: rotate(90deg) translateY(-100vh);
  transform-origin: top left;
    margin: 0;
  padding: 0;


.section 
    color: #000;
  width: 100vw;
  height: 100vh;

【问题讨论】:

看看上面提到的库:min30327.github.io/luxy.js你可以设置data-horizontal="1"水平滚动 感谢您帮助约瑟夫。我想我已经遵循了所有的指示,但似乎什么都没有发生……我做错了什么。请看:Fiddle2 对不起,我刚刚看到,当您垂直滚动时,它会为水平移动设置动画(就像demo page 上的字母一样)。我给你找点别的。对不起。 【参考方案1】:

我在 github 上发布了一个 API,可以轻松解决这个问题,下面你会找到代码来做你想做的事。

与您的相比,我只是在 HTML 中添加了 js 代码和 &lt;script&gt;

如果您想了解更多信息,请here you can find the documentation。

编辑 由于要求发生了一些变化并且 API 已经更新,我已经修改了下面的示例,以便它更适合问题。

答案的主要变化:

现在 js 位于一个名为 onloadinit() 方法中 修改了 css 样式(transform:rotate 制动了大部分滚动 API) 已添加对导航栏平滑滚动的支持 滚动量现在取决于用户物理滚动鼠标滚轮的程度

/* UPDATED 2022 ANSWER */
function init() 
    /*
     * Variables preparation
     */
    let yourWrapperElement = document.getElementsByClassName("outer-wrapper")[0];
    let whateverEaseFunctionYouWant = remaningScrollDistance =>  return remaningScrollDistance / 15 + 1 ;

    //Added support for navbar menu's smooth scrolling
    uss.hrefSetup();

    /*
     * As you asked for, we only apply the custom scrolling for desktop devices
     * by using the "wheel" event instead of the "scroll" or "touchmove" events.
     */
    yourWrapperElement.addEventListener("wheel", event => 
      /*
       * We want to overwrite the default scrolling behaviour
       * of your outer-wrapper component.
       */
      event.preventDefault();
      event.stopPropagation();
      uss.scrollXBy(event.deltaY, yourWrapperElement, null, false);             
    , passive:false);

    /*
     * We apply a the custom ease function
     * which will be used whenever our component is scrolled by the API
     */
    uss.setXStepLengthCalculator(whateverEaseFunctionYouWant, yourWrapperElement);
body 
  margin: 0;
  padding: 0;


.outer-wrapper 
  width: auto;
  height: 100vh; /*  Changed to vh */
  width: 100vw; /* Added */
  /*transform: rotate(-90deg) translateX(-100vh); ROTATING containers brakes 90% of scrolling APIs
  transform-origin: top left;*/
  overflow-y: scroll;
  overflow-x: hidden;
  position: absolute;
  scrollbar-width: none;
  -ms-overflow-style: none;
  /*scroll-behavior: smooth; ISN'T NEEDED FOR MY API */


::-webkit-scrollbar 
  display: none;


.wrapper 
  display: flex;
  flex-direction: row;
  /*width: auto; NOT NEEDED IF WE USE FLEX-SHRINK 0
  transform: rotate(90deg) translateY(-100vh); ROTATING containers brakes 90% of scrolling APIs
  transform-origin: top left;*/
  margin: 0; /* not really needed */
  padding: 0; /* not really needed */


.section 
  color: #000;
  flex-shrink: 0; /* ADDED insted of the width/height of the wrapper */
  width: 100vw;
  height: 100vh;


#a  background-color: #ccc; 
#b  background-color: #fff; 
#c  background-color: #ccc; 
#d  background-color: #fff; 
#e  background-color: #ccc; 
#f  background-color: #fff; 


h2 
  text-align: center;
  font-size: 200px;
  margin: 0;




/* MENU  _________________________ */



.logo 
  float: left;


nav 
  width: 100%;


/* HEADER */

header 
  float: left;
  width: 100%;
  position: absolute;
  z-index: 9999;



/* HEADER LARGE */

header.large 
  height: 50px;


header.large .logo 
  width: 225px;
  height: 50px;
  margin: 20px 0 0 20px;
  background: url('../images/logo-fireqa-green-500px.png');
  background-repeat: no-repeat;
  background-size: contain;

  transition: 0.7s all;
  -moz-transition: 0.7s all;
  -webkit-transition: 0.7s all;
  -o-transition: 0.7s all;



/* UNORDERED LIST */

header.large ul 
  list-style: none;
  float: right;
  margin-right: 25px;

header.small ul 
  list-style: none;
  float: right;
  margin: 0;


header.large li 
  display: inline;
  float: left;
  list-style-position: inside;
  height: 50px;
  -webkit-transition: all ease 0.3s;
  -moz-transition: all ease 0.3s;
  transition: all 0.3s ease-in-out;



header.large li a 
  display: block;
  padding: 20px;
  color: #0E6245;
  text-decoration: none;
  font-family: 'Montserrat', 'arial', sans-serif;
  font-weight: 600 !important;
  letter-spacing: -1px;
  font-size: 25px;

  background-image: linear-gradient(#0E6245, #0E6245);
  background-position: 50% 80%;
  background-repeat: no-repeat;
  background-size: 0% 4px;

  -moz-transition: all 0.3s ease-in-out 0s;
  -ms-transition: all 0.3s ease-in-out 0s;
  -o-transition: all 0.3s ease-in-out 0s;
  -webkit-transition: all 0.3s ease-in-out 0s;
  transition: all 0.3s ease-in-out 0s;


header.large li a:hover, a:focus 
  background-size: 60% 4px;
<script src = "https://cdn.jsdelivr.net/npm/universalsmoothscroll@latest/universalsmoothscroll-min.js"></script>

<body onload = init()>


<main class="outer-wrapper">
    <div class="wrapper">
        <article class="section" id="a"><h2>01</h2></article>
        <article class="section" id="b"><h2>02</h2></article>
        <article class="section" id="c"><h2>03</h2></article>
        <article class="section" id="d"><h2>04</h2></article>
        <article class="section" id="e"><h2>05</h2></article>
        <article class="section" id="f"><h2>06</h2></article>
    </div>
</main>


<!-- MENU _____________________ -->


<header class="large">
    <div class="container">
      <nav>
        <a><div class="logo"></div></a>
          <ul>
            <li><a href="#a">01</a></li>
            <li><a href="#b">02</a></li>
            <li><a href="#c">03</a></li>
            <li><a href="#d">04</a></li>
         </ul>
      </nav>
    </div>
  </header>

  </body>
</html>

【讨论】:

感谢 Christian 花时间介绍这个解决方案。它有效,并且非常容易实现。这非常接近我的需要。然而,它基于 scrollDistance 的事实不允许用户在他们想要的地方准确地暂停页面。但这仍然是一个很好的解决方案,如果我找不到更好的解决方案,我一定会使用它。非常感谢! 嗨,大卫,根据您提供的示例,我认为您不需要像素精度滚动,但如果是这种情况,我在此处提供的 API 有 2 种方法可以帮助您它们是:uss.scrollYTo()uss.scrollIntoView()。第一个允许您顺利转到 scrollingElement 的确切 y 轴坐标(在本例中为外包装),而第二个允许您滚动容器直到您指定的元素可见(您可能需要对齐) .如果您找不到更好的东西,我希望这对您有所帮助! 嗨,Christian,我不需要像素精度,但让我感到困扰的是,用户无法将布局的一部分放置在他想要的视口中,这可能会留下该部分的一部分.那是我唯一的问题,它不是世界末日......我只是希望有一些更流畅的东西,比如我提供的示例,其中滚动的速度和数量与鼠标滚轮的使用相关。不过不要误会我的意思,我真的很高兴有你的解决方案,如果没有更接近我需要的东西出现,我将非常感激使用它。非常感谢!!! 嗨 Cristian,当我意识到它在 Firefox 中不起作用时,我非常高兴地使用你的脚本植入我的项目。有什么建议吗? 嗨,大卫,据我测试,所有 API 函数在 Firefox 上都能正常工作,即使是提供的示例也是如此。所以问题可能是由于在示例中我使用event.deltaY 来了解用户滚动了多少:这工作正常但问题是chrome和firefox为相同的数量提供了两个不同的值的滚动。 Chrome 使用滚动值 x 100(这就是我放 event.deltaY / 100 的原因),而 firefox 使用原始值(所以 / 100 部分搞砸了)。我已经更新了代码,现在可以在 Firefox 中正常工作了!【参考方案2】:

有一个不错的包叫做smooth-scrollbar。

我已经调整了您的示例。它禁用移动设备的平滑滚动,否则它只是调用包。我已经清理了一些 CSS。

/** @see https://***.com/a/52855084/5312432 */
function isTouchDevice() 
  return window.matchMedia("(pointer: coarse)").matches;


function initSmoothScrolling() 
  const options = 
    damping: 0.1,
    alwaysShowTracks: true
  ;
  const elements = document.querySelectorAll(".smooth-scrollbar");
  for (const element of elements) 
    Scrollbar.init(element, options);
  


if (!isTouchDevice()) 
  initSmoothScrolling();
body 
  margin: 0;
  padding: 0;


.smooth-scrollbar 
  overflow: auto;


.wrapper 
  display: flex;
  flex-direction: row;


.section 
  width: 100vw;
  height: 100vh;
  flex-shrink: 0;


.section:nth-child(odd) 
  background-color: #ccc;


.section:nth-child(even) 
  background-color: #fff;


h2 
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  font-size: 200px;
  margin: 0;
<main class="smooth-scrollbar">
  <div class="wrapper">
    <article class="section"><h2>01</h2></article>
    <article class="section"><h2>02</h2></article>
    <article class="section"><h2>03</h2></article>
    <article class="section"><h2>04</h2></article>
    <article class="section"><h2>05</h2></article>
    <article class="section"><h2>06</h2></article>
  </div>
</main>

<script src="https://cdnjs.cloudflare.com/ajax/libs/smooth-scrollbar/8.5.3/smooth-scrollbar.js"></script>

【讨论】:

您好 Josef,感谢您的帮助,但我已经在所有主流浏览器中测试了您的示例,但它不会滚动。 :( 我已经用一些我正在寻找的示例更新了原始问题... 好的,当您单击滚动条轨迹时,平滑,平滑,但我不明白这个答案...帖子作者要求应用鼠标滚轮平滑水平滚动:您的 sn-p 1) 显示的内容也可以垂直滚动,2) 并且不能垂直使用鼠标滚轮...

以上是关于水平平滑动量滚动的主要内容,如果未能解决你的问题,请参考以下文章

平滑 JavaScript/jQuery 滚动到元素

平滑 JavaScript/jQuery 滚动到元素

Android 平滑滚动到底部

如何在wpf treeview控件上启用平滑滚动

CGridCtrl 水平滚动

RecyclerView 平滑滚动到中心位置。安卓