本文为原创,转载请注明出处: cnzt       文章:cnzt-p

  写在前面:最近写了个3d轮播效果图,在此将思路和过程中遇到的问题都记录下来。


首先,我们下来了解一下perspective和transform都是做什么的。

    transform -- css3属性,可以对元素进行变换(2d/3d),包括平移translate,旋转rotate,缩放scale,等等(完整取值参考 W3C)。

    perspective -- css3属性,当元素涉及3d变换时,perspective可以定义我们眼睛看到的3d立体效果,即空间感。通俗地解释就比如你去电影院看电影,你距离大荧幕的距离就相当于perspective的值啦,离得越远则perspective值越大,看到空间效果也就会不一样!

接下来,我们就进入正题了。

    先上3d轮播图效果图:

   

                  图一

   

                    图二

              

    

                   图三

  ***图一为前一张轮播图,图二是轮播图前后切换时的3d效果图,图三为后一张轮播图***

实现上面的效果,需要三层页面结构:

  1. 最外面的容器.swiper-wrapper,即图中天蓝色边框这个部分。为这部分设置关键css如下:

    transform-style: preserve-3d; //3d旋转效果
    perspective: 1000px; //3d立体空间感
    perspective-origin: 50% 50%; //观察视角, 50% 50%代表从中间观察

  2. 用ul包裹的li多边体。参考图二可知,我们的每张图片实际上是由n个片段拼接而成,这是怎么实现的呢?很简单,多个li + background-position定位轻松实现啦;

  3. li里的div数组,数组的长度等于轮播图的总张数。这个div数组将所有的图片围绕x轴形成了一个多边体。完整多边体效果如图四:

        

                        图四

  那么怎么实现这个多边体呢?这就要用到今天的transform属性了。假设一个多边体有m条边,每个div平面代表一条边(即每张图片的1/n),我们先将每个div平面绝对定位到li的左上角(left:0;top:0;),此时的每个div平面都在x轴与y轴形成的平面上,也就是电脑屏幕平面上。接下来我们将每个div平面依次进行变换transform: rotateX((360/m)*i deg) translateZ(z轴位移量),先围绕x轴依次旋转(默认旋转点是平面中心,可以通过transform-origin设置,我们就是用默认值)(360/m)*0、 (360/m)*1 、(360/m)*2 、... 、直到(360/m)*(m-1),这样形成的下面的效果,图五:

        

                        图五

  咦?不是多边体么?别急,接下里translateZ(z轴位移量)登场了,这个值是多少自己拿小本本算去... 反正是每个边到中心点的垂直距离... ok, 看一下每个边平移后的效果吧,图六:

          

                         图六

  怎么超前的几个面变这么大了?都超出粉色的框框了... 没错,这就是平移translateZ产生的效果,立体地看,就是前面的几个面都跑到电脑屏幕外面了,后面的几个面跑到电脑屏幕后面了。还不明白?就是说电脑屏幕沿着这个多边形的中点,并且从多边形的垂直方向穿透过去了。还不明白的话我也没辙了...闭眼想像去吧...

  (tips: 以面对电脑屏幕的视角看,假设一个平面在屏幕上,则向右为其x轴正向,向下为其y轴正向,向屏幕外为其z轴正向。且当这个平面旋转时,他的3个轴也跟着旋转。)

  那怎么让最外面的图片放到电脑屏幕的平面上呢?聪明的人都知道了,把li代表的多边形整体translateZ(z轴位移量)不就行啦!来看下效果图,往上看,再往上看,再往上看,对了,就是图四的效果了...

  接下来给ul整体设置overflow:hidden;隐藏多出粉色边框的部分,就看到图一的效果了~

  

下方轮播图切换点的控制:

  这个就很简单了,有m张图,就放m个点。点击第一个点(也是默认情况),将每个li绕x轴旋转(360/m)*0度;点击第二个点,将每个li绕x轴旋转(360/m)*1度;... 直到点击第m个点,将每个li绕x轴旋转(360/m)*(m-1)度。接下来,我们再给每个li多边体加上过渡transition:1s;transition-delay: (0.6 * (i-1))s; 这样就有每个li依次翻转的过渡效果啦。这里划重点:每个li翻转3d效果还要加上transform-style:perserve-3d; 然后聪明的你又知道了,对,就是图二的效果了~

perspecitve到底什么鬼?

  说了这么多,效果都实现了,我咋还不讲perspective呢?别急,这不是来了嘛... 如文章一开始所说,perspective会让你看到一种3d立体空间感,而非二位平面的体验了。本例中的perspective用在了class=‘swiper-wrapper’的蓝色边框元素上,赋值perspective:1000px; 它的取值越小,你在电影院的座位越靠前,视觉效果越近;反之,取值越大,你在电影院座位约靠后,视角越远。实际应用中,800-1000px效果较好,相当于电影院四五排的座位,got it?聪明的人一定get了... 下面上对比效果图:

完整代码如下:

HTML:

 <div class="swiper-wrapper">
<ul id="swiper" class="swiper"></ul>
<div id="dotlist" class="dots"></div>
</div>

