<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<script src="https://cdn.staticfile.org/vue/2.7.0/vue.min.js"></script>
<style>
li,
ul,
div,
html,
body {
margin: 0;
padding: 0;
}
html,
body {
height: 100%
}
li {
list-style-type: none
}
.wrap {
height: 100%;
overflow: hidden;
perspective: 800px;
}
#box {
top: 50%;
left: 50%;
width: 0;
height: 0;
position: relative;
transform-style: preserve-3d;
transform: translateZ(-1600px);
z-index: 1;
}
#box li img {
top: -80px;
left: -60px;
width: 240px;
height: 320px;
position: absolute;
text-align: center;
line-height: 160px;
background-color: rgba(5, 100, 80, 0.2);
border: 1px solid rgba(125, 255, 255, 0.25);
box-shadow: 0 0 15px rgba(0, 255, 255, 0.5);
cursor: pointer;
}
#box li span {
font-size: 28px;
font-weight: blod;
text-shadow: 2px 2px 5px black;
color: #efebef;
}
.mask {
width: 100%;
height: 100%;
background: url('https://materials.cdn.bcebos.com/images/40054665/64daa47e7470404400dd7add58431e8e.jpeg') no-repeat center;
background-size: cover;
filter: blur(5px);
}
.mask>.bg-mask {
width: 100%;
height: 100%;
background: #000;
opacity: 0.25;
}
.bottomstyle h1{
width: 240px;
background: white;
height:100px;
position: absolute;
top:120px;
left:-60px;
color: #000;
text-align: center;
}
.bottomstyle span{
background: white;
width: 240px;
overflow: hidden;
color: #000;
text-align: center;
}
.callWard{
padding-left: 30px;
position: absolute;
top: 0;
left: 0;
margin-top: 10px;
z-index: 100;
background: rgba(255,255,255,0.3);
width: 300px;
height: 50px;
}
.callWard::before{
position: absolute;
top:0;
left: 0;
content: "";
background: #817b7b;
width: 30px;
height: 50px;
}
.callWard .text{
color: #454444;
font-size: small;
font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
}
</style>
</head>
<body>
<div class="callWard">
<div class="text">提示词:</div>
<div class="text">点击中间盒子照片区域可转化动画</div>
<div class="text">点击白色区域可跳转响应top视频页面</div>
</div>
<div class="wrap">
<ul id="box">
<div id="app">
</div>
</ul>
<div class="mask">
<div></div>
</div>
</div>
<script>
Vue.config.devtools = true
const Moveone = {
template: `
<div>
<li v-for="item in items">
<img :src="item.pic" alt="">
<a :href="item.url" class="bottomstyle" target="_blank">
<h1> {{item.title}}</h1>
</a>
</li>
</div>
`,
data() {
return {
items:[{
"title": "海洋",
"url": "https://movie.douban.com/subject/3443389/",
"pic": "https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2559581324.jpg",
"rating_num": "9.1",
"commment_num": "154413人评价",
"info": "导演:雅克·贝汉JacquesPerrin/雅克·克鲁奥德JacquesCluzaud主演:...2009/法国瑞士西班牙美国阿联酋摩纳哥/纪录片"
},
{
"title": "穿越时空的少女",
"url": "https://movie.douban.com/subject/1937946/",
"pic": "https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2079334286.jpg",
"rating_num": "8.6",
"commment_num": "372498人评价",
"info": "导演:细田守MamoruHosoda主演:仲里依纱RiisaNaka/石田卓也Takuya...2006/日本/剧情爱情科幻动画"
},
{
"title": "我爱你",
"url": "https://movie.douban.com/subject/5908478/",
"pic": "https://img2.doubanio.com/view/photo/s_ratio_poster/public/p824590592.jpg",
"rating_num": "9.0",
"commment_num": "161733人评价",
"info": "导演:秋昌民Chang-minChoo主演:宋在河Jae-hoSong/李顺载Soon-jae...2011/韩国/剧情爱情"
},
{
"title": "地球上的星星",
"url": "https://movie.douban.com/subject/2363506/",
"pic": "https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2197897857.jpg",
"rating_num": "8.9",
"commment_num": "199772人评价",
"info": "导演:阿米尔·汗AamirKhan主演:达席尔·萨法瑞DarsheelSafary/阿...2007/印度/剧情儿童家庭"
}
]
}
}
}
const vm= new Vue({
template:`<Moveone></Moveone>
`,
el:'#app',
components:{
Moveone
}
})
</script>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
// 开启一个独立的空间避免全局变量污染
(function () {
let
idx,
timer,
// 存放li 元素
liElem,
// 存放span 元素
spanElem,
// 记录布局类型
currentStyle,
// 鼠标X、Y坐标值
oldCoordX,
oldCoordY,
nowCoordX,
nowCoordY,
// li 元素水平、垂直、纵深方向偏移位
offsetStepX,
offsetStepY,
offsetStepZ,
// li 元素的坐标
liElemCoordX,
liElemCoordY,
liElemCoordZ,
// 鼠标X、Y差值
minusX = 0,
minusY = 0,
// X、Y偏移度数
liElemDegX = 0,
liElemDegY = 0,
// li 元素的最大个数
liElemMaxNum = 162,
// li 元素 水平、垂直铺放的最大个数
liElemRowMaxNum = 5,
liElemColMaxNum = 5,
// li 元素水平、垂直、纵深方向的最大间隔距离
liElemOffsetX = 350,
liElemOffsetY = 350,
liElemOffsetZ = 350,
// li 元素默认景深
liElemDepDefault = -1000,
// 避免覆盖默认景深值
depDefault = liElemDepDefault - 600;
// 避免第一次拖动发生错位
liElemDepZ = liElemDepDefault - 600,
// 单个方阵中 li 元素的总个数
aScreenNum = liElemRowMaxNum * liElemColMaxNum,
// li 元素纵深方向的最在间隔距离
liElemDepMaxDist = parseInt(liElemMaxNum / aScreenNum),
// 计算第一个li 元素的坐标点
liElemFristSiteX = parseInt('-' + liElemRowMaxNum / 2) * liElemOffsetX,
liElemFristSiteY = parseInt('-' + liElemColMaxNum / 2) * liElemOffsetY,
liElemFristSiteZ = parseInt('-' + liElemDepMaxDist / 2) * liElemOffsetZ,
// 文本内容
data = [''];
// 指定一个区间,获取一个随机数
randomFrom = (lowerValue, upperValue) => {
return Math.floor(Math.random() * (upperValue - lowerValue + 1) + lowerValue);
}
// 方阵
gridLayout = _ => {
let arr = [...Array(liElemMaxNum).keys()];
$('#box li').each(i => {
// 数组的索引
let idx = randomFrom(0, arr.length - 1);
// 计算li 元素 水平、垂直、纵深方向的偏移位
offsetStepX = ((i % aScreenNum) % liElemRowMaxNum) * liElemOffsetX;
offsetStepY = parseInt((i % aScreenNum) / liElemColMaxNum) * liElemOffsetY;
offsetStepZ = parseInt(i / aScreenNum) * liElemOffsetZ;
// 计算当前li 元素的坐标值
liElemCoordX = liElemFristSiteX + offsetStepX;
liElemCoordY = liElemFristSiteY + offsetStepY;
liElemCoordZ = liElemFristSiteZ + offsetStepZ;
$('#box li').eq(arr[idx]).css({
"transform": `translate3d(${liElemCoordX}px,${liElemCoordY}px,${liElemCoordZ}px)`,
"transition": "4s ease-in-out"
})
// 删除数组中的值
arr.splice(idx, 1);
});
currentStyle = gridLayout;
}
// 螺旋
helixLayout = _ => {
let arr = [...Array(liElemMaxNum).keys()];
$('#box li').each(i => {
let idx = randomFrom(0, arr.length - 1);
let liElemDegY = 10 * i;
let liElemDepY = -10 * parseInt(liElemMaxNum / 2) + 10 * i;
$('#box li').eq(arr[idx]).css({
"transform": `rotateY(${liElemDegY}deg) translateY(${liElemDepY}px) translateZ(${Math.abs(liElemDepDefault)}px)`,
"transition": "4s ease-in-out"
})
// 删除数组中的值
arr.splice(idx, 1)
});
currentStyle = helixLayout;
}
// 球形
sphereLayout = _ => {
let arr = [...Array(liElemMaxNum).keys()];
$('#box li').each(i => {
let idx = randomFrom(0, arr.length - 1);
let liElemDegY = 3 * i;
let liElemDegX = 30 * i;
$('#box li').eq(arr[idx]).css({
"transform": `rotateY(${liElemDegY}deg) rotateX(${liElemDegX}deg) translateZ(${Math.abs(liElemDepDefault)}px)`,
"transition": "4s ease-in-out"
})
// 删除数组中的值
arr.splice(idx, 1)
});
currentStyle = sphereLayout;
}
// 三体
threeLayout = _ => {
let arr = [...Array(liElemMaxNum).keys()];
$('#box li').each(i => {
let idx = randomFrom(0, arr.length - 1);
let liElemDegY = 3 * i;
let liElemDegX = 60 * i;
$('#box li').eq(arr[idx]).css({
"transform": `rotateY(${liElemDegY}deg) rotateX(${liElemDegX}deg) translateZ(${Math.abs(liElemDepDefault)}px)`,
"transition": "4s ease-in-out"
})
// 删除数组中的值
arr.splice(idx, 1)
});
currentStyle = threeLayout;
}
// 几何
geomeLayout = _ => {
let arr = [...Array(liElemMaxNum).keys()];
$('#box li').each(i => {
let idx = randomFrom(0, arr.length - 1);
let liElemDegY = 8.9 * i;
let liElemDegX = 2.9 * i;
$('#box li').eq(arr[idx]).css({
"transform": `rotateY(${liElemDegY}deg) rotateX(${liElemDegX}deg) translateZ(${Math.abs(liElemDepDefault)}px)`,
"transition": "4s ease-in-out"
})
// 删除数组中的值
arr.splice(idx, 1)
});
currentStyle = geomeLayout;
}
// 曲线
curveLayout = _ => {
let arr = [...Array(liElemMaxNum).keys()];
$('#box li').each(i => {
let idx = randomFrom(0, arr.length - 1);
let liElemDegY = 1 * i;
let liElemDegX = 2 * i;
$('#box li').eq(arr[idx]).css({
"transform": `rotateY(${liElemDegY}deg) rotateX(${liElemDegX}deg) translateZ(${liElemDepDefault}px)`,
"transition": "4s ease-in-out"
})
// 删除数组中的值
arr.splice(idx, 1)
});
currentStyle = curveLayout;
}
// 随机
chaoticLayout = _ => {
$('#box li').each(function (i) {
// 随机生成li 元素的坐标点
liElemCoordX = (Math.random() - 0.5) * 3000;
liElemCoordY = (Math.random() - 0.5) * 3000;
liElemCoordZ = (Math.random() - 0.5) * 3000;
$(this).css({
"transform": `translate3d(${liElemCoordX}px,${liElemCoordY}px,${liElemCoordZ}px)`,
"transition": "4s ease-in-out"
})
});
currentStyle = chaoticLayout;
}
function main() {
$([...Array(liElemMaxNum).keys()]).each(i => {
// 创建一个li 元素
liElem = $('<li></li>');
let idx = randomFrom(0, data.length - 1);
// 创建一个span 元素
spanElem = $(`<span>${data[idx]}</span>`);
liElem.append(spanElem);
// 设置span 中的文本颜色
spanElem.css('color',
`rgb(${randomFrom(100,255)},${randomFrom(100,255)},${randomFrom(100,255)})`);
// 将已创建的li 元素添加至容器中
$('#box').append(liElem);
})
// 布局类型
layoutStyle = [gridLayout, helixLayout, chaoticLayout, sphereLayout,
threeLayout, geomeLayout, curveLayout
];
// 鼠标移入移出效果
$('#box li').hover(function () {
$(this).css('border', '1px solid rgba(125,255,255,0.75)');
$(this).css('boxShadow', '0 0 15px rgba(0,255,255,0.75)');
$(this).css('transition', '0s');
}, function () {
$(this).css('border', '1px solid rgba(125,255,255,0.25)');
$(this).css('boxShadow', '0 0 15px rgba(0,255,255,0.5)');
$(this).css('transition', '0s');
})
// 鼠标点击,切换布局
$('#box li').click(function () {
switch ($(this).text()) {
case 'Grid':
gridLayout();
break;
case 'Helix':
helixLayout();
break;
case 'Three':
threeLayout();
break;
case 'Geome':
geomeLayout();
break;
case 'Curve':
curveLayout();
break;
case 'Sphere':
sphereLayout();
break;
case 'Chaotic':
chaoticLayout();
break;
default:
while (true) {
idx = randomFrom(0, layoutStyle.length - 1);
if (layoutStyle[idx] != currentStyle) {
return layoutStyle[idx]();
}
}
break;
}
})
// 鼠标拖动与滚轮效果
$(document).mousedown(function (event) {
event = event || window.event;
// 上一个点的X、Y坐标
oldCoordX = event.clientX;
oldCoordY = event.clientY;
$(this).on('mousemove', event => {
event = event || window.event;
// 若上一个定时器存在,则将其删除
timer && clearInterval(timer);
// 当前点的X、Y坐标
nowCoordX = event.clientX;
nowCoordY = event.clientY;
// 计算机X、Y差值
minusX = nowCoordX - oldCoordX;
minusY = nowCoordY - oldCoordY;
// 更新上一个点的X、Y坐标值
oldCoordX = nowCoordX;
oldCoordY = nowCoordY;
// 计算X、Y轴的移动度数
liElemDegX -= minusY * 0.1;
liElemDegY += minusX * 0.1;
$('#box').css({
"transform": `translateZ(${liElemDepZ}px) rotateX(${liElemDegX}deg) rotateY(${liElemDegY}deg)`
})
}).mouseup(_ => {
// 当鼠标弹起解除移动
$(document).off('mousemove');
// 若上一个定时器存在,则将其删除
timer && clearInterval(timer);
// 鼠标弹起后有缓动效果
timer = setInterval(_ => {
// 缓动差值
minusX *= 0.95;
minusY *= 0.95;
// 计算X、Y轴的移动度数
liElemDegX -= minusY * 0.1;
liElemDegY += minusX * 0.1;
// 当差值超出指定范围时,则清除定时器
Math.abs(minusX) < 0.05 &&
Math.abs(minusY) < 0.05 &&
clearInterval(timer);
$('#box').css({
"transform": `translateZ(${liElemDepZ}px) rotateX(${liElemDegX}deg) rotateY(${liElemDegY}deg)`
})
}, 12);
})
}).on('mousewheel DOMMouseScroll', e => {
// 若上一个定时器存在,则将其删除
timer && clearInterval(timer);
// 获取鼠标滚动方向
let step = (e.originalEvent.wheelDelta &&
(e.originalEvent.wheelDelta > 0 ? 1 : -1)) ||
(e.originalEvent.detail && (e.originalEvent.detail > 0 ? -1 : 1));
// 计算滚轮滚动时Z 轴景深的步长
liElemDepZ = depDefault += step * 90;
$('#box').css({
"transform": `translateZ(${liElemDepZ}px) rotateX(${liElemDegX}deg) rotateY(${liElemDegY}deg)`
})
// 设置缓动效果
timer = setInterval(_ => {
// 缓动步长
step *= 0.6;
liElemDepZ += step * 80;
Math.abs(step) < 0.000005 &&
clearInterval(timer);
$('#box').css({
"transform": `translateZ(${liElemDepZ}px) rotateX(${liElemDegX}deg) rotateY(${liElemDegY}deg)`
})
}, 12);
})
// 加载布局
setTimeout(gridLayout, 1000);
}
main();
})();
</script>
</body>
</html>
效果图如下: