玩转3D Swiper性感秀之思路分析总结

本文介绍了一个使用CSS和JavaScript实现的3D翻转轮播图效果,通过精细控制每列背景位移和旋转动画,达到立体视觉效果。文章详细解释了立体感构成原理,如何设置每列的背景位移,以及使用requestAnimationFrame和setTimeout实现平滑过渡和延时效果。

解析:

创建列DIV :
  • 从上图中我们能看出,每次旋转的动画是由多列小卡片组成的;
  • 每列根据它的下标,对背景进行位移,做到拼接的效果,整体看起来就成了一张图
  • 一起来看一下真像是啥样的:

旋转的动画是由多列小卡片组成

colNode(){

//生成列的节点
for (var i=0;i<this.colLen;i++){
    let iDivCol = document.createElement('div'); //列
    iDivCol.className = "div-col";
    iDivCol.style.width = this.colW+'px';
    iDivCol.style.height = this.cubeH+'px';
    iDivCol.style.zIndex = (i>this.colLen/2?this.colLen-i:i);
    this.swiperEle.appendChild(iDivCol);
}

}

立体感的构成 :
  • 旋转的立体感是如何构成的呢?
  • 原理其实很简单,可以理解成每列都是一个 立体魔方 ,它们都是相互独立的,
  • 每列 backgroundPosition:index*xcolW,进行一个位移,
  • 简单来说,即每列内部都有6个面组成,每个面都以父级为目标进行 position、transform等设置,
  • 一张图,让你看懂全世界:—— 图五为完成输出

单列的构成之四个面的展示

//——[正、上、左、右]
for(var i = 0;i<4;i++){

let dividingLine = i<2;
let span = document.createElement('span');
span.className = `${dividingLine?'bg-img':'pure-color'} i${i}`;
span.style.width = `${dividingLine? this.colW:this.cubeH}px`;
span.style.height = this.cubeH+'px';
if(dividingLine){
    span.style.backgroundPosition = `-${index*this.colW}px 0`;
};
iDivCol.appendChild(span);

};

单列的布局结构 :

zIndex

Zindex的重要性

transform 等角投影

/四个面的样式/
...省略N行
.div-col span.i1{

/*top*/
transform-origin:top;
transform:translateZ(-360px) rotateX(90deg);

}
.div-col span.i2{

/*left*/
transform-origin: left;
transform: rotateY(90deg);

}
.div-col span.i3{

/*right*/
transform-origin:left;
transform:translateX(25px) rotateY(90deg);

}

单列的html布局及重点样式

切换 :

div-col
transform-origin:50% 50% -180px

单列的鼠标经过

  • 鼠标经过都实现了,上下页切换还远吗?
  • 之前创建结构的时候,我们已知div的列数,
  • 为了更好的装B,我们在旋转的时候,给每列都要添加一定延时 setTimeout ,得以达到缓冲的视差,
  • 然后 requestAnimationFrame 就该它出场了, setInterval 已经成为过去式,
  • 同时旋转前,还要设置下一页,要显示的图片,
  • 当然记得旋转完成,后要重置角度哦。

单次旋转展示

3D旋转缓冲效果

...省略N行
swiperAnimate(){

const _requestAnimationFrame_ = window.requestAnimationFrame||window.WebkitRequestAnimationFrame;
const iDivCol = this.swiperEle.querySelectorAll(".div-col");
for(var i=0;i<iDivCol.length;i++){
    //让动画更逼真,给个过渡,当然也可以调整,requestAnimationFrame每次递增的值,
    iDivCol[i].style.WebkitTransition=`.8s -webkit-transform ease`;
    iDivCol[i].style.WebkitTransformOrigin=iDivCol[i].style.transformOrigin = "50% 50% -180px";
    this.animateMove(iDivCol[i],i,_requestAnimationFrame_);
}

}
animateMove(Col,index,animationFrame){

let ColNum =0;
let spanSurface =  Col.querySelectorAll("span");
//即将旋转到的面,展示的图片
spanSurface[1].style.backgroundImage="url(./2.jpg)";
setTimeout(()=>{
    //每列进行一个延时,以达到缓冲效果
    this.rotate(Col,0,spanSurface,animationFrame);

},index*this.delayMilli);

}
...省略N行

上下翻页 :
  • 上面基本已实现了旋转的效果,再加一些修饰,
  • 上下点击切换的功能,注意的地方在于,防止重复点击,当前旋转中时不能点:

pageDown(){

if(this.status){
    console.log("下翻,不能点击")
    return ;
};
this.status = 1;
this.pageNum = this.pageNum>=this.imageList.length ? 1 :++this.pageNum;
this.swiperAnimate();

}

上下点击切换3D旋转示例

预加载 :
  • 因轮播图图片较多,且此示例的图片每次只加载了两张,故要对图片进行一个预加载,
  • 以及图片加载出错后的过滤,避免影响后续效果的呈现:

preloadingImage(){

this.imageList.map((k,v)=>{
    let imgNode = new Image();
    imgNode.onerror=err=>{
        this.imageList.splice(v,1);
    }
    imgNode.src = k;
});

}

图片加载出错后的过滤

总结:

一个效果实现的方式有很多种,比如我们可以设置6个面,每设置一次,都是展示一张图,这样就不用每次旋转完后又去重置图片、角度等问题,包括 requestAnimationFrame 动画切换的过渡过程,也应该有更好的方式,欢迎各位大佬指点。以上就是今天为您带来的分享,你GET到了吗?如果觉得不错,记得给个赞哦

原文链接:https://www.jianshu.com/p/332...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值