HTML5实现3D球效果

效果图:

javascript 复制代码
<!DOCTYPE html>
<html>
<head>
	<meta name="format-detection" content="telephone=yes"/>
	<title>3d球型标签云</title>

</head>
<style>
    body {
    	background: #000
    }
    #main {
    	margin: 20px auto;
    	width: 450px;
    	height: 450px;
    	border: 1px solid green;
    	position: relative;
    	z-index: 10;
    }
    #main a {
    	position: absolute;
    	left: 0;
    	top: 0;
    	font-size: 15px;
    	font-weight: bolder;
    	text-decoration: none;
    	z-index: 9;
    }
    a:hover {
    	transform: scale(2);
    }
	.red {
		color: red;
	}
	.blue {
		color: blur;
	}
	.yellow {
		color: yellow;
	}
</style>
<body>
<div id="main"> 
	<a href="#">小仙女</a> 
	<a href="#" class="red">苹果</a> 
	<a href="#">香蕉</a> 
	<a href="#">西瓜</a> 
	<a href="#" class="blue">小仙女</a> 
	<a href="#">SEO</a> 
	<a href="#">小公主</a> 
	<a href="#" class="yellow">梨</a> 
	<a href="#">小泰迪</a> 
	<a href="#" class="red">CSS</a> 
	<a href="#">小猫咪</a> 
	<a href="#" class="blue">Java</a> 
	<a href="#">小度熊</a> 
	<a href="#">C#</a> 
	<a href="#">语言类别</a> 
	<a href="#" class="blue">西红柿</a> 
	<a href="#">C++</a> 
	<a href="#">C</a> 
	<a href="#">番茄</a> 
	<a href="#">demo</a>
</div> 
</body>
</html>
<script type="text/javascript">
document.getElementById('main').onclick=function() {
	window.location.hash = 'page';
	alert(11);
}

// 1.计算所有的标签在球面上的坐标
var main = document.getElementById('main');
var tagElement = document.getElementsByTagName('a');
var tagLength = tagElement.length;
var offsetList = [];
var radius = 120;
var tspeed = 10; 
var size = 250;
var active = false;
var d = 300;
var lasta = 1; 
var lastb = 1;
var mouseX = 0; 
var mouseY = 0; 


// 2.计算所有元素的offsetWidth,offsetHeight值
for (var i = 0; i < tagElement.length; i++) {
    offsetList.push({
    	offsetWidth: tagElement[i].offsetWidth,
    	offsetHeight: tagElement[i].offsetHeight
    });
};

calcXYZ();
// 鼠标移入事件
main.onmouseover = function (){ 
	active = true; 
}; 
// 鼠标移出事件
main.onmouseout = function () {
    active = false;
    // clearInterval(t);
}; 
main.onmousemove = function (event) {
	var e = window.event  || event; //兼容ie和其他浏览器的事件
	mouseX = (e.clientX - (main.offsetLeft + main.offsetWidth/2))/5;
    mouseY = (e.clientY - (main.offsetTop + main.offsetHeight/2))/5;
}
var t = setInterval(update, 30);




// 设置元素在球形坐标系的位置
function calcXYZ() {
	// var radomθ,radomΦ;
	for (var i = 0; i < tagElement.length; i++) {
		var radomθ = Math.acos(-1 + (2 * i)/tagLength); //θ = arccos(((2 * num)-1)/all - 1);
		var radomΦ = Math.sqrt(tagLength * Math.PI) * radomθ; //Φ = θ*sqrt(all * π);
		//x,y,z坐标的计算公式 x=r*sinθ*cosΦ   y=r*sinθ*sinΦ   z=r*cosθ;
		var x = radius * Math.sin(radomθ) * Math.cos(radomΦ);
		var y = radius * Math.sin(radomθ) * Math.sin(radomΦ);
		var z = radius * Math.cos(radomθ);
		offsetList[i].x = x;
		offsetList[i].y = y;
		offsetList[i].z = z;
		// 设置元素的位置
		tagElement[i].style.left = x + main.offsetWidth/2 - offsetList[i].offsetWidth/2 + 'px';
		tagElement[i].style.top = y + main.offsetHeight/2 - offsetList[i].offsetHeight/2 + 'px';
	}
}

