首页 > 其他分享 >原生js实现3D照片墙

原生js实现3D照片墙

时间:2023-02-28 21:02:47浏览次数:42  
标签:原生 center photo transform js item nav var 3D


聊一下心得:CSS写得好,真的可以省很多js代码哈,写起来也简单很多,所以要好好掌握js哈,所以这里也提供了css代码,如果您觉得您的css写得不错,可以直接看js代码哦

效果:

1、点击Start View进入照片墙

2、只有一张图片是在中间显示,其他图片在中间的图片两侧随机排序,并且随机旋转一定的角度,层级也是随机的哦

3、点击上面的导航条,可以让对应的图片在中间显示

4、点击中间的图片该照片翻转,显示背面(照片的描述信息)

实现过程:

1、用数据生成结构(模拟的数据,此处不再提供)

2、对所有图片进行排序

3、计算两侧图片的随机范围

4、控制图片翻转

5、控制导航按钮切换图片

6、遮罩层动画实现

HTML代码:

<body>
<div class="photo_wall">
<div class="photo">
<!-- 每张图片的最外层,用来控制图片的旋转和位移 -->
<div class="photo_i front" id="photo_{{id}}">
<!-- 内层用来控制图片的3D翻转 -->
<div class="photo_3d">
<!-- 每个照片的正面 -->
<div class="photo_side photo_front">
<p><img {{src}}="{{img}}"></p>
<h3>{{caption}}</h3>
</div>
<!-- 每个照片的反面 -->
<div class="photo_side photo_back">
<p class="desc">{{desc}}</p>
</div>
</div>
</div>
{{split}}
<div class="nav"><span class="nav_i" id="nav_{{id}}"></span></div>
</div>
<div class="shade">
<div class="start">Start View</div>
</div>
</div>
</body>

CSS代码:

/*最外层样式*/
.photo_wall{
width: 100%;
height: 600px;
position: relative;
background: url(../imgs/bg.jpg) no-repeat center center;
background-size: cover;
overflow: hidden;
}

/*照片区域的样式*/
.photo {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 1;
opacity: 0;
transition: 1s;
}

/*每个照片的样式*/
.photo .photo_i,.photo .photo_3d,.photo .photo_side {
width: 336px;
height: 392px;
position: absolute;
left: 0;
top: 0;
}

.photo .photo_i {
transition: 800ms;
perspective: 750px;
left: 50%;
top: 50%;
transform: translate(-50%,-50%) scale(.5) rotate(0);
}

.photo .photo_3d {
transition: 500ms;
transform-style: preserve-3d;
transform-origin: 0 50%;
}
/*正面和反面的公共样式*/
.photo .photo_side {
border-radius: 6px;
background: #fff;
padding: 26px 24px;
box-sizing: border-box;
backface-visibility: hidden;
}

/*照片的正面样式*/
.photo .photo_front {
transform: rotateY(0);
}
.photo .photo_front p {
width: 286px;
height: 286px;
border: 2px solid #d8536d;
overflow: hidden;
display: flex;
/*align-items: center;*/
}
.photo .photo_front p img{
width: 100%;
align-self: center;
}
.photo .photo_front h3{
width: 166px;
height: 44px;
background: #d8536d;
border-radius: 0 0 6px 6px;
margin: 0 auto;
text-align: center;
font: 16px/44px Arial;
color: #fff;
}
/*照片的反面样式*/
.photo .photo_back {
transform: rotateY(-180deg);
}

.photo .photo_back .desc {
font-size: 14px;
line-height: 20px;
color: #d8536d;
}
.photo .photo_back a {
color: #d8356d;
}
/*照片的居中样式*/
.photo .center {
z-index: 9999;
left: 50%;
top: 50%;
transform: translate(-50%,-50%) scale(1) rotate(0);
}

/*照片正面的class*/
.photo .front .photo_3d {
transform: translateX(0) rotateY(0);
}
/*照片反面的calss*/
.photo .back .photo_3d {
transform: translateX(100%) rotateY(-180deg);
}

/*导航栏的样式*/
.nav {
position: absolute;
left: 0;
top: 0;
z-index: 888;
width: 100%;
height: 200px;
padding-top: 10px;
box-sizing: border-box;
text-align: center;
background: -webkit-linear-gradient(top,rgba(0,0,0,.5),transparent);
}

