什么是Google搜索结果页面Carousel技术?

时间:2018-05-08 07:22:13

标签: javascript css google-chrome google-search serp

在过去的几周里,Google为Stack Overflow结果展示了一个旋转木马,它非常棒,移动平稳但对我来说很奇怪,没有JavaScript DOM更改,甚至{{1}这导致水平滚动,我找不到它。

Google SERP carousel for Stack Overflow

即使我读到了CSS Horizontal Scroll,但它是如此不同,它只适用于CSS在其他浏览器中它不存在。

经过一些搜索和实验,我发现这个奇怪的旋转木马实际上是一个带有Google Chrome滚动条的长水平分割,但是如何用display: none和移动鼠标指针,分割滚动移动?这是一个原生的铬技巧?或者只是使用grab来计算水平滚动的动作?

2 个答案:

答案 0 :(得分:1)

实际上,我已经找到了问题的答案,但是我决定现在将其发布在这里。 Google网站开发人员使用许多性感技巧来实现UI,而该轮播就是其中之一,当然,这不是DOM操纵,它是一个简单的滚动分区。因此,分割运动非常平稳,即使拖动正确也是如此。

在某些设备(例如Apple设备或其他触摸设备)中,滚动具有某些本机行为,即使Microsoft新型笔记本电脑也具有一些通过触摸滚动的功能。但是,如果我们使用一些JavaScript代码来处理拖动,那就很好了,请参见以下代码:

提示您可以使用本机设备水平滚动功能,例如MacBook触控板上的两指水平滚动,只需单击并拖动即可移动转盘水平

var slider = document.querySelector('.items');
var isDown = false;
var startX;
var scrollLeft;
slider.addEventListener('mousedown', function (e) {
  isDown = true;
  slider.classList.add('active');
  startX = e.pageX - slider.offsetLeft;
  scrollLeft = slider.scrollLeft;
});
slider.addEventListener('mouseleave', function () {
  isDown = false;
  slider.classList.remove('active');
});
slider.addEventListener('mouseup', function () {
  isDown = false;
  slider.classList.remove('active');
});
slider.addEventListener('mousemove', function (e) {
  if (!isDown) return;
  e.preventDefault();
  var x = e.pageX - slider.offsetLeft;
  var walk = (x - startX) * 3; //scroll-fast

  slider.scrollLeft = scrollLeft - walk;
});
@import url(https://fonts.googleapis.com/css?family=Rubik);
body,
html {
  color: #fff;
  text-align: center;
  background: #efefef;
  font-family: Helvetica, sans-serif;
  margin: 0;
}

.grid-container {
  background: #efefef;
  font-family: 'Rubik', sans-serif;
}

@supports (display: grid) {
  .grid-container {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: auto 1fr auto;
    grid-template-areas: "header header header" "title title footer" "main main main";
  }
  @media screen and (max-width: 500px) {
    .grid-container {
      grid-template-columns: 1fr;
      grid-template-rows: 0.3fr 1fr auto 1fr;
      grid-template-areas: "header" "title" "main" "footer";
    }
  }

  .grid-item {
    color: #fff;
    background: skyblue;
    padding: 3.5em 1em;
    font-size: 1em;
    font-weight: 700;
  }

  .header {
    background-color: #092a37;
    grid-area: header;
    padding: 1em;
  }

  .title {
    color: #555;
    background-color: #f4fbfd;
    grid-area: title;
  }

  .main {
    color: #959595;
    background-color: white;
    grid-area: main;
    padding: 0;
    overflow-x: scroll;
    overflow-y: hidden;
  }

  .footer {
    background-color: #5bbce4;
    grid-area: footer;
    padding: 0.6em;
  }

  .items {
    position: relative;
    width: 100%;
    overflow-x: scroll;
    overflow-y: hidden;
    white-space: nowrap;
    transition: all 0.2s;
    transform: scale(0.98);
    will-change: transform;
    user-select: none;
    cursor: pointer;
  }

  .items.active {
    background: rgba(255, 255, 255, 0.3);
    cursor: grabbing;
    cursor: -webkit-grabbing;
    transform: scale(1);
  }

  .item {
    display: inline-block;
    background: skyblue;
    min-height: 100px;
    min-width: 400px;
    margin: 2em 1em;
  }
  @media screen and (max-width: 500px) {
    .item {
      min-height: 100px;
      min-width: 200px;
    }
  }
}
a {
  display: block;
  color: #c9e9f6;
  text-decoration: underline;
  margin: 1em auto;
}
a:hover {
  cursor: pointer;
}

p {
  text-align: left;
  text-indent: 20px;
  font-weight: 100;
}

i {
  color: skyblue;
}
<div class="grid-container">
  <main class="grid-item main">
    <div class="items">
      <div class="item item1"></div>
      <div class="item item2"></div>
      <div class="item item3"></div>
      <div class="item item4"></div>
      <div class="item item5"></div>
      <div class="item item6"></div>
      <div class="item item7"></div>
      <div class="item item8"></div>
      <div class="item item9"></div>
      <div class="item item10"></div>
    </div>
  </main>
</div>

答案 1 :(得分:0)

对于 ReactJs 开发人员,我创建了一个很好的钩子来支持桌面水平滚动:

import { useEffect } from 'react';
import type { MutableRefObject } from 'react';

const useHorizontalScroll = (
  scrollWrapperRef: MutableRefObject<HTMLElement>,
  scrollSpeed = 1
): void => {
  useEffect(() => {
    const horizWrapper = scrollWrapperRef.current;
    let isDown = false;
    let startX: number;
    let scrollLeft: number;
    horizWrapper?.addEventListener('mousedown', (e: any) => {
      isDown = true;
      startX = e.pageX - horizWrapper?.offsetLeft;
      scrollLeft = horizWrapper?.scrollLeft;
    });
    horizWrapper?.addEventListener('mouseleave', () => {
      isDown = false;
    });
    horizWrapper?.addEventListener('mouseup', () => {
      isDown = false;
    });
    horizWrapper?.addEventListener('mousemove', (e: any) => {
      if (!isDown) return;
      e.preventDefault();
      const x = e.pageX - horizWrapper?.offsetLeft;
      const walk = (x - startX) * scrollSpeed;

      horizWrapper.scrollLeft = scrollLeft - walk;
    });
  }, [scrollSpeed, scrollWrapperRef]);
};

export default useHorizontalScroll;