前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CSS魔法|MagicDesign - CSS实现3D拐角轮播图

CSS魔法|MagicDesign - CSS实现3D拐角轮播图

作者头像
源心锁
发布2022-09-21 14:45:41
1.2K0
发布2022-09-21 14:45:41
举报
文章被收录于专栏:前端魔法指南

1 前言

大家好,我是心锁,一枚23届准毕业生。

近期我正在尝试完成所谓的「拐角轮播」,目前拐角的部分已经完成了百分之七八十,所以我们来解析一下如何实现这种CSS 3D效果

2 演示

这里是体验链接,给各位大佬呈上https://grinzero.github.io/magic-design-react/swiper/corner-swiper

当然效果有些残缺哈......

别急着走嘛,我们虽然没有原图在拐角处实现的那么丝滑,但是也算是实现了方案中的3D容器方案

那我究竟是怎么把卡片3D化的呢?

(补充码上掘金的简易版本) 代码片段

3 3D折叠容器实现

众所周知,起码截止目前为止,CSS并不支持把单一一个页面元素折叠成曲面或者说部分折叠。

在这个基础上,我们必定需要使用到多个元素叠加。

3.1 基本框架

我们得到这样一份基本框架

代码语言:javascript
复制
<div className="swiper-container">
    <div
        className="mg-w-full mg-h-full mg-relative corner-swiper"
        ref={listRef}
    >
        这里放SwiperItem
    </div>
</div>

我们暂时不需要知道swiper-container属性,我们现在仅需要关注SwiperItem的上层,我们在这里实现3D容器,而在swiper-container只实现Swiper的滑动功能。

我们在corner-swiper真正实现3D容器

3.2 容器的切割拼接

众所周知,圆形是可以由无数个正多边形拼合形成的

而我实现3D容器的思路就是切割,我目前将3D容器切成了两份,通过absolute叠加在一起,这里的实现并不麻烦,是absolute的应用,就不贴代码了。

再接着就是切割

我们要用到的CSS属性是clip-path,如图的三份元素切片的实现,我们借助clip-path是比较容易实现的

代码语言:javascript
复制
.swiperElement1{
  clip-path:polygon(0% 0, 20% 0, 20% 100%, 0% 100%);
}
.swiperElement2{
  clip-path:polygon(20% 0, 26% 0, 26% 100%, 20% 100%);
}
.swiperElement3{
  clip-path:polygon(26% 0, 100% 0, 100% 100%, 26% 100%);
}

可以看到,我们通过polygon函数将各个元素按照百分比切割成了三份,这三个元素可以完整地拼成原本的容器

当然,可能是浏览器原因,拼接之间会存在一条白线

我们可以通过translateX属性从右到左渐进的+1px来隐藏这条白线

代码语言:javascript
复制
.swiperElement1{
  clip-path:polygon(0% 0, 20% 0, 20% 100%, 0% 100%);
  transform:translateX(2px);
}
.swiperElement2{
  clip-path:polygon(20% 0, 26% 0, 26% 100%, 20% 100%);
  transform:translateX(1px);
}
.swiperElement3{
  clip-path:polygon(26% 0, 100% 0, 100% 100%, 26% 100%);
  transform:translateX(0px);
}

那么现在3D容器的切割拼接就完毕了,接下来我们要将容器3D化。

3.3 容器3D化

说到3D化,我们将使用到transform3D系列的属性,我可以先列举一下我们用到的属性

  • perspective
  • perspective-origin
  • transform-style: preserve-3d
  • transform: rotateX、rotateY
  • transform-origin

3.3.1 perspective

perspective,透视,是CSS 3D的基础,transform-styleperspective任意一个属性不配置都不会产生3D效果。

根据MDN的解释,perspective指定了观察者(也就是我们)和屏幕z之间的距离

可以在这个链接感受一下https://developer.mozilla.org/zh-CN/docs/Web/CSS/perspective

3.3.2 perspective-origin

而perspective-origin操控透视的视角

我们可以通过该属性控制拐角的弧度

需要注意,两个透视相关需要放在父容器

3.3.3 transform-style

其中transform-style最为简单,指定transform变换的类型是3D模式

代码语言:javascript
复制
.swiperElement1{
  clip-path:polygon(0% 0, 20% 0, 20% 100%, 0% 100%);
  transform:translateX(2px);
  transform-style:preserve-3d;
}
.swiperElement2{
  clip-path:polygon(20% 0, 26% 0, 26% 100%, 20% 100%);
  transform:translateX(1px);
  transform-style:preserve-3d;
}
.swiperElement3{
  clip-path:polygon(26% 0, 100% 0, 100% 100%, 26% 100%);
  transform:translateX(0px);
  transform-style:preserve-3d;
}