// 计算中心点的sin,cos值
function sineCosine( a, b, c) {
    sa = Math.sin(a * (Math.PI/180));
    ca = Math.cos(a * (Math.PI/180)); 
    sb = Math.sin(b * (Math.PI/180));
    cb = Math.cos(b * (Math.PI/180));
    sc = Math.sin(c * (Math.PI/180));
    cc = Math.cos(c * (Math.PI/180));
}

// 球运动算法
function update() {
    var a, b; 
    if(active) { 
	    a = (-Math.min( Math.max( -mouseY, -size ), size ) / radius ) * tspeed; 
	    b = (Math.min( Math.max( -mouseX, -size ), size ) / radius ) * tspeed; 
	} 
	else 
	{ 
	    a = lasta * 0.98;
	    b = lastb * 0.98;
	} 

    lasta = a;
    lastb = b;

	if(Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) {
	    return;
	} 

    var c = 0;
    sineCosine(a,b,c);
    // 计算球旋转后的坐标
    for(var j = 0; j < tagLength; j++) {
		var rx1 = offsetList[j].x;
		var ry1 = offsetList[j].y * ca + offsetList[j].z * (-sa);
		var rz1 = offsetList[j].y * sa + offsetList[j].z * ca;

		var rx2 = rx1 * cb + rz1 * sb; 
		var ry2 = ry1; 
		var rz2 = rx1 * (-sb) + rz1 * cb;

		var rx3 = rx2 * cc + ry2 * (-sc);
		var ry3 = rx2 * sc + ry2 * cc;
		var rz3 = rz2;

		offsetList[j].x = rx3;
		offsetList[j].y = ry3;
		offsetList[j].z = rz3;

		per = d / (d + rz3);

		// offsetList[j].x=(howElliptical*rx3*per)-(howElliptical*2); 
		// offsetList[j].y=ry3*per; 
		// offsetList[j].scale=per; 
		offsetList[j].alpha = per;

		offsetList[j].alpha=(offsetList[j].alpha - 0.6)*(10/6); 
	} 
    doPosition();
// depthSort(); 
}


function doPosition() {
	// console.log(11);
    var l = main.offsetWidth/2;
    var t = main.offsetHeight/2;
    for(var i = 0; i < tagLength; i++) {
        tagElement[i].style.left = offsetList[i].x + l - offsetList[i].offsetWidth/2 + 'px';
        tagElement[i].style.top = offsetList[i].y + t - offsetList[i].offsetHeight/2 + 'px';
        // console.log(tagElement[i].style.left, tagElement[i].style.top)
        // tagElement[i].style.fontSize=Math.ceil(12*mcList[i].scale/2)+8+'px';

        // tagElement[i].style.filter="alpha(opacity="+100*mcList[i].alpha+")";
        tagElement[i].style.opacity = offsetList[i].alpha;
    }
} 
</script>
相关推荐
孔令飞44 分钟前
Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中
前端
溪语流沙1 小时前
【Web全栈进阶】PostgreSQL上手:Docker跑库 + 把早报站从SQLite迁过去
前端·docker·postgresql
IT_陈寒1 小时前
SpringBoot自动配置的坑:你以为的捷径可能是弯路
前端·人工智能·后端
paopaokaka_luck1 小时前
高校社团管理(AI辅助任务分配、协同过滤算法推荐、ECharts数据可视化、活动参与闭环、校园交流与反馈、器材借还管理)
java·前端·javascript·spring boot·数据分析·echarts
Dovis(誓平步青云)1 小时前
导览音频切换太快,旧讲解不能覆盖新展品
android·前端·javascript·ecmascript·音视频·宠物
福兮说12 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
郑州光合科技余经理13 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
小呆呆66613 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
Dovis(誓平步青云)14 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan14 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js