CSS:

 .swiper-wrapper{
width: 600px;
height: 350px;
margin-top: 100px;
padding: 10px;
box-shadow: 0px 0px 10px 5px skyblue;
transform-style: preserve-3d;
perspective: 1000px;
perspective-origin: 50% 50%;
}
.swiper-wrapper ul{
position: relative;
width: 600px;
height: 300px;
box-shadow: 0px 0px 10px 2px pink;
overflow: hidden;
/*transform:translate/rotate(0px/deg); 若加这个属性,则3d效果消失。*/
}
.swiper-wrapper ul li{
position: absolute;
height: 300px;
transform-style: preserve-3d;
transform-origin:0px 50% 0px;
transform: rotateX(0deg);
transition: transform 1s;
}
.swiper-wrapper ul li div{
position: absolute;
left:;
top:;
width: 100%;
height: 100%;
background-repeat: no-repeat;
}
.swiper-wrapper .dots{
height: 46px;
box-shadow: 0px 0px 10px 2px pink;
text-align: center;
}
.dots span{
display: inline-block;
width: 10px;
height: 10px;
margin: 10px;
background-color: pink;
border-radius: 10px;
transition: all .5s;
}
.dots span.selected{
background-color: red;
}

JS:

 <script>
var img_num = 6;//li下的div个数,即z平面上多边盒的边数
var cut_num = 6;//li个数,每个li代表切割的一块 var ang = 360/img_num;//每张图片旋转的角度
var ele_swiper = document.getElementById("swiper");
var ele_dotlist = document.getElementById("dotlist");
var ele_li;
var ele_div;
var ele_dot;
var swiperWidth = ele_swiper.clientWidth;//整个swiper区域的宽度
var width_li = swiperWidth/cut_num;//每个li的宽度
var tranZ_dist = 260;//每张轮播图rotate之后要向z轴平移的距离
var imgChosenId = 0;//初始显示第几张轮播图 for (var i = 0; i < cut_num; i++) {//遍历li
ele_li = document.createElement("li"); for (var j = 0; j < img_num; j++) {//遍历div
//动态创建图片div
ele_div = document.createElement("div");
ele_li.appendChild(ele_div);
ele_div.style.backgroundImage = "url(images/"+(j+1)+".jpg)";
ele_div.style.backgroundSize = swiperWidth+"px 300px";//图片宽度等于swiper区域宽度
ele_div.style.backgroundPosition = (swiperWidth/cut_num)*i*(-1) + "px 0";//图片定位
ele_div.style.transform = "rotateX("+ang*j+"deg) translateZ("+tranZ_dist+"px)";
} ele_swiper.appendChild(ele_li);
ele_li.style.width = width_li+"px";
ele_li.style.left = width_li*i+"px";
(i > cut_num/2-1) && (ele_li.style.zIndex = (cut_num-i)*10);
ele_li.style.transform = "translateZ("+tranZ_dist*(-1)+"px) rotateX("+ang*imgChosenId+"deg)"; //设置初始li翻转角度
} //动态创建轮播点按钮
for (var j = 0; j < img_num; j++) {
ele_dot = document.createElement("span");
ele_dot.setAttribute("idx",j);
ele_dotlist.appendChild(ele_dot);
if(j == imgChosenId){
ele_dot.className = "selected";
}
} //点击切换轮播图
ele_dotlist.onclick = function doSwiper (e) {
var targetNode = e.target;
var idx;
var swipeNode;
if(targetNode.nodeName === "SPAN"){
for (var ii = 0; ii < this.childNodes.length; ii++) {
this.childNodes[ii].className = "";
};
targetNode.className = "selected";
idx = targetNode.getAttribute("idx"); for (var z = 0; z < cut_num; z++) {//遍历li /*for (var zi = 0; zi < img_num; zi++) {//遍历div
ele_swiper.childNodes[z].childNodes[zi] }*/ swipeNode = ele_swiper.childNodes[z];
swipeNode.style.transform = "translateZ("+tranZ_dist*(-1)+"px) rotateX("+ang*idx+"deg)";
swipeNode.style.transitionDelay = 0.3*z+"s";
} }
} </script>

不算彩蛋的彩蛋

  本例中图片张数(div),轮播效果翻转片数(li),初始显示第几张--都是定义在js变量中的,我们也可以在页面上写几个input输入控制这些值。这么简单的事情我就不上代码了啊哈哈哈。就这样吧。

最后附上github源码,需要的同学下载(彩蛋实现和代码优化的版本后续会更新到github)。

预览地址: https://tinatingzhang.github.io/HTML-Demos/3D%E8%BD%AE%E6%92%AD%E5%9B%BE%E7%89%B9%E6%95%88/index.html

本文完。

  