3.3.4 transform: rotateX、rotateY

transform中的rotateX、rotateY都是3D旋转,这两种旋转在3d模式是什么表现呢?我这里给些例子

  • rotateX

这里是45deg角度的X轴旋转,我们可以看到x轴的表现如图

  • rotateY

而这是y轴旋转,我们会发现目前y轴在最中心,从展示角度来讲这是正确的,但是实际中我们需要把原点移动。

这也就引申出来了transform-origin

3.3.5 transform-origin

在上述例子中,我们改变的是swiperElement1,而swiperElement1是在20%的地方做了切割

所以我们把y轴对准20%,这样我们就可以将y轴搬运到20%这里

代码语言:javascript
复制
.swiperElement1{
  clip-path:polygon(0% 0, 20% 0, 20% 100%, 0% 100%);
  transform:translateX(2px);
  transform-style:preserve-3d;
  transform-origin:20%;
}

3.4 再次拼接

我们会发现,如果我们给swiper1,swiper2配置了3D化之后,第三个元素和前边就接不上了。

这是很显然的问题,因为前两个元素拼接之后,第二个元素的最右方z轴实际上是上移了

所以我们需要计算出Z轴移动了多少,将前边所有的元素或者后边的元素移动回去

对于我们正在做的demo来说,目前代码是这样的

代码语言:javascript
复制
.swiperElement1{
  clip-path:polygon(0% 0, 20% 0, 20% 100%, 0% 100%);
  transform:translateX(2px);
  transform-style:preserve-3d;
  transform:translateX(2px) rotateY(-45deg);
  transform-origin:20%;
}
.swiperElement2{
  clip-path:polygon(20% 0, 26% 0, 26% 100%, 20% 100%);
  transform:translateX(1px);
  transform-style:preserve-3d;
  transform:translateX(1px) rotateY(-22.5deg);
  transform-origin:20%;
}
.swiperElement3{
  clip-path:polygon(26% 0, 100% 0, 100% 100%, 26% 100%);
  transform:translateX(0px);
  transform-style:preserve-3d;
  transform:translateX(-3px) translateZ(17.25px);
}

可以看到swiperElement3,存在属性transform:translateX(-3px) translateZ(17.25px);

这其中的translateX(-3px) translateZ(17.25px)是怎么计算的呢?

我们俯视得到透视图

那么现在我们只需要建模出X的计算公式和Z的计算公式,我们可以假设全长为“1”。

注意上图的所有蓝色字体均指x轴宽,而不是直接长度

...

看到这里你是不是以为我算出来了

....

不,我不太想算了

咱把思路已经给得很明白了,亲爱的读者你动动手啊,直接告诉我答案,我要白嫖答案

4 数据建模

虽然我没有对三个元素叠加进行建模,不过我做了两个元素的建模

如图,将clip-path的部分属性和transform-origin通过CSS变量var(--position)来绑定。

同时在之前提到的swiper-container层通过translateX来控制Swiper的「切换current操作」

之所以最终没有做3个面乃至于多个面的建模,一方面是麻烦,一方面是实现效果上。

三个元素的叠加其实效果并没有说特别好,而往上走到5、6或者更多元素叠加,其实对于网页的性能是会产生一定压力的。

那么,我们最终得到~

5 总结

那么我们实践完这个堪称变态的拐角轮播,学习到了什么呢?

  • 一个复杂动画的实现需要一定的数学建模
  • CSS 3D的作用条件以及X、Y、Z轴的实际作用展现
  • clip-path与不同的orgin的实际作用展现

当然~如果亲只想试试这个效果,打开https://grinzero.github.io/magic-design-react/即可体验

(文档刚刚写,组件也不是很完善,还很简陋,见谅见谅)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 前言
  • 2 演示
  • 3 3D折叠容器实现
    • 3.1 基本框架
      • 3.2 容器的切割拼接
        • 3.3 容器3D化
          • 3.3.1 perspective
          • 3.3.2 perspective-origin
          • 3.3.3 transform-style
          • 3.3.4 transform: rotateX、rotateY
          • 3.3.5 transform-origin
        • 3.4 再次拼接
        • 4 数据建模
        • 5 总结
        相关产品与服务
        图像处理
        图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档