3D按钮视差

Avatar of Alexander Futekov
Alexander Futekov

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

以下是 Alexander Futekov 的客座文章。我们最近发布了 一篇文章,作者是 Joshua Bader,文章中介绍了随着页面滚动调整 3D 内嵌外观以获得更真实的交互效果。这与 Alexander 在按钮上使用挤出外观并采用完全不同的技术的做法类似。

CSS3 的引入导致了美观且有趣的按钮的爆发,这些按钮使用渐变、阴影和边框进行样式化,通常是为了实现 3D 效果。此类 3D 按钮的问题在于透视角度是静态的。当您只能看到其正面以及可能的一两个边缘时,3D 效果并不总是非常令人信服,即使页面移动且按钮在页面上的位置发生变化也是如此。

幸运的是,我们可以借助 3D 变换来调整按钮的侧面,从而实现逼真的透视效果。我们可以通过使用伪元素来创建侧面,而无需修改现有的 HTML。然后使用 translateZ 将按钮本身向前移动。

在开始之前,我们必须首先解决一个问题。透视原点通常设置为元素的垂直和水平中心。这意味着当我们根据主体设置它时,我们将得到如下所示的内容

通过将主体的 height 设置为 100%,我们可以将透视原点固定到视口的中心,如下所示

html {
  height: 100%;
  overflow: hidden;
}

body {
  height: 100%;
  overflow-y: scroll;
}

对于一个简单的 <button>,以下是 CSS 代码

button {
  position: relative;
  display: inline-block;
  padding: 4px 16px;
  border: 0;
  background-color: blue;
  background-image: radial-gradient(ellipse at top, rgba(255, 255, 255, 0.15) 50%, transparent);
  color: #222;
  transform-style: preserve-3d;
  transform: translateZ(20px);
}

button::before {
  content: "";
  position: absolute;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
  transform-origin: 0% 0%;
  transform: rotateX(-90deg);
}

button::after {
  content: "";
  position: absolute;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
  transform-origin: 0% 0%;
  transform: rotateY(90deg);
}

但是我们如何仅使用 2 个伪元素为每个按钮获取 4 个侧面呢?JavaScript!如果我们想避免为每个按钮添加额外的包装器(我们确实需要),则需要使用脚本根据按钮相对于用户视口的位置将顶部向下移动,将左侧向右移动。切换按钮顶部和底部的脚本非常简单 - 更改顶部/底部或左右侧仅在加载和调整大小时发生,而顶部/底部仅在滚动时发生

$(window).on("load resize", function() {
  topHalf();
  leftHalf();
});

$("body").scroll(function() {
  topHalf();
});

function topHalf() {
  $("button").each(function() {
    var self = $(this),
        offTop = self.offset().top,
        scrTop = $(window).scrollTop(),
        halfWindowHeight = ($(window).height())/2;

    self.toggleClass("top-half", (offTop - scrTop) < halfWindowHeight);
  });
}

function leftHalf() {
  $("button").each(function() {
    var self = $(this),
        offLeft = self.offset().left,
        halfWindowWidth = ($(window).width())/2;

    self.toggleClass("left-half", offLeft < halfWindowWidth);
  });
}

编辑注: 这当然可以进行一些重构以增强结构并提高效率。随时可以分叉下面的 Pen 并尝试一下!

一些新类将有助于定位侧面

button.top-half::before {
  top: auto;
  bottom: 0;
  transform-origin: 100% 100%;
  transform: rotateX(90deg);
}

button.left-half::after {
  left: auto;
  right: 0;
  transform-origin: 100% 100%;
  transform: rotateY(-90deg);
}

请记住,如果您使用类来浮动按钮(例如 Twitter Bootstrap 中的 .pull-left.pull-right),您将知道每个按钮在水平方向上的位置,从而能够跳过一半的 JavaScript 代码。

这是一个可供您体验的样式化演示。它为按钮提供了一个动画向下推效果,并包含一些不需要任何 JavaScript 的其他 3D 元素

Check out this Pen!

类似的技术也可以用来以非常粗略的方式复制 3D 内嵌视差效果。它稍微复杂一些,但不需要任何 JavaScript

Check out this Pen!