Citrons

【源码+教程】3D旋转相册(css3+js/纯css)
今天在抖音刷到了一个旋转相册,挺好玩的,就试着写了一下,我只是一个菜鸟,勿喷。另外,演示站请PC端食用,移动端不能...
扫描右侧二维码阅读全文
12
2018/08

【源码+教程】3D旋转相册(css3+js/纯css)

今天在抖音刷到了一个旋转相册,挺好玩的,就试着写了一下,我只是一个菜鸟,勿喷。另外,演示站请PC端食用,移动端不能拖拽(很卡)


工具:DW/Editplus等等都行、一部电脑/云电脑、有电、一堆图片
由于这是写着玩的,我就没按套路搞了(不喜欢看的,源码在最下面)


OK!步入正题,这里只讲代码,不讲萌新教程(重点都标出来了)
新建站点:名字自取,创建img文件夹存放图片,新建HTML文件

第一步:配置好景深(设置div盒子体现出景深)
首先设置一个盒子,由于是要体现景深的盒子,我就取名为perspective

<div id="perspective"><div>

然后我们需要一个用来放图片的盒子,并插入图片,我就取名为wrap了` <div id="wrap">

<img src="img/1.jpg" alt="">
<img src="img/2.jpg" alt="">
<img src="img/3.jpg" alt="">
<img src="img/4.jpg" alt="">
<img src="img/5.jpg" alt="">
<img src="img/6.jpg" alt="">
<img src="img/7.jpg" alt="">
<img src="img/8.jpg" alt="">
<img src="img/9.jpg" alt="">
<img src="img/10.jpg" alt="">
<img src="img/11.jpg" alt="">

</div>`
第一步布局总代码为:
`<div id="perspective">
<div id="wrap">

<img src="img/1.jpg" alt="">
<img src="img/2.jpg" alt="">
<img src="img/3.jpg" alt="">
<img src="img/4.jpg" alt="">
<img src="img/5.jpg" alt="">
<img src="img/6.jpg" alt="">
<img src="img/7.jpg" alt="">
<img src="img/8.jpg" alt="">
<img src="img/9.jpg" alt="">
<img src="img/10.jpg" alt="">
<img src="img/11.jpg" alt="">

</div>
<div>`


第二部,页面布局
首先清除默认边距:
*{margin:0;padding:0;}/*清除浏览器默认样式*/
接着把body的滚动条去掉,然后再加一个背景色:
` body{
background:#66677c;
overflow:hidden;
}`

做完这些,效果是这样的:
查看原图

然后再把图片缩在一起(wrap里面)相框大小与图片大小等同:
`#wrap{
width:149px;
height:200px;
margin:150px auto 0;/居中/
}`
到这里效果如下图:
235.png
然后将其叠加:` #wrap img{
position:absolute;
}`
tips:需要在其父级(wrap)加上相对定位:
position:relative;
效果图如下:
点击查看原图
然后设置景深。之前说了perspective是景深,代码如下:
` #perspective{
perspective:800px;/场景景深/

}`
tips:什么是场景景深?场景景深就类似于一个视角问题。
点击查看原图

然后给wrap元素赋予3D属性:
transform-style:preserve-3d;/*当前元素3D效果*/
设置wrap元素原始度数:
transform:rotateX(-20deg) rotateY(0deg);

然后我们需要计算图片入场动画时所需要旋转的度数,这个我们就交给JavaScript(HTML是从上执行到下的,所以这个放在最后 )
1.求出图片旋转的单位度数 360/图片的个数
①获取到所有图片:
var oImg = document.getElementsByTagName("img");//通过元素的名字获取节
②算出单位度数:
var deg = 360/oImg.length;//单位度数
2.针对每一张图片旋转相对应的度数
call改变数组的forEach方法中的实例执行 用元素集合去代替:`[].forEach.call(oImg,function(node,index){

console.log(index*deg);//每张图片应该旋转的度数
node.style.transform = "rotateY("+index*deg+"deg)translatez(350px)";//赋予给图片,并撑开350px

});`
①:设置图片精致拖拽,在最前面的<html>里添加ondragstart="return false":
<html ondragstart="return false">

