介绍
简单手写3D地球星球无限无缝轮播
# 简单手写一个3D地球星球
# 开始自己手写一个好玩的3D地球星球轮播
代码思路,
1、 先定义好球体要在屏幕的位置
2、 定义好对应的球体数组,可以包含球体的信息,如要跳转和对应图片等
3、 计算好球体数量得出每个球的角度和旋转度, 如 六个球体, 360/6 得出对应的角度
4、点击旋转的思路, 先定义一个空数组收集每个球体的位置, 点击后,计算当前球体和点击球体的距离,也就是要旋转的圈数, 计算完后, 每个球体的角度加上上面得出的对应角度, 反之减减
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3D地球星球无缝轮播</title>
<style>
body{
background: #333;
}
.ellipse {
width: 100vw;
height: 160px;
border-radius: 50%;
position: absolute;
/* border: 2px #555 solid; */
transform-style: preserve-3d;
perspective: 800;/*在画框上设置透视*/
transform: rotateZ(80deg) rotateY(-80deg);
top: 50%;
z-index: 99999999;
}
.ellipse .circle {
width: 100px;
height: 100px;
border-radius: 50%;
top: 0;
left: 0;
right: 0;
bottom: 0;
/* margin: auto; */
position: absolute;
/* background: red; */
animation: move 10s linear infinite;
font-size: 12px;
color: #fff;
text-align: center;
line-height: 20px;
}
.circle .names{
position: absolute;
z-index: 99999;
font-size: 16px;
text-align: center;
width: 100%;
top: 50%;
transform: translateY(-50%) rotateY(180deg);
}
.cir_cont{
width: 500px;
height: 500px;
border-radius: 50%;
position: absolute;
transform: rotateZ(-380deg) translateX(550px) rotateZ(380deg) rotateY(90deg) rotate(-100deg) translateZ(-745px);
perspective: 400;/*在画框上设置透视*/
}
.cir_cont_link{
width: 940px;
height: 810px;
border-radius: 50%;
position: absolute;
transform: rotateZ(-380deg) translateX(1080px) rotateZ(380deg) rotateY(82deg) rotate(-90deg) translateZ(-1453px);
pointer-events: none;
perspective: 400;/*在画框上设置透视*/
opacity: 0.6;
}
img{
width: 100%;
}
.video-box {
position: relative;
height: 100vh;
background-color: #C1CFF7;
/*进行视频裁剪*/
overflow: hidden;
}
.video-box .video-background {
position: absolute;
left: 50%;
top: 50%;
/*保证视频内容始终居中*/
transform: translate(-50%, -50%);
width: 100%;
height: 100%;
/*保证视频充满屏幕*/
object-fit: cover;
min-height: 800px;
}
.logo{
width: 70px;
height: 70px;
position: absolute;
top: 33%;
left: 50.2%;
transform: translateY(-50%);
transform: translateX(-50%);
z-index: 99999999999999;
}
body::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
.logo_top{
position: absolute;
top: 0;
}
.title_png{
position: absolute;
width: 400px;
left: 50%;
transform: translateX(-50%);
top: 10px;
}
.cont_top{
position: absolute;
top: 0;
color: #fff;
padding: 15px 20px;
width: 90%;
display: flex;
justify-content: space-between;
}
.cont_top_img{
display: flex;
}
.cont_top img{
width: 30px;
margin: 0 10px;
}
.ig_3{
width: 26px !important;
height: 26px;
margin-top: 20px;
}
.left_t{
width: 200px;
position: absolute;
top: 150px;
left: 100px;
}
.right_t{
width: 200px;
position: absolute;
top: 150px;
right: 100px;
}
</style>
</head>
<body>
<div class="ellipse">
<!-- 地球的光环 -->
<div class="cir_cont_link" >
<img src="./baff9fb910e2912776b05b59335e32fbdd544f0847ea3-OdLKdw_fw1200.png" />
</div>
<!-- 地球 -->
<div class="cir_cont" >
<img src="./20230519115311.gif" />
</div>
</div>
<!-- 背景图 -->
<div class="video-box">
<video class="video-background" preload="auto" loop playsinline autoplay src="./WeChat_20230519103945.mp4" tabindex="-1" muted="muted"></video>
</div>
<div class="logo" >
</div>
<div class="logo_top">
<img src="./导航.png" />
<div class="cont_top">
<div>
2023-05-19 18:51:12
</div>
<div class="cont_top_img">
<img src="./形状 1.png" />
<img src="./形状 2.png" />
<img src="./形状 3.png" class="ig_3" />
</div>
</div>
</div>
<div class="left_t" >
<img src="./组 214.png" onclick="moveOne();res_init()"/>
</div>
<div class="right_t" >
<img src="./组 214 拷贝.png" onclick="moveOne2();res_init()"/>
</div>
</body>
<script src="./jquery-2.1.0.js" type="text/javascript" charset="utf-8"></script>
<script>
let tagArr = [ // 对应的选项 球球
{img:'./1.png',title:'公租房',url:'https://www.baidu.com/'},
{img:'./1.png',title:'物业',url:'https://www.baidu.com/'},
{img:'./1.png',title:'安全生产',url:'https://www.baidu.com/'},
{img:'./1.png',title:'智慧社区',url:'https://www.baidu.com/'},
{img:'./1.png',title:'成本',url:'https://www.baidu.com/'},
{img:'./1.png',title:'营销数据',url:'https://www.baidu.com/'},
{img:'./1.png',title:'资产',url:'https://www.baidu.com/'},
{img:'./1.png',title:'其他',url:'https://www.baidu.com/'},
]
let arr = [];// 保存每个球的位置
let on_indexs = 0; // 当前的位置
let start = 360 / (tagArr.length ); // 计算需要多少标题
let ev_show = false; //判断是否是点击球的, 如果是球的才可以跳转连接
let on_url =''; // 当前选中的连接
//初始化方法
function init(){
// let num1= Math.floor(tagArr.length/3); //获取第一个拐弯的位置
// let num2 = Math.floor(tagArr.length - num1); //获取第二个拐弯的位置
tagArr.forEach((item,index)=>{
let org = {
x:450, //间隔
y:80, //扁平角度 与css上的宽度有关
z1:0,
z2:0,
niu:80, // 旋转度 与css上的宽度有关
}
org.z1 = Math.floor('-'+(start * index));
org.z2 = Math.floor(start * index);
// if(num1 == index || num2 == index){
// org.x = org.x + 80;
// }
arr.push(org) // 保存每个球的位置
// 开始渲染
$(".ellipse").append(`
<div class="circle circle${index}" onclick="on_index(${index},'${item.url}' )" onmouseenter="img_onmouseenter(${index})" onmouseleave="img_mouseleave(${index})" >
<img class='cir_img' src=${item.img} />
<div class=names>${item.title}</div>
</div>`);
$(".ellipse .circle"+index+"").css({transform:`rotateZ(${org.z1}deg) translateX(${org.x}px) rotateZ(${org.z2}deg) rotateY(${-org.y}deg) rotate(${org.niu}deg)`,transition:'transform 2s'});
})
}
function img_onmouseenter(index){
// var is=event.target;;
$(".ellipse .circle"+index+" .cir_img").attr("src",'./20230519104736.gif')
// console.info($(is).attr("src"))
}
function img_mouseleave(index){
// var is=event.target;;
$(".ellipse .circle"+index+" .cir_img").attr("src",'./1.png')
}
function on_index(index,url){ //点击后移动
ev_show=true
var is=event;
console.info(is.pageX,'---',on_indexs,'---',index)
on_url = url
let num = 0; // 前进多少圈
if(is.clientX > 700){ //点击的是右边的球球 应该像左滑
//1 上一个的位置 如果小于当前点击的位置, 那么就向左
if(index > on_indexs){ // 如果点击的大于当前位置, 那么就前进
num = index-on_indexs // 获取要交换的次数
}// 如果上一个位置是大于 当前点击的位置, 因为是点击右边, 那么也需要向左滑
else{
// 1 先算出上一个位置在整个圈的位置 并加上当前点击的位置 得出圈数
num = (arr.length-on_indexs) + index
}
for(let j = 0; j<num; j++){
moveOne(arr)
}
}else{ // 如果是点击左边的球球, 应该向右滑
// 如果上一个位置是 小于当前点击的位置, 那么就向右滑
if(index > on_indexs){
// 1 先算出点击的在全部中的位置 + 当前的位置
num = (arr.length-index) + on_indexs
}else{ // 如果是上一个点击的也就是当前的位置 大于点击的位置
num = on_indexs-index // 得出圈数
}
for(let j = 0; j<num; j++){
moveOne2(arr)
}
}
on_indexs = index
$(".ellipse .circle"+index+" .cir_img").attr("src",'./20230519104736.gif')
res_init() //重新构建样式
}
//重新构建css
function res_init(){
arr.forEach((item,index)=>{
$(".ellipse .circle"+index+"").css({transform:`rotateZ(${item.z1}deg) translateX(${item.x}px) rotateZ(${item.z2}deg) rotateY(${-item.y}deg) rotate(${item.niu}deg)`,transition:'transform 2s'});
})
}
init()
// 向前
function moveOne() {
// let tt = arr[arr.length-1]
// let first = arr[0]
// let second = arr[1]
for (let i = 0; i < arr.length; i++) {
// arr[i] = first
// first = second
// second = arr[i+1]
arr[i].z1 = arr[i].z1 + start
arr[i].z2 = arr[i].z2 - start
}
// tt.z1 = start
// tt.z2 = -start
// arr[0] = tt
}
// 向后
function moveOne2() {
// let tt = arr[arr.length-1]
// let first = arr[arr.length-1]
// let second = arr[arr.length-2]
for (let i = 0; i < arr.length; i++) {
// arr[i] = first
// first = second
// second = arr[i+1]
arr[i].z1 = arr[i].z1 - start
arr[i].z2 = arr[i].z2 + start
}
}
var test = document.querySelector('.circle');
test.addEventListener("transitionend", (res)=>{
if(ev_show){
ev_show=false
window.open(on_url)
}
});
</script>
</html>