纯js怎样实现3d相册
创始人
2024-12-17 09:42:38
0次

纯JavaScript实现 旋转木马/3d相册特效(鼠标拖拽旋转)

先来看看效果图

说一下实现的思路

旋转木马是通过依靠拥有景深(perspective)属性的盒子(此处盒子id起为:perspective)产生向网页内部的延伸感,并让装有图片沿z轴平移后(translateZ(Xpx))的盒子(此处起名为wrap)在拥有景深属性的盒子(perspective)内凭借transform属性产生的3d效果沿盒子(wrap)y轴旋转转动来实现的。

3d实现过程

首先要知道在js中transform中的xyz轴的含义

首先设置一个div,为其加上perspective的属性(撑开空间),方便后边观察效果

/* 场景景深 */
#perspective{perspective: 700px;
/*此属性是实现旋转木马的要点,能产生空间上的距离/延伸感。在此盒子中放置图片的盒子便可以实现向网页内部延伸的感觉*/}

2. 其次,设置装有图片盒子的容器wrap,使其居中显示,并加上position:relative的属性,让其内的图片定位。加上transform属性,在之后会用到。

#wrap{position: relative;width: 200px;height: 200px;margin: 150px  auto;border:  1px solid black;transform-style: preserve-3d;  /*实现3d效果的关键步骤,与boxshadow配合使用可以忽略层级问题,之后会说到*/transform: rotateX(0deg) rotateY(0deg) ;//为盒子的3d效果和旋转效果做准备。}

加入图片,设置样式,使用position:absolute;使其重叠。以数组的形式获取,并根据其数组长度length来计算图片的旋转角度。

#wrap img{position: absolute;width: 200px;}

遍历数组,使其沿y轴旋转Deg度。此处使用了原型,使用foreach方法遍历了数组,让其内每个图片都执行了function(el,index)。使用index下标区分开了数组内每个图片需要旋转的不同度数(第一张0°(Deg * 0) 第二张Deg度 (Deg * 1) 第三张(Deg * 2)度…)

/*oImg表示数组对象,
function(el,index)表示数组内每个对象要执行的函数,
index为其下标。
*/Array.prototype.forEach.call(oImg,function(el,index){
el.style.transform = "rotateY("+Deg*index+"deg)";
})

Array.prototype 属性表示 Array 构造函数的原型,并允许我们向所有Array对象添加新的属性和方法。

forEach() 方法对数组的每个元素执行一次提供的函数。

此处值得注意的是,xxx.xx.transform = “rotateY(”+Deg*index+“deg)”;

需要加上deg单位,括号要被双引号包着,也就是说,出来后的结果是transform :rotateY(度数deg);度数表示数字,要避免被转为字符串。

做完上一步操作后,让盒子其内图片沿Z轴平移translateZ(350px)属性便能初步看到3d效果,但此时会发现容器内图片数组出现了层级问题(Zindex)导致了理应在后面的图片能被显示出来。

这里有一种方法能忽略掉这个影响,避开层级问题:

/*加上沿z扩散*/-------执行完毕后--------加上属性观察效果---------#wrap{width: 200px;height: 200px;position: relative;margin:150px auto;transform-style: preserve-3d;  /*实现3d效果的关键步骤,与boxshadow配合使用可以忽略层级问题*/}#wrap img{position: absolute;width: 200px;box-shadow: 0px 0px 1px #000000;  /* 用box-shadow配合transform-style: preserve-3d;可以忽略层级问题 */}

这时候为装有图片的盒子加上transform:rotateX(-15deg);便能看到较为完整的3d效果了,此时实现盒子绕y轴转动便可实现旋转木马的效果。

实现运动过程

单纯使盒子转动就可以实现旋转木马,可以使用setinterval来不断使其旋转。

如果想使用鼠标拖动实现旋转木马,则需要再加一些代码,使装有盒子的容器(wrap)能够根据鼠标坐标变化绕容器(wrap)自身y轴转动。

var nowX ,nowY,//当前鼠标坐标lastX ,lastY ,//上一次鼠标坐标minusX,minusY ,//距离差roX = -10,roY = 0;//总旋转度数window.onmousedown = function(ev){var ev = ev;//获得事件源//鼠标移动后当前坐标会变为旧坐标,此处先保存,在算鼠标位移距离差的时候会用到。lastX = ev.clientX;lastY = ev.clientY;this.onmousemove = function(ev){var ev = ev;//获得事件源nowX = ev.clientX;nowY = ev.clientY;//获得移动时的当前坐标minusX = nowX - lastX;//坐标差minusY = nowY - lastY;//坐标差//累计差值,如果不累计的话转轮在每次点击-->移动后都会从第一张开始。roY += minusX;roX -= minusY;//累计差值//转动容器的x轴和y轴,使其转动度数(数值,不带单位)等于鼠标坐标差。oWrap.style.transform = "rotateX("+roX+"deg)"+"rotateY("+roY+"deg)";lastX = nowX;lastY = nowY;//移动末期现坐标变为旧坐标}this.onmouseup = function(){this.onmousemove = null;//取消鼠标移动的影响// this.onmousedown = null;}}}

完整代码






*{margin: 0;
padding: 0;}
body{overflow: hidden;background: #000000;}
/* 场景景深 */#perspective{perspective: 700px;
}#wrap{position: relative;width: 200px;
height: 200px;margin: 150px  auto;
border:  1px solid black;transform-style: preserve-3d;transform: rotateX(-15deg) rotateY(0deg) ;
/*景深可以简写在此属性里*/}#wrap img{position: absolute;
width: 200px;
transform: rotateX(0deg) rotateY(0deg);
box-shadow: 0px 0px 1px #000000;
/* 用box-shadow可以忽略层级问题 */}
















window.onload=function(){ var oImg = document.getElementsByTagName('img'),oWrap = document.getElementById('wrap'); var Deg = 360/(oImg.length);Array.prototype.forEach.call(oImg,function(el,index){el.style.transform = "rotateY("+Deg*index+"deg)translateZ(350px)"; // el.style.zIndex = -index;el.style.transition = "transform 1s "+ index*0.1 +"s";}); var nowX ,nowY,//当前鼠标坐标 lastX ,lastY ,//上一次鼠标坐标 minusX,minusY ,//距离差 roX = -10,roY = 0;//总旋转度数 window.onmousedown = function(ev){var ev = ev;//获得事件源 lastX = ev.clientX;lastY = ev.clientY;this.onmousemove = function(ev){var ev = ev;//获得事件源 nowX = ev.clientX;nowY = ev.clientY;//获得当前坐标 minusX = nowX - lastX;minusY = nowY - lastY;//坐标差 roY += minusX;//累计差值 roX -= minusY;//累计差值 oWrap.style.transform = "rotateX("+roX+"deg)"+"rotateY("+roY+"deg)";lastX = nowX;lastY = nowY;//移动末期现坐标变为旧坐标} this.onmouseup = function(){this.onmousemove = null;//取消鼠标移动的影响 // this.onmousedown = null; }}}

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...