使用CSS3的Perspective属性创建3D感

最终产品图片
您将要创造的

在本教程中,我们将使用CSS3透视图属性创建一个交互式元素,以提供三个维度的感觉。 本教程还将教您如何将jQuery与鼠标事件结合使用,以获取JavaScript中的元素位置以及如何操纵CSS属性。

Perspective属性HTML结构

我们需要一个父子关系才能使Perspective属性正常工作。 首先创建HTML结构,然后继续CSS样式。

<div id="mainWrapper">
  <div id="cardsWrapper">
    
    <div class="card">
      <div class="image first">
        <div class="screen"></div>
        <div class="text">
            <p>Mountain</p>
            <p>5 Days</p>
        </div>
      </div>
    </div>
    
    <div class="card">
      <div class="image second">
        <div class="screen"></div>
        <div class="text">
            <p>Island</p>
            <p>2 Days</p>
        </div>
      </div>
    </div>
    
  </div>  
</div>

在这里,我们将两个card元素包装为具有cardsWrapper id的cardsWrapper 。 同样,此cardsWrapper被包装到另一个div中,以便能够轻松地在视口中操纵其位置。

card类别的每个元素都有一个image元素,其中包含screentext元素。 暂时的结构有点模糊,但是我将在相关的后续章节中解释每个元素的用法。

让我们使用以下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元素具有独立的透视效果。

如下调整cardCSS。

.card{
  width: 300px;
  height: 175px;
  background-color: red;
  perspective: 500px;
}

现在尝试向图像元素添加一个transform属性,以查看透视图的效果。

.image{
  width: 100%;
  height: 100%;
  background-color: red;
  transform: rotateX(30deg);
}

由于imagecard的直接子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中,然后设置screentext元素的样式。

让我们使用以下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.clientXe.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_minin_max参数分别是输入值的最小值和最大值,它们对应于card元素的宽度和高度。 out_minout_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);

现在我们的映射值是rXrY

下一步是通过使用映射值作为旋转值为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轴旋转rXrY度。

您将认识到卡元素在它们各自的角度中跟随光标。 但是,当光标离开卡片元素时,它们将保持其方向。 此外,它们突然对卡元素上的光标的存在做出反应。 因此,当鼠标进入和离开卡片元素时,我们还需要处理这些情况。

为了处理这些问题,我们需要使用mouseentermouseleave事件。

当鼠标进入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元素上时如何注册鼠标光标的位置。

最重要的是,我们使用mousemovemouseentermouseleave事件通过使用jQuery向HTML元素添加CSS规则来引入交互性。

希望您喜欢本教程并学到一些有用的方法。

翻译自: https://code.tutsplus.com/articles/creating-sense-of-3d-with-perspective-property-of-css3--cms-25393

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值