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>
相关推荐
醉の虾7 分钟前
Vue3 使用v-for 渲染列表数据后更新
前端·javascript·vue.js
张小小大智慧15 分钟前
TypeScript 的发展与基本语法
前端·javascript·typescript
hummhumm25 分钟前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j
asleep70137 分钟前
第8章利用CSS制作导航菜单
前端·css
hummhumm41 分钟前
第 28 章 - Go语言 Web 开发入门
java·开发语言·前端·python·sql·golang·前端框架
幼儿园的小霸王1 小时前
通过socket设置版本更新提示
前端·vue.js·webpack·typescript·前端框架·anti-design-vue
疯狂的沙粒1 小时前
对 TypeScript 中高级类型的理解?应该在哪些方面可以更好的使用!
前端·javascript·typescript
gqkmiss2 小时前
Chrome 浏览器 131 版本开发者工具(DevTools)更新内容
前端·chrome·浏览器·chrome devtools
Summer不秃2 小时前
Flutter之使用mqtt进行连接和信息传输的使用案例
前端·flutter
旭日猎鹰2 小时前
Flutter踩坑记录(二)-- GestureDetector+Expanded点击无效果
前端·javascript·flutter