3.入场动画
在第2步的代码里加上过渡属性:
node.style.transition = "1s ";//过渡属性:时间
然后发现这个动画并没有过渡性(延迟加载)于是我搞了一下延迟加载(不加也能用)代码如下:
node.style.transition = "1s "+(oImg.length - index)*0.11+"s";

然后说一下特效是什么?
特效:JS控制元素节点 在指定的时间点改变元素的样式或者属性的值 算法 逻辑思维

4.拖拽元素:分开处理——点击(onmousedown)、移动(onmousemove)、松开(onmouseup)
点击事件:
document.onmousedown = function(e){}
移动事件(位于点击时间内,为什么?你吃饭为什么要煮饭):
document.onmousemove = function(e){}
松开事件(这里还是位于点击事件内,且要结束移动事件):
` document.onmouseup =function(e){

 document.onmousemove = null; //清空鼠标移动事件}`

接下来就很麻烦了,我也说不清,就不细说了(其实是懒):
5拖拽:

 每一次移动 移动了多少距离  每次鼠标的位置在哪里
 每两次   是   哪两次移动了
 距离   添加到原有的元素度数上
 移动距离差 = 新的移动距离 - 旧的移动距离

①定义六个值:
var newX,newY,pervX,pervY,minusX,minusY;//分别为新值、旧值、差值
②定义的新值使用完后就变成了旧值(移动内):
`pervX = newX;

pervY = newY;//新的值用完之后就变成了旧的值`

那么新值是从哪来的呢?
③第一次点击的值(很明显,点击内):
` pervX = e.clientX;

pervY = e.clientY;//第一次点击时候的值`

④保存新值,计算差值,给给出旋转速度(移动内):
` //保存新的鼠标位置的值

newX = e.clientX;
newY = e.clientY;
minusX = newX - pervX;
minusY = newY - pervY;//差值

rotateX -= minusY*0.2;
rotateY += minusX*0.1;//距离差加上当前元素度数

oWrap.style.transform = "rotateX("+rotateX+"deg) rotateY("+rotateY+"deg)";`

重要的差不多就是上面那些了(对了,舞台颜色用文本渲染,这些是没有写惯性的,如果需要自行百度,当然,源码我有,也会放出来),下面放出上面的总代码:
HTML代码
`<div id="perspective">
<div id="wrap">

<img src="img/1.jpg" alt="">
<img src="img/2.jpg" alt="">
<img src="img/3.jpg" alt="">
<img src="img/4.jpg" alt="">
<img src="img/5.jpg" alt="">
<img src="img/6.jpg" alt="">
<img src="img/7.jpg" alt="">
<img src="img/8.jpg" alt="">
<img src="img/9.jpg" alt="">
<img src="img/10.jpg" alt="">
<img src="img/11.jpg" alt="">

</div>
<div>`
css样式
` *{margin:0;padding:0;}
body{
background:#66677c;
overflow:hidden;
}
#perspective{
perspective:800px;/场景景深/

}
#wrap{
position:relative;
width:149px;
height:200px;
margin:150px auto 0;
transform-style:preserve-3d;/当前元素3D效果/
transform:rotateX(-20deg) rotateY(0deg);

}
#wrap img{
position:absolute;
/倒影设置/
-webkit-box-reflect:below 10px -webkit-linear-gradient(top,rgba(0,0,0,0) 50%,rgba(0,0,0,0.5) 100%);
cursor:pointer;

-moz-user-select: -moz-none;
        -moz-user-select: none;
        -o-user-select: none;
        -khtml-user-select: none;
        -webkit-user-select: none;
        -ms-user-select: none;
        user-select: none;
          border-radius:5px;

box-shadow:0 0 20px #FFF;
/背景渐变效果!important/
-webkit-box-reflect:below 10px
-webkit-linear-gradient(top,rgba(0,0,0,0) 80%,rgba(0,0,0,1) 100%);

}
#wrap p{

    width: 1200px;
    height: 1200px;
    background: -webkit-radial-gradient(center center,600px 600px,rgba(255,255,255,0.5),rgba(0,0,0,0));
    position: absolute;
    top:100%;left:50%;
    margin-top: -600px;
    margin-left: -600px;
    border-radius:600px;
    transform:rotateX(90deg);
}`

