首页 > 解决方案 > 如何实现与孙子的视差效果

问题描述

我之前在 codepen 和小型实验项目中实现了几次视差背景效果。

这是我最喜欢的教程 - https://keithclark.co.uk/articles/pure-css-parallax-websites/

这是参考教程中的标记:

<div class="parallax">
  <div class="parallax__layer parallax__layer--back">
    ...
  </div>
  <div class="parallax__layer parallax__layer--base">
    ...
  </div>
</div>

以及重要的 CSS 位:

.parallax {
  ...
  perspective: 1px;
}
.parallax__layer--base {
  transform: translateZ(0);
}
.parallax__layer--back {
  transform: translateZ(-1px);
}

基本上 -.parallax元素有一个透视图,这基本上意味着它可以在 3d 空间中查看事物。

.parallax__layer--base即前景层)位于0z 轴上。所以它并没有离开它的起源。

.parallax__layer--back背景层)在 z 轴上向后放置一个像素。

所以现在,当您滚动.parallax元素时,您可以看到这些背景和前景图层在 3d 空间中移动,从而产生视差效果。

但它只有在你滚动.parallax元素时才有效——在一个完整的、健壮的页面上怎么样?

<div class='home'>
...
  <div class="parallax">
    <div class="parallax__layer parallax__layer--back">
      ...
    </div>
    <div class="parallax__layer parallax__layer--base">
      ...
    </div>
  </div>
  ...
</div>

css 和标记没有改变。但现在我正在滚动.home元素,而不是.parallax元素。前景和背景层仍然在 3d 空间中,但它只是相对于.perspective元素。

有没有办法以某种方式将这种观点传递给主页的孙子或曾孙?或者我是否需要将整个页面分成前景和背景部分才能达到这种效果?

标签: htmlcss

解决方案


我想出了一种用 JavaScript 实现这一点的“hacky”方式。

这是步骤的概要(您可以将其称为算法):

  • 监听窗口滚动事件
  • 等到视差容器(您定义为base和的父级back)在视图中
  • 就我而言,我固定back并更改了过渡持续时间的top值。base

这是我的实现(特定于我的用例):

/**
 * hacky parallax effect
 */
const viewportHeight =
  'innerHeight' in window
    ? window.innerHeight
    : document.documentElement.offsetHeight

const headerHeight = document.querySelector('header').offsetHeight

window.onscroll = () => {
  const preFooterPosition = document
    .querySelector('.pre-footer')
    .getBoundingClientRect()

  /** start parallax when pre-footer is in view */
  if (
    preFooterPosition.top <= headerHeight &&
    preFooterPosition.bottom >= viewportHeight
  ) {
    // parallax
    document.querySelector('.content').classList.add('transform-content')
  } else {
    // reverse parallax
    document
      .querySelector('.content')
      .classList.remove('transform-content')
  }
}
.content {
  display: flex;
  flex-direction: column;
  flex: 1;
  z-index: 1;
  position: relative;
  top: 0;
  transition: top 1s ease;
}

.transform-content {
  top: -5rem;
}

.watermark {
  position: absolute;
  z-index: 0;
  flex: 1;
  display: flex;
}
<template>
  <section class="pre-footer">
    <div class="wrapper">
      <div class="watermark">
        <SVGIcon class="watermark-left" icon="LearnLongShort" />
        <SVGIcon class="watermark-right" icon="FreeEducation" />
      </div>
      <div class="content">
        <div class="content-left content-wrapper">
          <div>
            <h3 class="title">Evidence base</h3>
            <div class="body">
              <p>The Academy of Medical Cannabis Evidence Base is an advanced referencing tool for CBMP research. Containing the history of research to date and all emerging findings, this cutting-edge engine underpins our learning content.</p>
            </div>
            <WhiteButton text="View database" />
          </div>
        </div>
        <div class="content-right content-wrapper">
          <div>
            <h3 class="title">White Papers</h3>
            <div class="body">
              <p>Alongside our learning platform, The Academy publishes a series of authoritative papers discussing the core topics and themes related to CBMPs. Register to view and download the archive.</p>
            </div>
            <WhiteButton text="Archive" />
          </div>
        </div>
      </div>
    </div>
  </section>
</template>

我希望这会有所帮助。当您提出更好的解决方案时,请告诉我。与此同时,我正在推动这一点。

干杯!


推荐阅读