吃透css3之3d属性--perspective和transform的更多相关文章

  1. css3的3d属性集合

    css3的3d属性集合 想进入css3的3d世界必须知道一下几个属性及其用法. 当然在进入属性介绍之前我想你必须知道3维坐标,附上一张经典图如下: 我想不用解释了吧.之后要平移和旋转都是在这个基础之上 ...

  2. CSS3之3D效果中的transform运用

    css3中添加了很多新的标签 属性 描述 css transform 向元素应用 2D 或 3D 转换. 3 transform-origin 允许你改变被转换元素的位置. 3 transform-s ...

  3. CSS3打造3D效果——perspective transform的深度剖析

    声明:此篇博文虽是自己手写,但大量资源取自 张鑫旭 的博文.想看更详细 更专业的剖析请看张鑫旭的博文. 昨天对css3的transform做了初步的分析和认识,突然看到perspective属性,调了 ...

  4. CSS3 《3D骰子 压大小》

    游戏在线预览地址:http://dtdxrk.github.io/game/3d-dice/index.html js判断一个随机数大小的游戏. 本来想用canvas做的,平面的生产一个点数,感觉没啥 ...

  5. CSS3 3D立方体效果-transform也不过如此

    CSS3系列已经学习了一段时间了,第一篇文章写了一些css3的奇技淫巧,原文戳这里,还获得了较多网友的支持,在此谢过各位,你们的支持是我写文章最大的动力^_^. 那么这一篇文章呢,主要是通过一个3D立 ...

  6. HTML5培训入门基础知识了解CSS3 3D属性

    CSS3 3D 什么是3d的场景呢? 2d场景,在屏幕上水平和垂直的交叉线x轴和y轴 3d场景,在垂直于屏幕的方法,相对于3d多出个z轴 Z轴:靠近屏幕的方向是正向,远离屏幕的方向是反向 CSS3中的 ...

  7. CSS3动画属性:变形(transform)

    Transform字面上就是变形,改变的意思.在CSS3中transform主要包括以下几种:旋转rotate.扭曲skew.缩放scale和移动translate以及矩阵变形matrix. 语法 t ...

  8. 详解如何用 CSS3 完成 3D transform变换

    Tips:阅读提示!!! 首先,本文针对的是3D transform变换的学习,所以你需要对 2D transform变换 有一定的了解 其次,需要说明的是,代码是一种需要自己不断实践的学科,建议各位 ...

  9. CSS3中动画属性transform、transition 和 animation

    CSS3中和动画有关的属性有三个 transform.transition 和 animation.下面来一一说明:        transform   从字面来看transform的释义为改变,使 ...

随机推荐

  1. 学习计划——巩固基础+进阶练习

    时间:2016/3/23---24 内容:如何用CSS进行网页布局  课程复习 目标:完成一个demo+完成一篇学习心得博客 时间:2016/3/25---26 内容:网页布局基础  课程复习 目标: ...

  2. 学习计划(一)——JavaScript

    一:与前端之缘 大一时除了上课和社团外不知道要学点什么,但是又不想睡觉打游戏,常常就是啥都想学,photoshop,premiere,After Effects都学,但始终没有明确的目标. 大二时一直 ...

  3. windows下搭建GO开发环境

    1. Go下载 由于某些原因golang.org不能访问,可以使用下面的镜像地址进行下 http://fossies.org/windows/misc/ 我的环境是win8 64位,所以选择go1.7 ...

  4. C# 基于DotRas的VPN管理

    由于工作环境有部分网址被公司屏蔽,特意做了个VPN管理工具,在想访问公司被屏蔽的网址时就开启连接,不用时就关掉.对于做安卓开发的或者.net core类库更新还是很方便的,现在把运行效果展示一下: 点 ...

  5. Spark RDD编程核心

    一句话说,在Spark中对数据的操作其实就是对RDD的操作,而对RDD的操作不外乎创建.转换.调用求值. 什么是RDD RDD(Resilient Distributed Dataset),弹性分布式 ...

  6. MongoDB学习总结(五) —— 安全认证

    作为数据库软件,我们要确保数据的安全,不是谁都可以访问的,所以mongodb也像其他的数据库软件一样可以采用用户验证的方法, mongodb 3.0之前的版本提供了addUser方法向不同的数据库添加 ...

  7. c++编程思想(一)--对象导言

    回过头来看c++编程思想第一章,虽然只是对c++知识的一个总结,并没有实质性知识点,但是收获还是蛮多的! 下面感觉是让自己茅塞顿开的说法,虽然含义并不是很准确,但是很形象(自己的语言): 1.类描述了 ...

  8. [Hadoop] - Hadoop Mapreduce Error: GC overhead limit exceeded

    在运行mapreduce的时候,出现Error: GC overhead limit exceeded,查看log日志,发现异常信息为 2015-12-11 11:48:44,716 FATAL [m ...

  9. NodeJs下的测试框架Mocha

    介绍和代码下载 Mocha在2011年发布,是目前最为流行的javascript框架之一,在本文我们重点介绍它在NodeJs上的使用. 如果你需要下载实例代码,可以通过这个链接 gitClone 或者 ...

  10. Alamofire源码解读系列(一)之概述和使用

    尽管Alamofire的github文档已经做了很详细的说明,我还是想重新梳理一遍它的各种用法,以及这些方法的一些设计思想 前言 因为之前写过一个AFNetworking的源码解读,所以就已经比较了解 ...