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>
相关推荐
多多*19 分钟前
Spring之Bean的初始化 Bean的生命周期 全站式解析
java·开发语言·前端·数据库·后端·spring·servlet
linweidong24 分钟前
在企业级应用中,你如何构建一个全面的前端测试策略,包括单元测试、集成测试、端到端测试
前端·selenium·单元测试·集成测试·前端面试·mocha·前端面经
满怀101544 分钟前
【HTML 全栈进阶】从语义化到现代 Web 开发实战
前端·html
东锋1.31 小时前
前端动画库 Anime.js 的V4 版本,兼容 Vue、React
前端·javascript·vue.js
满怀10151 小时前
【Flask全栈开发指南】从零构建企业级Web应用
前端·python·flask·后端开发·全栈开发
小杨升级打怪中2 小时前
前端面经-webpack篇--定义、配置、构建流程、 Loader、Tree Shaking、懒加载与预加载、代码分割、 Plugin 机制
前端·webpack·node.js
Yvonne爱编码2 小时前
CSS- 4.4 固定定位(fixed)& 咖啡售卖官网实例
前端·css·html·状态模式·hbuilder
SuperherRo2 小时前
Web开发-JavaEE应用&SpringBoot栈&SnakeYaml反序列化链&JAR&WAR&构建打包
前端·java-ee·jar·反序列化·war·snakeyaml
大帅不是我2 小时前
Python多进程编程执行任务
java·前端·python
前端怎么个事2 小时前
框架的源码理解——V3中的ref和reactive
前端·javascript·vue.js