@font-face {
font-family: "icont";
src: url(../font/iconfont.woff) format("woff");
}

.nav .nav_i {
display: inline-block;
width: 30px;
height: 30px;
border-radius: 50%;
background: rgba(255,255,255,.5);
font-family: "icont";
text-align: center;
line-height: 30px;
color: rgba(255,255,255,0);
cursor: pointer;
transform: scale(.5);
transition: 500ms;
}

.nav .active {
color: rgba(255,255,255,1);
transform: scale(.9) rotateY(0);
}

.nav .back {
transform: scale(.8) rotateY(-180deg);
}

/*遮罩层*/
.photo_wall .shade {
position: absolute;
left: 0;
top: 0;
z-index: 2;
width: 100%;
height: 100%;
background: rgba(255,255,255,.7);
display: flex;
justify-content: center;
align-items: center;
}
.photo_wall .hide {
transition: 1s;
opacity: 0;
transform: scale(0) rotateY(360deg);
}
.photo_wall .shade .start {
width: 200px;
height: 60px;
border: 2px solid #d8536d;
border-radius: 10px;
background: rgba(248,229,227,.5);
text-align: center;
font: 22px/60px Arial;
cursor: pointer;
}

js代码:用到了我昨天在博客上写的工具函数

提供主要的实现步骤的js代码:

(function () {

//---------------------------------------------------------
// 初始化数据
var data = dataList,len = data.length;

createPhotos(data);

var n = 0;

//---------------------------------------------------------
// 基本逻辑
M('.shade .start').addEventListener('click',function() {
addClass(M('.shade'),'hide');
M('.photo').style.opacity = 1;
addClass(M(`#photo_0`),'center');
setTimeout(function(){
sortImgs(n);
}, 200);
});

M('.nav_i').forEach((item,i)=>{
item.onclick = function(){
turnImg(M(`#photo_${i}`));
};
});

//---------------------------------------------------------
// 需求函数化

// 需求1:利用数据生成所有html结构
function createPhotos(data) {
var photo_html = M('.photo').innerHTML.split('{{split}}')[0].trim(),
nav_html = M('.nav').innerHTML.trim();

var photos = [],nav = [];

data.forEach((item,i)=>{
var photoTemp = photo_html.replace(/{{id}}/,i)
.replace(/{{src}}/,'src')
.replace(/{{img}}/,item.img)
.replace(/{{caption}}/,item.caption)
.replace(/{{desc}}/,item.desc),
navTemp = nav_html.replace(/{{id}}/,i);

photos.push(photoTemp);
nav.push(navTemp);
});
photos.push(`<div class="nav">${nav.join('')}</div>`);
M('.photo').innerHTML = photos.join('');
}

// 需求2:给所有的图片排序
function sortImgs(n) {
var photos = M('.photo_i');

initPhotos(photos);

var center = photos.splice(n,1)[0];
addClass(center,'center');
addClass(M(`#nav_${n}`),'active');

// center.addEventListener('click', function(e){
// turnImg(this);
// });

center.onclick = function () {
turnImg(this);
};

// 对剩余的图片进行随机排序
photos.sort(()=>{
return 0.5 - Math.random();
})


var rP = scope(); //返回左右两侧范围 从 x - y

// 分成左侧和右侧两部分
var left = photos.splice(0,Math.ceil((len-1)/2)),
right = photos;

left.forEach((item,i)=>{
item.style.zIndex = rn([0,len]);
item.style.left = rn(rP.L.x) + 'px';
item.style.top = rn(rP.L.y) + 'px';
item.style.transform = `translate(0,0) scale(.9) rotate(${rn([-2160,2160])}deg)`;
});
right.forEach((item,i)=>{
item.style.zIndex = rn([0,len]);
item.style.left = rn(rP.R.x) + 'px';
item.style.top = rn(rP.R.y) + 'px';
item.style.transform = `translate(0,0) scale(.9) rotate(${rn([-2160,2160])}deg)`;
});
}

// 需求3 编写某个区间的随机整数
function rn(arr) {
var max = Math.max.apply(null,arr),
min = Math.min.apply(null,arr);
var p = Math.round(Math.random() * (max - min) + min);
//?;
return p;
}

// 需求4 计算随机的范围
function scope() {
var outer = M('.photo_wall');
var pic = M(`#photo_${rn([0,len-1])}`);
var W = outer.clientWidth,
H = outer.clientHeight,
w = pic.offsetWidth,
h = pic.offsetHeight;
console.log(W,w);
var data = {
L:{
x:[-w/3,W/2 - w/2 - w],
y:[-h/3,H - h*2/3]
},
R:{
x:[W/2 + w/2,W - w*2/3],
y:[-h/3,H - h*2/3]

}
}
return data;
}

// 需求5:控制图片翻转
function turnImg(ele) {
var cur = ele.id.split('_')[1];
var nav = M(`#nav_${cur}`);

if(!hasClass(ele,'center')){ //如果点的不是当前对应的按钮就重新排序
return sortImgs(cur)
}

if(hasClass(ele,'front')){
//翻转到背面
console.log('现在是正面准备移除front');
addClass(ele,'back');
console.log(ele.className);
rmClass(ele,'front');
console.log(ele.className);
addClass(nav,'back');
}else{
//翻转到正面
console.log('现在是反面准备移除back');
addClass(ele,'front');
console.log(ele.className);
rmClass(ele,'back');
console.log(ele.className);
rmClass(nav,'back')
}
}

// 需求6 初始化所有样式
function initPhotos(objs) {
objs.forEach((item,i)=>{
if(hasClass(item,'center')){
var nav = M(`#nav_${i}`);
rmClass(item,'center');
rmClass(item,'back');
addClass(item,'front');
rmClass(nav,'active');
rmClass(nav,'back');
item.onclick = null;
}
item.style.left = '';
item.style.top = '';
item.style.zIndex = '';
item.style.transform = `translate(-50%,-50%) scale(1.1) rotate(0deg)`;
});
}

})()