JavaScript代码:
` /*1.求出图片旋转的单位度数 360/图片的个数
2.针对每一张图片旋转相对应的度数
3.入场动画
4.拖拽元素 分开处理事件 点击 移动 松开

特效:JS控制元素节点 在指定的时间点改变元素的样式或者属性的值 算法 逻辑思维
*/
var oImg = document.getElementsByTagName("img");//通过元素的名字获取节点
var deg = 360/oImg.length;//单位度数
//call改变数组的forEach方法中的实例执行 用元素集合去代替
window.onload = function(){//页面加载完毕之后再执行的脚本
[].forEach.call(oImg,function(node,index){

console.log(index*deg);
node.style.transform = "rotateY("+index*deg+"deg)translatez(350px)";
node.style.transition = "1s "+(oImg.length - index)*0.11+"s";

});
}
/*
拖拽:

 每一次移动 移动了多少距离  每次鼠标的位置在哪里
 每两次   是   哪两次移动了
 距离   添加到原有的元素度数上

 移动距离差 = 新的移动距离 - 旧的移动距离

*/

var newX,newY,pervX,pervY,minusX,minusY;
var rotateX = -20,rotateY = 0;
var oWrap = document.getElementById("wrap");//通过id获取元素
var timer;

//点击
document.onmousedown = function(e){

pervX = e.clientX;
pervY = e.clientY;//第一次点击时候的值

//移动
document.onmousemove = function(e){

  //保存新的鼠标位置的值
newX = e.clientX;
newY = e.clientY;
minusX = newX - pervX;
minusY = newY - pervY;

rotateX -= minusY*0.2;
rotateY += minusX*0.1;

oWrap.style.transform = "rotateX("+rotateX+"deg) rotateY("+rotateY+"deg)";

pervX = newX;
pervY = newY;//新的值用完之后就变成了旧的值

}
//松开
document.onmouseup =function(e){

 document.onmousemove = null; //清空鼠标移动事件
 //抬起
                this.onmouseup = function(){
                    this.onmousemove = null;
                    timer = setInterval(function(){
                        minusX *= 0.95;
                        minusY *= 0.95;
                        rotateY += minusX*0.2; // roY = roY + minusX*0.2;
                        rotateX -= minusY*0.1;
                        oWrap.style.transform = 'rotateX('+ rotateX +'deg) rotateY('+ rotateY +'deg)';

                        if ( Math.abs(minusX)<0.1 && Math.abs( minusY )<0.1 )
                        {
                            clearInterval( timer );
                        }
                        console.log( minusX );
                    },13);
                }
                return false;

}

}`


3D旋转相册css+js(拖拽惯性版):点击下载
3D旋转相册(无惯性):点击下载
3D旋转相册(自动旋转):点击下载

tips:音乐可以自己加,记得将demo.html改为index.html;演示站:在线演示

广而告之:

Last modification:April 23rd, 2019 at 08:25 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment

10 comments

  1. 张三无语

    真的很棒!(☆ω☆)

    1. Citrons
      @张三无语

      谢谢,QAQ 鞠躬!

  2. 左利钢

    向大佬学习

    1. Citrons
      @左利钢

      在学习面前,我们都是萌新QAQ

  3. MHun

    那么牛逼的么

    1. Citrons
      @MHun

      嘿嘿嘿

  4. 九日

    原来你研究了一天这个。挺好看

    1. Citrons
      @九日

      可惜没有小姐姐照片,果然,我是找不到女朋友的男人

      1. 九日
        @Citrons

        那就找男朋友吧哈哈哈

        1. Citrons
          @九日

          是个好主意