以下是 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!
非常棒的技术。我以前从未想过以这种方式使用视差效果。也许作为一种更“有趣”的用法,可以在一幅画上画一对眼睛,跟随用户:P 令人毛骨悚然!
真的很酷。而且在 IE 中看起来还可以!:-) 谢谢
非常酷。
对我来说有点俗气。
是的,看起来很棒!!在 IE 中测试过,看起来也很棒!感谢你的帖子
看起来很棒!
但我没有看到它可以在真实的客户端网站上使用。
酷!尽管我认为,对于那些没有获得这种效果的人来说,他们会说“哇,每次我滚动时文本框都会变得乱七八糟!”
很棒的效果!我不是很喜欢这个网站周围的那些 3D 元素,我更喜欢在我的设计中使用平面元素,但这段代码在某种 3D 书架中会看起来很棒。
我只有一个问题——在您的代码中,您两次“获取”了 window 元素而没有缓存它——将其缓存到函数块之外不是更好吗?或者,每次(以及两次)获取它不是一个很大的性能问题吗?
你的意思是像这样…
http://cdpn.io/xhzFC
是的,窗口高度可以在 each 函数之外设置。我已经更新了 Pen。
我还将 window 元素变成了顶部的变量。
我想你应该也缓存 inset,而不是在每次滚动事件中都重新选择它们
http://codepen.io/anon/pen/Ddhnz
说得对。
哦,再挤一点——实际上不需要使用 Math.round(),对吧?
我真的不喜欢它,通常我总是让我的眼睛在滚动时看着网页上的同一个地方,而且我相当确定大多数人都是这样做的。所以效果不明显,甚至感觉很奇怪和有故障:/
顺便说一句,眼动追踪毫无用处,即使你移动眼睛,视差也不会改变。你必须改用头部追踪。就像那个第三个视频:http://johnnylee.net/projects/wii/
@scarfacedeb
嘿,这是常识,你可以在你的客户网站上使用它,使它更有价值、设计更优雅、风格更时尚。
嘿,Chris,新的 Outlook 邮件我认为不换行,这使得阅读你的 Feed 变得非常困难。你能为此包含一行 CSS 吗?因为交给微软,它永远不会发生。
在“编辑注”中,鼠标视角示例在 codepin 上有效,但当我复制粘贴到单独的 html、css 和 script.js 文件中时却无效。使用相同的浏览器(Chrome)。还尝试过使用前缀 -webkit-perspective 和 -webkit-transform:rotate,但页面只是加载为一堆白色方块,因此甚至没有显示初始透视:80px,尽管它在开发者工具下加载了样式。在开发者工具中查看,我看到 -webkit-perspective-origin 在我移动鼠标时发生了变化,但页面本身并没有改变。
有人知道为什么它在 codepin 上有效,但在实际的 html 页面上无效吗?
谢谢
哎呀,错拼了 codepen 两次 :-)
很棒的想法,即使我认为深度效果有点太强,在视觉上不太吸引人。
无论如何,代码非常轻量级,这很好。:)
要获得不太剧烈的影响,请尝试使用更小的边框宽度。
这真是太棒了。谢谢!但是,我不得不说,您依赖 JavaScript 来设置页面上元素的样式。
作为一名尝试仅用 CSS 实现这种效果的人,我能够理解这里对 JavaScript 的需求。敬佩!
可爱的小把戏。
呵呵…这太棒了…非常感谢
这真的非常棒,尤其对于那些不是创建此类效果的向导的人来说。
我花了 10 分钟的集中注意力才弄明白这里有什么大不了的——但现在我明白了。我可能有点迟钝,但可以用讽刺来弥补。这里的效果几乎太微妙了,但我看到了它可以用来做一些很酷的网页特效的地方。去 CodePen 看看。谢谢,Chris。
+brian
它非常微妙,我不得不滚动几次才能注意到它(或者更确切地说,真正地“看”它 ;)),对我来说,任何微妙的东西都是技能组合中不错的补充,可能有一天会派上用场,也可能不会。但是,视差效果的例子越多,我们对它的动态理解就越深刻。
有一个小错误——页面高度会根据你在页面中的位置而变化。
要查看它,请滚动到最底部,然后向上拖动滚动条手柄——你会注意到手柄的大小减小,并且与你的鼠标不同步。
事实证明,当内嵌元素超出屏幕并且其中一个边框为 0px 时,另一个边框(底部或顶部)会无限增长。在较大的页面上,这将是一个严重的问题。
非常棒,但使用 JavaScript 使它有点繁琐。
嗨,我需要将所有代码都放到我的网页上吗?html、js 和 css?谢谢
超级酷!我不确定我是否喜欢内嵌内容与标题“位于”内嵌内容外部的效果。看起来有点奇怪。我当然可以看到一些设计理念以很酷的方式实现这一点。我正在考虑从页面上的 A 点到 B 点平滑的自动滚动。如果你用滚动条手柄而不是鼠标滚轮来滚动,效果看起来非常棒。
感谢分享!!好消息是它在 IE8 中也能工作。
在 IE 和 FF 上尝试并测试。效果很好。这真的很棒。谢谢