标签:原生,center,photo,transform,js,item,nav,var,3D
From: https://blog.51cto.com/u_15983333/6091811

相关文章

  • 3D翻转效果的实现函数封装
    实现3D翻转的效果:使用TweenMax库的方法(使用之前要先引入jQuery和TweenMax哦)参数说明:obj:是要翻转的两个面的父级,element1是正面,element2是背面,d是翻转的时间vardonna={}......
  • js中阻止事件冒泡与阻止事件默认行为
    一、冒泡事件我们都知道冒泡就像水底气泡浮到水面这一过程。冒泡事件即是事件从最底层逐个经过上面一级级事件的过程,就是冒泡事件。那么如何有效的阻止冒泡事件的发生?其实在......
  • JS内存爆破问题
    原理检测到调试,格式化等,疯狂的在js文件,或者html中进行读写,cookie重写追加,字节追加,导致内存不足够,卡死内存爆破,指js通过死循环/频繁操作数据库(包括cookie)/频繁调取histo......
  • 云原生数据库TDSQL-C 容灾的实践和探索
    云原生数据库TDSQL-C作为腾讯云架构平台部核心数据库产品之一,致力于为云上ToB用户和公司自研业务提供集高性能、低成本、大存储、低延迟、秒级扩缩容、极速回档、Serverles......
  • json(1)键值对
    好了进入正题json教程(1):键值对其实键值对非常好理解,毕竟生活中处处都有键可以理解为数据的名称值就是数据拿我们的幸运观众举个例子首先,他的名字是李子墨名字就......
  • 微信json对象 转换为json字符串传参给后端,后端解析
    普通js通常这样转换//这是一个json对象varjsonobj={"sztno":"330890811","transTime":"2018-5-708:00:36","amt":"50"};//json对象转成json字符串varjsonstr=JSON.s......
  • JS混淆解密技术研究与案例分析
    引言在现代互联网的世界中,JavaScript(JS)已成为最为流行和广泛使用的编程语言之一。JS的开发人员使用它来构建各种Web应用程序,包括网站、应用和游戏等。然而,随着JS应......
  • JsonResponse中文乱码问题
    直接使用JsonResponse返回结果中文乱码returnJsonResponse({'ret':0,'msg':f'id为{customer_id}的客户信息删除成功'})解决乱码问题可以添加json_dumps_params={'e......
  • zabbix钉钉告警js脚本
    varDingding={params:{},proxy:null,setParams:function(params){if(typeofparams!=='object'){return;}D......
  • JS文件夹上传解决方案
    ​ 我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用。这次项目的需求:支持大文件的上传和续传,要求续传支持......