style.css代码:
body,p{
margin: 0;
}
ul{
margin: 0;
padding: 0;
list-style: none;
}
img{
border: none;
vertical-align: middle;
}
body{
background: #000000;
color: #fff;
overflow-x: hidden; /* 旋转后会出现横向的滚动条 */
}
/*works*/
#wrap{margin-top: 150px}
#wrap ul{
width: 1050px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
transform-style: preserve-3d; /* 自己变成3d的空间是为了图片像弹簧一下能出来,加不加景深都可以,加了会视觉冲击感强烈一点 */
transform: translateY(-15%) rotateX(45deg) rotateZ(45deg); /* 先往右转45deg,斜着(wtud3)了,再往后一把推倒(旋转Z轴45deg) */
}
#wrap li{
width: 330px;
height: 230px;
margin-bottom: 30px;
position: relative;
background: rgba(255,255,255,0.5); /* 给一个灰色的底色 */
cursor: pointer;
}
#wrap li img,#wrap li div{
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
transition: 0.3s; /* 加上运动效果 */
}
#wrap li img{
z-index: 2; /* 把图片放到最上面 */
}
#wrap li div:nth-of-type(1){
background: #ac5cf5;
opacity: 0.5;
}
#wrap li div:nth-of-type(2){
background: #5db4eb;
opacity: 0.5;
}
#wrap li div:nth-of-type(3){
background: #5debb4;
opacity: 0.5;
}
/* 以下为弹簧效果 */
#wrap li:hover{
box-shadow: 0 0 50px #fff;
}
#wrap li:hover img:nth-of-type(1){
transform: translateZ(100px);
}
#wrap li:hover div:nth-of-type(1){
transform: translateZ(75px);
}
#wrap li:hover div:nth-of-type(2){
transform: translateZ(50px);
}
#wrap li:hover div:nth-of-type(3){
transform: translateZ(25px);
}
#shadowBox{
width: 100%;
height: 2000px;
background: rgba(0,0,0,0.5);
position: absolute;
left: 0;
top: 0;
opacity: 0;
transition: 0.5s;
display: none; /* 不设置为none的话,它会档住图片 */
}
#showPic{
width: 600px;
height: 400px;
box-shadow: 0 0 50px #000;
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
opacity: 0;
transition: 0.5s;
transform: scale(0); /* 出现的形式是从小到大 */
display: none; /* 不设置为none的话它会档住图片 */
}
.prev,.next{
width: 50px;
height: 45px;
position: absolute;
/* top: 50%;
margin-top: -22px; */
top: 0;
bottom: 0;
margin: auto;
cursor: pointer;
z-index: 2;
}
.prev{
left: 0;
background: url(../img/prev.png);
}
.next{
right: 0;
background: url(../img/next.png);
}
#showPic .img{
position: relative;
z-index: 1;
transform-style: preserve-3d;
perspective: 500px;
height: 400px;
}
#showPic img{
width: 600px;
height: 400px;
position: absolute;
left: 0;
top: 0;
transition: transform .3s;
}
/* 图片张开时候的变换中心点 */
#showPic img.moveToRight{
transform-origin: left;
}
#showPic img.moveToLeft{
transform-origin: right;
}
script.cs代码:
var lis=document.querySelectorAll('#wrap li'),
shadowBox=document.querySelector('#shadowBox'),
showPic=document.querySelector('#showPic'),
prev=document.querySelector('.prev'),
next=document.querySelector('.next'),
imgCon=document.querySelector('#showPic .img'),
bigImgs=imgCon.children;
var curNum=0; //当前图片的索引
var canClick=true; //用户是否可以点击
//图片预加载功能函数
function loadImg(imgs,callBack){
var loadImgs=[],loadImgNum=0;
for(var i=0;i<imgs.length;i++){
loadImgs[i]=new Image();
loadImgs[i].onload=function(){
loadImgNum++;
if(loadImgNum==imgs.length){
callBack(loadImgs);
}
};
loadImgs[i].src=imgs[i];
}
}
//把所有的图片都获取并存储到一个数组里
var imgs=[];
for(var i=0;i<lis.length;i++){
imgs.push('img/t'+i+'.png');
}
loadImg(imgs,function(images){
for(var i=0;i<lis.length;i++){
lis[i].index=i;
lis[i].onclick=function(){
shadowBox.style.height=document.documentElement.offsetHeight+'px';
shadowBox.style.display=showPic.style.display='block';
//缩放需要一个过程,所以让它延迟一会再出来
setTimeout(function(){
shadowBox.style.opacity=showPic.style.opacity=1;
showPic.style.transform='scale(1)';
},50);
//把点击的那个索引更新给curNum
curNum=this.index;
bigImgs[1].src=images[curNum].src; //弹出层出来以后,前面那张图片应该是点击对应的那个图。此时后面那张图要改么?不需要。它应该在点击的时候确定,往右走与往左走是不一样的。
nextClick(images);
prevClick(images);
};
}
});
//鼠标点击遮罩(yalh)层,隐藏弹出层
shadowBox.addEventListener('click',function(){
//如果点击遮罩层的时候正在运动,那就禁止用户点击,只有在运动停止的时候才能点击。这一点最后说
if(!canClick){
return;
}
shadowBox.style.display=showPic.style.display='none';
shadowBox.style.opacity=showPic.style.opacity=0;
showPic.style.transform='scale(0)';
});
//下一张点击
function nextClick(images){
var nextNum=0; //下一张图片的索引(背后那张图片的索引)
next.onclick=function(){
if(!canClick){
return;
}
canClick=false; //点击后立马变成false,再书合上后再变成true,只有为true的时候才能点
/*
点击的时候要做的事情
1、背后图片的地址要换成正确的
1、上面的图片走到右边
2、下面的图片像翻书(tonn)一样打开(上一步结束后进行)
3、上面的图片回到原始位置、下面图片合上(上一步结束后进行)
*/
//往右点击后下一张图片的索引是当前图片的索引+1
nextNum=curNum+1;
if(nextNum==lis.length){ //走到最后了,再回到起点
nextNum=0;
}
bigImgs[0].src=images[nextNum].src; //换后面那张图片的地址
var endNum1=0; //记录上面图片运动结束的次数
var endNum2=0; //记录下面图片运动结束的次数
bigImgs[0].className=bigImgs[1].className='moveToRight'; //上面图往右走、下面图张开的时候,旋转不太对劲,是因为旋转中心没有设置
bigImgs[1].style.transform='translateX(600px) rotateY(-10deg)'; //上面图片往右走
bigImgs[1].addEventListener('transitionend',function(){ //上面图片已经走到右边了
endNum1++;
bigImgs[0].style.transform='rotateY(-10deg)'; //下面图张开
bigImgs[1].style.transform='translateX(0) rotateY(0deg)'; //上面图回去
/*
这里要注意
1、按正常的逻辑应该是上面的图回去了,然后下面图上再合上。所以需要知道什么时候上面的图回去了
2、可能大家会再来个transitionend方法,其实不需要
3、先在这里console.log(1),看到会弹出两次
3、在外面声明一个变量,用来存储结束事件发生的次数,当这个数字加到2的时候就代表上面的图片回去的结束事件发生了
*/
if(endNum1==2){ //这个条件成立说明,现在是上面的图上已经回到原点了
bigImgs[0].style.transform='rotateY(0)'; //下面的图合上
bigImgs[1].style.zIndex=1; //上面的图跑后面
bigImgs[0].style.zIndex=2; //下面的图跑前面
}
});
//下面的图合上了
bigImgs[0].addEventListener('transitionend',function(){
//这里也会发生两次,因为下面的图,张开又合上,是两次过渡
//console.log(1);
endNum2++;
if(endNum2==2){
/*
1、这个条件成立,说明现在的end事件对应的是书合上的过渡
2、这里需要做两件事件
1、更改当前图片的索引,下一张的索引在函数一开始就修改了
2、还原图片的层级到初始状态
*/
//书合上了,也代表一次完整的运动走完了,然后就要改索引了。这里只需要
curNum++;
if(curNum==lis.length){ //走到最后了,再回到起点
curNum=0;
}
bigImgs[0].style.zIndex=1; //后面图片的zIndex
bigImgs[1].style.zIndex=2; //前面图片的zIndex,既然层级变了,那图片的路径也要变
bigImgs[1].src=images[nextNum].src; //只用变前面那张图片的地址,变成下一张图片的地址
canClick=true; //书合上了,才可以进行下次的点击
}
})
};
}
//上一张点击
function prevClick(images){
var prevNum=0; //修改
prev.onclick=function(){ //修改
if(!canClick){
return;
}
canClick=false;
//这一块全部修改
prevNum=curNum-1;
if(prevNum==-1){
prevNum=lis.length-1;
}
bigImgs[0].src=images[prevNum].src;
var endNum1=0;
var endNum2=0;
bigImgs[0].className=bigImgs[1].className='moveToLeft'; //修改
bigImgs[1].style.transform='translateX(-600px) rotateY(10deg)'; //修改
bigImgs[1].addEventListener('transitionend',function(){
endNum1++;
bigImgs[0].style.transform='rotateY(10deg)'; //修改
bigImgs[1].style.transform='translateX(0) rotateY(0deg)';
if(endNum1==2){
bigImgs[0].style.transform='rotateY(0)';
bigImgs[1].style.zIndex=1;
bigImgs[0].style.zIndex=2;
}
});
bigImgs[0].addEventListener('transitionend',function(){
endNum2++;
if(endNum2==2){
//这一块修改
curNum--;
if(curNum==-1){
curNum=lis.length-1;
}
bigImgs[0].style.zIndex=1;
bigImgs[1].style.zIndex=2;
bigImgs[1].src=images[prevNum].src; //修改
canClick=true;
}
})
};
}
HTML代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>js+css3 3D倾斜图片列表布局点击放大切换特效</title>
<link rel="stylesheet" href="css/style.css" />
</head>
<body>
<div id="wrap">
<ul>
<li>
<img src="img/t0.png" alt="">
<div></div>
<div></div>
<div></div>
</li>
<li>
<img src="img/t1.png" alt="">
<div></div>
<div></div>
<div></div>
</li>
<li>
<img src="img/t2.png" alt="">
<div></div>
<div></div>
<div></div>
</li>
<li>
<img src="img/t3.png" alt="">
<div></div>
<div></div>
<div></div>
</li>
<li>
<img src="img/t4.png" alt="">
<div></div>
<div></div>
<div></div>
</li>
<li>
<img src="img/t5.png" alt="">
<div></div>
<div></div>
<div></div>
</li>
<li>
<img src="img/t6.png" alt="">
<div></div>
<div></div>
<div></div>
</li>
<li>
<img src="img/t7.png" alt="">
<div></div>
<div></div>
<div></div>
</li>
<li>
<img src="img/t8.png" alt="">
<div></div>
<div></div>
<div></div>
</li>
</ul>
</div>
<div id="shadowBox"></div>
<div id="showPic">
<div class="prev"></div>
<div class="img">
<img style="z-index: 1;" src="img/t0.png"/>
<img style="z-index: 2;" src="img/t1.png"/>
</div>
<div class="next"></div>
</div>
<script type="text/javascript" src="js/script.js" ></script>
</body>
</html>
img文件夹下任意九张图片t0.png到t9.png和两张切换图片prev.png、next.png