忽想起,一个3D球面标签的效果很帅气。逐思考如何实现。一番思考,判断我能想出的算法太龊了。立即google百度之,得:http://www.cnblogs.com/hongru/archive/2010/12/19/1910476.html感觉很不错。它是根据鼠标的滑动后,得出一个鼠标的变量值。根据了这个变量值,判断球旋转的方向。结果又些没看明白。不管了,秉承一贯的拿来主义手法,把改在了C++(使用MFC)平台重现之。不错... 没看懂当然不能这样就过去了,这也无非是数学问题嘛,好歹也是学过数学的人啊。 “然后通过绕原点的矩阵变换公式(这个公式网上可以查到) var z = this.y * Sphere.sx + this.z * Sphere.cx; this.y = this.y * Sphere.cx + this.z * -Sphere.sx; this.z = this.x * -Sphere.sy + z * Sphere.cy; this.x = this.x * Sphere.cy + z * Sphere.sy;” 三下五除二,就在网上搜索了一大片,却没有一个说绕原点旋转的。咋一下,三维空间中,绕点旋转其实就是绕轴旋转么?逐查询之,思考之。
上图是从z轴正方向往下看的平面图。某一点从A到B,△x,△y表示由鼠标的变化量所产生的对对点偏移影响的关于x,y轴的偏移量。简单的说,可以认为是鼠标从A到B,△x,△y就是相应的x,y轴的偏移量。从A到B无非就是绕x,y轴旋转一定的角度后到得。根据下面的坐标转换公式,然后复合就可以得到。
算法中的sx,sy,cx,cy就是sin△x,sin△y,cos△x,cos△y。其中,它为了简便它就转换的角度直接使用了x,y轴的变化量了。其中算法中的公式就是上两个转换矩阵的相乘.... 效果图:
附其原型的javascript实现代码:
<!DOCTYPE html>
<html>
<head>
<title>3D Sphere</title>
<meta name="Author" content="hongru.chen" />
<style type="text/css">
html {
overflow: hidden;
}
body {
position: absolute;
margin: 0px;
padding: 0px;
background: #222;
width: 100%;
height: 100%;
}
#screen {
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background: #000;
overflow: hidden;
}
#screen .plo {
position: absolute;
font-size: 1px;
cursor: pointer;
}
</style>
<script type="text/javascript">
var Sphere = {
/* ==== variables ==== */
O : [],
x : 0,
y : 0,
ax : 0,
ay : 0,
/* ==== init script ==== */
init : function () {
Sphere.screen = document.getElementById('screen');
onresize = Sphere.resize;
for (var i = 0; i < 200; i++) {
o = {};
/* ==== plot ==== */
o.plo = document.createElement('div');
o.plo.className = 'plo out';
Sphere.screen.appendChild(o.plo);
var r = .4
var a = Math.random() * Math.PI * 2;
var b = Math.random() * Math.PI * 2;
o.x = Math.sin(a) * Math.sin(b) * r;
o.y = Math.cos(a) * Math.sin(b) * r;
o.z = Math.cos(b) * r;
/* ==== push object ==== */
Sphere.O.push(o);
/* ==== 3D transform function ==== */
o.transform = function () {
/* ==== Rotation ==== */
var z = this.y * Sphere.sx + this.z * Sphere.cx;
this.y = this.y * Sphere.cx + this.z * -Sphere.sx;
this.z = this.x * -Sphere.sy + z * Sphere.cy;
this.x = this.x * Sphere.cy + z * Sphere.sy;
/* ==== 3D to 2D ==== */
var scale = 1 / (1 + this.z);
var x = this.x * scale * Sphere.screen.w * (Sphere.screen.h / Sphere.screen.w);
var y = this.y * scale * Sphere.screen.h;
var c = Math.round(256 + (-this.z * 256));
/* ==== plot ==== */
var p = this.plo.style;
p.left = Math.round(x + Sphere.screen.w - scale * 2) + 'px';
p.top = Math.round(y + Sphere.screen.h - scale * 2) + 'px';
p.width = Math.round(scale * 2) + 'px';
p.height = Math.round(scale * 2) + 'px';
p.background = 'rgb('.concat((c),',',(c),',',(512 - c),')');
p.zIndex = 200 + Math.floor(-this.z * 100);
}
}
/* ==== start script ==== */
Sphere.resize();
Sphere.run();
},
/* ==== resize window ==== */
resize : function ()
{
Sphere.screen.w = Sphere.screen.offsetWidth / 2;
Sphere.screen.h = Sphere.screen.offsetHeight / 2;
},
/* ==== main loop ==== */
run : function ()
{
/* ==== mouse ==== */
Sphere.x = mouse.x;
Sphere.y = mouse.y;
var sx = (Sphere.y - Sphere.ax) * (10 / Sphere.screen.h);
var sy = (Sphere.x - Sphere.ay) * (10 / Sphere.screen.w);
Sphere.ax += sx;
Sphere.ay += sy;
/* ==== angles sin and cos ==== */
Sphere.cx = Math.cos( sx * .01);
Sphere.sx = Math.sin( sx * .01);
Sphere.cy = Math.cos(-sy * .01);
Sphere.sy = Math.sin(-sy * .01);
/* ==== loop through all points ==== */
for (var i = 0, o; o = Sphere.O[i]; i++) o.transform();
/* ==== loop ==== */
setTimeout(Sphere.run, 16);
}
}
/* ==== global mouse position ==== */
var mouse = {
x : 0,
y : 0
}
document.onmousemove = function(e) {
if (window.event) e = window.event;
mouse.x = e.clientX;
mouse.y = e.clientY;
return false;
}
/* ==== start script ==== */
onload = function () {
setTimeout(Sphere.init, 500);
}
</script></head>
<body>
<div id="screen">
</div>
</body>
</html>
<!DOCTYPE html><html><head><title>3D Sphere</title><meta name="Author" content="hongru.chen" /><style type="text/css">html {overflow: hidden;}body {position: absolute;margin: 0px;padding: 0px;background: #222;width: 100%;height: 100%;}#screen {position: absolute;left: 0px;top: 0px;width: 100%;height: 100%;background: #000;overflow: hidden;}#screen .plo {position: absolute;font-size: 1px;cursor: pointer;}</style><script type="text/javascript"> var Sphere = {/* ==== variables ==== */O : [],x : 0,y : 0,ax : 0,ay : 0,/* ==== init script ==== */init : function () {Sphere.screen = document.getElementById('screen');onresize = Sphere.resize;for (var i = 0; i < 200; i++) {o = {};/* ==== plot ==== */o.plo = document.createElement('div');o.plo.className = 'plo out';Sphere.screen.appendChild(o.plo);var r = .4 var a = Math.random() * Math.PI * 2; var b = Math.random() * Math.PI * 2; o.x = Math.sin(a) * Math.sin(b) * r; o.y = Math.cos(a) * Math.sin(b) * r; o.z = Math.cos(b) * r;/* ==== push object ==== */Sphere.O.push(o);/* ==== 3D transform function ==== */o.transform = function () {/* ==== Rotation ==== */var z = this.y * Sphere.sx + this.z * Sphere.cx;this.y = this.y * Sphere.cx + this.z * -Sphere.sx;this.z = this.x * -Sphere.sy + z * Sphere.cy;this.x = this.x * Sphere.cy + z * Sphere.sy;/* ==== 3D to 2D ==== */var scale = 1 / (1 + this.z);var x = this.x * scale * Sphere.screen.w * (Sphere.screen.h / Sphere.screen.w);var y = this.y * scale * Sphere.screen.h;var c = Math.round(256 + (-this.z * 256));/* ==== plot ==== */var p = this.plo.style;p.left = Math.round(x + Sphere.screen.w - scale * 2) + 'px';p.top = Math.round(y + Sphere.screen.h - scale * 2) + 'px';p.width = Math.round(scale * 2) + 'px';p.height = Math.round(scale * 2) + 'px';p.background = 'rgb('.concat((c),',',(c),',',(512 - c),')');p.zIndex = 200 + Math.floor(-this.z * 100);}}/* ==== start script ==== */Sphere.resize();Sphere.run();},/* ==== resize window ==== */resize : function (){Sphere.screen.w = Sphere.screen.offsetWidth / 2;Sphere.screen.h = Sphere.screen.offsetHeight / 2;},/* ==== main loop ==== */run : function (){/* ==== mouse ==== */Sphere.x = mouse.x;Sphere.y = mouse.y;var sx = (Sphere.y - Sphere.ax) * (10 / Sphere.screen.h);var sy = (Sphere.x - Sphere.ay) * (10 / Sphere.screen.w);Sphere.ax += sx;Sphere.ay += sy;/* ==== angles sin and cos ==== */ Sphere.cx = Math.cos( sx * .01);Sphere.sx = Math.sin( sx * .01);Sphere.cy = Math.cos(-sy * .01);Sphere.sy = Math.sin(-sy * .01);/* ==== loop through all points ==== */for (var i = 0, o; o = Sphere.O[i]; i++) o.transform();/* ==== loop ==== */setTimeout(Sphere.run, 16);}}/* ==== global mouse position ==== */var mouse = {x : 0,y : 0}document.onmousemove = function(e) {if (window.event) e = window.event;mouse.x = e.clientX;mouse.y = e.clientY;return false;}/* ==== start script ==== */onload = function () {setTimeout(Sphere.init, 500);}</script></head><body> <div id="screen"> </div></body></html>