3D 内嵌视差效果

Avatar of Josh Bader
Josh Bader

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费积分!

以下是 Joshua Bader 的客座文章。Joshua 发现,网络上的某些 3D 效果可以从调整网页滚动时的透视效果中获益。我让他来解释一下。

人们喜欢使平面事物看起来像是三维的。在二维环境中实现这种效果有两种方法:形状和运动。

通过赋予平面形状边缘或侧面的外观,我们可以使按钮或其他对象看起来像是凸起或凹陷到屏幕中。即使在 CSS-Tricks 上也能看到这一点。

运动效果有点棘手。在三维世界中,靠近你的物体移动速度快,而远离你的物体移动速度慢。物体越远,移动速度越慢。这被称为 视差效应。视差效应在过去几年中被用于 各种 地方

第一种方法(形状)之所以有效,是因为它使事物看起来像是凸出或远离你。第二种方法(运动)之所以有效,是因为它使事物看起来像是彼此之间具有位置关系。但是,如果我们把它们结合起来呢?一个看起来凹陷到屏幕中的物体,比如一个架子,它的边缘会收缩和放大,利用视差效果,使物体看起来像是真的处于 3D 空间中。

首先,我们需要在页面上添加一些标记,并为我们想要影响的项目赋予 inset 类。任何块级元素都可以。这是一个带有输入的简单表单,将应用该效果。

<form>

  <label>
    First Name:
    <input class="inset" type="text" placeholder="Enter First Name" />
  </label>

  <label>
    Last Name:
    <input class="inset" type="text" placeholder="Enter Last Name" />
  </label>

  <label>
    Email Address:
    <input class="inset" type="text" placeholder="Enter Email Address" />
  </label>

  <label>
    Address:
    <input class="inset" type="text" placeholder="Enter Address" />
  </label>

  <label>
    Phone Number:
    <input class="inset" type="text" placeholder="Enter Phone Number" />
  </label>

</form>

接下来,我们需要为我们的 inset 元素设置样式。通过赋予项目略微不同的颜色边框,我们可以使元素产生深度的错觉。这是因为边框之间的连接是一个角度,并且由于不同的颜色,它看起来像是光线照射到 3D 区域的不同“侧面”。这是我们之前提到的“形状”方法。

.inset {
  width: 100%;
  box-sizing: border-box;
  background: #f9f9f9;
  border-style: solid;
  border-width: 30px;
  border-top-color: #e5e5e5;
  border-right-color: #eee;
  border-bottom-color: #e5e5e5;
  border-left-color: #eee;
}

现在我们想要操作的形状已经设置了样式,我们可以使用一些简单的 jQuery 来获取元素的原始边框宽度、窗口高度、滚动位置、目标元素在屏幕上的位置,并将该位置转换为顶部边缘和底部边缘的百分比。

var origBorderWidth = parseInt($('.inset').css('border-top-width')),
win = $(window),
windowHeight = win.height();

$('.inset').each(function() {
  var self = $(this),
    scrollHeight = win.scrollTop(),
    elementPosition = self.position(),
    positionPercentTop = Math.round((elementPosition.top - scrollHeight) / windowHeight * 100);
    positionPercentBottom = Math.round((elementPosition.top + self.outerHeight() - scrollHeight) / windowHeight * 100);
});

一旦我们将所有这些数字作为变量,我们就可以根据每个元素在屏幕上的位置调整其顶部和底部边框宽度。

var origBorderWidth = parseInt($('.inset').css('border-top-width')),
win = $(window),
windowHeight = win.height();

$('.inset').each(function() {
  var self = $(this),
    scrollHeight = win.scrollTop(),
    elementPosition = self.position(),
    positionPercentTop = Math.round((elementPosition.top - scrollHeight) / windowHeight * 100);
    positionPercentBottom = Math.round((elementPosition.top + self.outerHeight() - scrollHeight) / windowHeight * 100);

  self.css({
    'border-top-width' : origBorderWidth - (origBorderWidth * (positionPercentTop / 100)) + 'px',
    'border-bottom-width' : origBorderWidth * (positionPercentBottom / 100) + 'px'
  });
});

现在到了有趣的部分——在页面滚动时重新计算每个元素的顶部和底部边框宽度。这将为我们提供所需的视差“运动”效果。

var origBorderWidth = parseInt($('.inset').css('border-top-width')),
  win = $(window);

function set3D() {
  var windowHeight = win.height();

  $('.inset').each(function() {
    var self = $(this),
      scrollHeight = win.scrollTop(),
      elementPosition = self.position(),
      positionPercentTop = Math.round((elementPosition.top - scrollHeight) / windowHeight * 100);
      positionPercentBottom = Math.round((elementPosition.top + self.outerHeight() - scrollHeight) / windowHeight * 100);

    self.css({
      'border-top-width' : origBorderWidth - (origBorderWidth * (positionPercentTop / 100)) + 'px',
      'border-bottom-width' : origBorderWidth * (positionPercentBottom / 100) + 'px'
    });
  });
};

win.on('load scroll resize', function() {
  set3D();
});

就是这样。要查看效果,请在滚动时将目光停留在某个元素上,并观察它在页面上上下移动。您将看到它的顶部和底部边框宽度根据它在页面上的位置而变化。它很微妙,但很有效。

Check out this Pen!
编辑注:非常棒,不是吗?也许使用更多技术,我们可以创建一个演示,该演示可以进行眼动追踪,并根据您的眼睛相对于屏幕的位置调整视角。这是一个根据鼠标调整视角的另一个示例