在本教程中,我们将使用CSS3透视图属性创建一个交互式元素,以提供三个维度的感觉。 本教程还将教您如何将jQuery与鼠标事件结合使用,以获取JavaScript中的元素位置以及如何操纵CSS属性。
Perspective属性HTML结构
我们需要一个父子关系才能使Perspective属性正常工作。 首先创建HTML结构,然后继续CSS样式。
Mountain
5 Days
Island
2 Days
在这里,我们将两个card
元素包装为具有cardsWrapper
id的cardsWrapper
。 同样,此cardsWrapper
被包装到另一个div中,以便能够轻松地在视口中操纵其位置。
card
类别的每个元素都有一个image
元素,其中包含screen
和text
元素。 暂时的结构有点模糊,但是我将在相关的后续章节中解释每个元素的用法。
让我们使用以下CSS样式来放置元素。
#mainWrapper{
display: flex;
justify-content: center;
align-items: center;
height: 350px;
}
#cardsWrapper{
display: flex;
justify-content: space-between;
width: 700px;
}
.card{
width: 300px;
height: 175px;
background-color: red;
}
.image{
width: 100%;
height: 100%;
background-color: red;
}
使用透视图属性
perspective
属性是您必须在父div中设置的属性,其中包含要以透视感进行变换的div。 想象一下,父div是您的世界,它具有您正在体验的某个透视图值。
让我们将perspective
属性添加到我们的父div(即card
。 我们将选择card
元素作为父元素,而不是cardsWrapper
,因为我们希望对每个card元素具有独立的透视效果。
如下调整card
CSS。
.card{
width: 300px;
height: 175px;
background-color: red;
perspective: 500px;
}
现在尝试向图像元素添加一个transform
属性,以查看透视图的效果。
.image{
width: 100%;
height: 100%;
background-color: red;
transform: rotateX(30deg);
}
由于image
是card
的直接子card
,因此它受透视图的影响。 但是,如果尝试将transform
属性添加到image
任何子级,则将无法正常工作。
为了使这些子项相对于其父项(在本例中为image
元素)进行transform-style: preserve-3d
,您应该在父元素上使用transform-style: preserve-3d
。
.image{
width: 100%;
height: 100%;
transform-style: preserve-3d;
transform: rotateX(30deg);
}
现在,我们在Perspective属性中具有足够的背景,并准备继续设计其他元素的样式。
不要忘记删除transform: rotateX(30deg)
从图像元素中transform: rotateX(30deg)
。
造型卡
我们有一个image
元素,在它上面我们有一个叫做screen
的元素,然后是text
。 由于我们在这里使用透视图,因此您可以将这些元素视为单独的图层。
现在,我们将背景图像添加到image
div中,然后设置screen
和text
元素的样式。
让我们使用以下CSS样式将背景图像添加到每个单个卡对象。
.image.first{
background-image: url("https://c1.staticflickr.com/1/343/31652757460_b2b5794a51_n.jpg");
}
.image.second{
background-image: url("https://c2.staticflickr.com/2/1506/25121644830_2d768ef51a_n.jpg");
}
现在我们将设置screen
元素的样式。
由于我们希望screen
元素与其父image
元素的大小完全相同,因此我们使用100%的宽度和高度值以及带有alpha通道的灰黑色背景色。
导入部分进行transform: translateZ(30px) scale(0.940)
。
因此,这里我们仅将screen
元素在Z轴上平移20px。 这使其悬停在image
元素上。 由于它是面向我们的,因此根据透视规则,它的大小将更大。 因此,我们将其缩小以使其尺寸与父元素匹配。 如果使用不同的转换值,则比例值将有所不同。 同样,为父元素定义不同的高度和宽度尺寸将导致要求不同的缩放值。
.screen{
background-color: rgba(0, 0, 0, 0.22);
width: 100%;
height: 100%;
transform: translateZ(30px) scale(0.940);
}
为了了解这里发生的情况,只需将以下行添加到CSS规则中,即可围绕X和Y轴旋转image
元素:
transform: rotateX(30deg) rotateY(30deg)
现在,本节的最后一部分是设置text
元素的样式,这很简单。
我们基本上对text
元素使用相同的转换设置,以使其与screen
元素处于同一级别。 其余CSS只是简单的样式。 您可以按照自己的方式进行调整。
.text{
position: absolute;
bottom: 25px;
left: 30px;
color: white;
transform: translateZ(30px) scale(0.940);
}
.text p{
cursor: default;
padding: 0;
margin: 0;
}
.text p:first-of-type{
font-size: 2em;
margin-bottom: 5px;
}
.text p:last-of-type{
font-size: 1em;
}
这是手动旋转以查看效果的最终结果。
在继续进行操作之前,请从CSS中删除旋转规则,因为我们将根据光标位置自动控制旋转。
现在,我们将编写一些jQuery代码,以使这些卡具有交互性。
让我们开始吧!
与jQuery添加交互
让我们从基本的jQuery代码开始。
(function($){
})(jQuery);
我们将在此函数中编写所有内容。 这将允许jQuery等待DOM准备就绪。
由于我们有兴趣与card
元素进行交互,因此需要选择它。
(function($){
var card = $(".card");
})(jQuery);
下一步是在卡元素上注册光标位置。 为此,我们将使用内置的mousemove
事件。
(function($){
var card = $(".card");
card.on('mousemove', function (e) {});
})(jQuery);
现在我们需要跟踪光标位置。 获取正确的值有点棘手。
(function($){
var card = $(".card");
card.on('mousemove', function (e) {
var x = e.clientX - $(this).offset().left + $(window).scrollLeft();
var y = e.clientY - $(this).offset().top + $(window).scrollTop();
});
})(jQuery);
在这里, e.clientX
和e.clientY
返回光标在视口内的位置。 但是,由于每个card
对象都相对于视口放置,因此我们需要通过提取左偏移值和顶偏移值来对此进行补偿。
最后要考虑的最重要的事情是对窗口滚动的补偿。 因此,由于光标位置是相对于视口注册的,但是偏移值是固定的,因此在滚动时,根据滚动方向,对象将更靠近视口的顶部或左侧。
结果,我们到视口顶部或左侧的相对距离将更小。 但是,由于偏移值是固定的,因此我们需要对此进行补偿,这可以通过$(window).scrollLeft()
和$(window).scrollTop()
。 因此,通过将这些值添加到各个变量中,我们只需补偿滚动量即可。 结果,当您将鼠标悬停在任何card
元素上时,您的X位置范围为0到卡片宽度(定义为300像素)。 同样,Y位置的范围是0到卡片的高度,即175px。
下一步是将光标位置映射到新的范围,该范围将是我们要应用的度数,以度为单位,这样当您的光标位于card元素的中间时,它看起来就很平坦,但是当您向左/向右或顶部/底部移动时,您将获得旋转效果,就像卡在光标之后一样。
这是映射功能结果的快速说明。
function map(x, in_min, in_max, out_min, out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
在此函数中, in_min
和in_max
参数分别是输入值的最小值和最大值,它们对应于card
元素的宽度和高度。 out_min
和out_max
是输入将映射的最小值和最大值。
让我们将此地图函数与X和Y光标位置一起使用。
(function($){
var card = $(".card");
card.on('mousemove', function (e) {
var x = e.clientX - $(this).offset().left + $(window).scrollLeft();
var y = e.clientY - $(this).offset().top + $(window).scrollTop();
var rY = map(x, 0, $(this).width(), -17, 17);
var rX = map(y, 0, $(this).height(), -17, 17);
});
function map(x, in_min, in_max, out_min, out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
})(jQuery);
现在我们的映射值是rX
和rY
。
下一步是通过使用映射值作为旋转值为image
元素设置CSS规则。
(function($){
var card = $(".card");
card.on('mousemove', function (e) {
var x = e.clientX - $(this).offset().left + $(window).scrollLeft();
var y = e.clientY - $(this).offset().top + $(window).scrollTop();
var rY = map(x, 0, $(this).width(), -17, 17);
var rX = map(y, 0, $(this).height(), -17, 17);
$(this).children(".image").css("transform", "rotateY(" + rY + "deg)" + " " + "rotateX(" + -rX + "deg)");
});
function map(x, in_min, in_max, out_min, out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
})(jQuery);
在这里,我们选择了card
元素的子元素,命名为image
,然后设置CSS规则以将该元素分别绕X和Y轴旋转rX
和rY
度。
您将认识到卡元素在它们各自的角度中跟随光标。 但是,当光标离开卡片元素时,它们将保持其方向。 此外,它们突然对卡元素上的光标的存在做出反应。 因此,当鼠标进入和离开卡片元素时,我们还需要处理这些情况。
为了处理这些问题,我们需要使用mouseenter
和mouseleave
事件。
当鼠标进入card
元素的区域时,我们向image
元素添加了一个过渡CSS规则。 这将使image
元素的“凝视”平滑过渡。
card.on('mouseenter', function () {
$(this).children(".image").css({
transition: "all " + 0.05 + "s" + " linear"
});
});
同样,我们需要处理mouseleave
事件。
在这里,我还添加了另一个具有不同定时的过渡CSS规则,当鼠标离开card
元素时,它可以更平滑地过渡到初始位置。
我还添加了transform CSS规则,以重置card
元素的旋转。
card.on('mouseleave', function () {
$(this).children(".image").css({
transition: "all " + 0.2 + "s" + " linear"
});
$(this).children(".image").css("transform", "rotateY(" + 0 + "deg)" + " " + "rotateX(" + 0 + "deg)");
});
因此,我们最终的jQuery代码如下所示:
(function($){
var card = $(".card");
card.on('mousemove', function (e) {
var x = e.clientX - $(this).offset().left + $(window).scrollLeft();
var y = e.clientY - $(this).offset().top + $(window).scrollTop();
var rY = map(x, 0, $(this).width(), -17, 17);
var rX = map(y, 0, $(this).height(), -17, 17);
$(this).children(".image").css("transform", "rotateY(" + rY + "deg)" + " " + "rotateX(" + -rX + "deg)");
});
card.on('mouseenter', function () {
$(this).children(".image").css({
transition: "all " + 0.05 + "s" + " linear",
});
});
card.on('mouseleave', function () {
$(this).children(".image").css({
transition: "all " + 0.2 + "s" + " linear",
});
$(this).children(".image").css("transform", "rotateY(" + 0 + "deg)" + " " + "rotateX(" + 0 + "deg)");
});
function map(x, in_min, in_max, out_min, out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
})(jQuery);
这是最终结果。 我还在text
元素上使用了不同的sans-serif字体,以使其看起来更好。
结论
在本教程中,我们学习了如何使用Perspective属性和所需HTML结构来使其正常工作。 此外,我们介绍了将鼠标悬停在特定HTML元素上时如何注册鼠标光标的位置。
最重要的是,我们使用mousemove
, mouseenter
和mouseleave
事件通过使用jQuery向HTML元素添加CSS规则来引入交互性。
希望您喜欢本教程并学到一些有用的方法。
翻译自: https://code.tutsplus.com/articles/creating-sense-of-3d-with-perspective-property-of-css3--cms-25393