[原]javascript 仿3D球体旋转文本 不含透视

说明:用javascript做3D效果的原理,通过三角函数将3D坐标降维成2D坐标,使之视觉上看起来像3D。
注意:javascript中三角函数所用到的参数是角的弧度而不是角度。
 有兴趣的朋友请到最下面代码范本(<-点我^^)下copy下来保存到记事本内将后缀名改为htm并不用客气地玩弄它  >///< ....
 
============================================================
在开始之前,我们要做一些准备,比如 
css 之类:
*{margin:0px; font-family:Tahoma; cursor:default;} body{background-color:#888888;} 
容器之类:
<div id="dvMain" style="background-color:#222222; width:400px; height:400px; overflow:hidden; position:absolute; z-index:-200;"></div>
文本在此容器内旋转。
============================================================
// 乱七八糟的声明
    var jsBox = { tagObj: function(id) { return document.getElementById(id); }, strJoin: function(strArr) { return strArr.join(""); } } // var tagArr = []; var tagArr = [[10, 100, 100, "A"], [49, 50, 0, "B"], [50, -50, 60, "C"], [-49, -50, 0, "D"], [-100, 50, 30, "E"], [0, 0, -100, "F"],[60,21,54,"G"]]; // [[x轴, y轴, z轴, txt], ...] // var tagArr = [[0, 0, 100, "A"], [0, 100, 0, "B"], [100, 0, 0, "C"], [0, -100, 0, "D"], [-100, 0, 0, "E"], [0, 0, -100, "F"]]; var r = 100; // 标准半径 var o = [200, 200]; // 容器内转动轴心坐标 var fs_c = 20; // 轴心时的字体大小 var c_c = 10; // 轴心时的字体颜色 var rdegree = 0; // 鼠标偏差角度 var siv = null, sto = null; // 计时器 var sivSeed; // 计时器单位时间
// 初始 tagArr 数组
    var init_tagArr = function() {
        var x, y, z;
        for (var i = 0, ilen = 26; i < ilen; i++) {
            x = Math.floor(Math.random() * 201) - 100;
            y = Math.floor(Math.random() * 201) - 100;
            z = Math.floor(Math.random() * 201) - 100;
            tagArr.push([x, y, z, i + "", 0, 0, 0, 0]);
        }
    };
// 模板
    var tagUnit = function() {
        var span = document.createElement("span");
        span.style.position = "absolute";
        return span;
    };
// 容器 dvMain 内添加文本标签
    var initTag = function() {
        var i = 0;
        var main = jsBox.tagObj("dvMain");
        var taLen = tagArr.length;
        var tmpZ, tmpZM, tmpZD;
        var c0, c1, c2;
        var obj;
        var objStyle;
        while (i < taLen) {
            obj = tagUnit();
            obj.id = "sp" + i;
            if (obj.innerText != undefined) {
                obj.innerText = tagArr[i][3];
            }
            else {
                obj.textContent = tagArr[i][3];
            }
    // 按 z轴 每30个坐标单位为一颜色梯度
            tmpZ = Math.floor(tagArr[i][2] / 30);
            c2 = c1 = c0 = c_c + tmpZ;

            objStyle = obj.style;
            objStyle.zIndex = tagArr[i][2];
            objStyle.fontSize = Math.round((tagArr[i][2]) / 10) + fs_c + "px";
            objStyle.color = "#" + c0.toString(16) + "" + c1.toString(16) + "" + c2.toString(16);
            objStyle.top = o[1] - tagArr[i][1] + "px";
            objStyle.left = o[0] + tagArr[i][0] + "px";
            main.appendChild(obj);

            obj.onmouseover = function(ev) {
                var item;
                item = !ev ? window.event.srcElement : ev.target;
                item.style.backgroundColor = "#3300ff";
            }

            obj.onmouseout = function(ev) {
                var item;
                item = !ev ? window.event.srcElement : ev.target;
                item.style.backgroundColor = "";
            }

            i++;
        }
    };
// 三角函数 通过角度数返回 正弦 余弦 正切
    var reSinAndCos = function(degree) {
        var arg = degree * Math.PI / 180;
        var sinVar = Math.sin(arg);
        var cosVar = Math.cos(arg);
        var tanVar = Math.tan(arg);
        return [sinVar, cosVar, tanVar];
    };
// 反三角函数 通过 直角边和斜边返回角度数
    var reDegree = function(b, c) {
        var sArg, cArg, sDg, cDg;
        if (c != 0) {
            sArg = Math.asin(b / c);
            cArg = Math.acos(b / c);
            sDg = sArg / (Math.PI / 180);
            cDg = cArg / (Math.PI / 180);
        }
        else {
            sDg = 0;
            cDg = 0;
        }
        return [sDg, cDg];
    };
// 设置旋转前必要值
    var setTagArrDegree = function() {
        var i = 0;
        var tLen = tagArr.length;
        var x, y, z, xy, r, d2d, dy, dyz, d3d;
        while (i < tLen) {
            x = tagArr[i][0], y = tagArr[i][1], z = tagArr[i][2];
            xy = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
            r = Math.sqrt(Math.pow(xy, 2) + Math.pow(z, 2));
    // 2D 下单位所处的角度 包括鼠标角度修正
            d2d = Math.abs(reDegree(x, xy)[0]);
            if (x == 0 && y == 0 || x == 0 && y > 0 || x > 0 && y > 0) {
                d2d += 0;
            }
            else if (x > 0 && y == 0) {
                d2d = 90;
            }
            else if (x > 0 && y < 0) {
                d2d = 180 - d2d;
            }
            else if (x == 0 && y < 0) {
                d2d = 180;
            }
            else if (x < 0 && y < 0) {
                d2d += 180;
            }
            else if (x < 0 && y == 0) {
                d2d = 270;
            }
            else if (x < 0 && y > 0) {
                d2d = 360 - d2d;
            }
            d2d = xy > 0 ? d2d - rdegree : d2d;
            d2d = d2d < 0 ? 360 + d2d : d2d;
    // 通过 2D 角度计算单位在 3D 下所处的地角度
            dy = xy * reSinAndCos(d2d)[1];
            dyz = Math.sqrt(Math.pow(dy, 2) + Math.pow(z, 2));
            d3d = Math.abs(reDegree(dy, dyz)[0]);
            if (z == 0 && dy == 0 || z > 0 && dy == 0 || z > 0 && dy > 0) {
                d3d += 0;
            }
            else if (z == 0 && dy > 0) {
                d3d = 90;
            }
            else if (z < 0 && dy > 0) {
                d3d = 180 - d3d;
            }
            else if (z < 0 && dy == 0) {
                d3d = 180;
            }
            else if (z < 0 && dy < 0) {
                d3d += 180;
            }
            else if (z == 0 && dy < 0) {
                d3d = 270;
            }
            else if (z > 0 && dy < 0) {
                d3d = 360 - d3d;
            }

            tagArr[i][4] = d3d;
            tagArr[i][5] = d2d;
            tagArr[i][6] = xy;
            tagArr[i][7] = r;
            i++;
        }
    };
// 旋转
    var Rotation3D = function(lf) {
        var _deg = 0;
        var argLen = arguments.length;

        this.rotationFun = function() {
            var id3d, id2d, ixy, ir, dx, dy;
            var a, b, c, zInd, tmpSC, tmpAl;
            var _a, _b;
            var z, zd, zm, c0, c1, c2;
            var ta_i;
            var tagObj;
            var i = 0;
            var tLen = tagArr.length;

            _deg++;
            while (i < tLen) {
                tagObj = jsBox.tagObj("sp" + i);
                ta_i = tagArr[i];
                id3d = ta_i[4], id2d = ta_i[5], ixy = ta_i[6], ir = ta_i[7];

                tmpSC = reSinAndCos((id3d + _deg) % 360);
                b = reSinAndCos(id2d)[0] * ixy; // 定边
                c = Math.sqrt(Math.pow(ir, 2) - Math.pow(b, 2));
                a = tmpSC[0] * c; // 变边

// 降维
                tmpAl = rdegree * Math.PI / 180;
                dx = b * Math.cos(tmpAl);
                dy = b * Math.sin(tmpAl);
                _a = Math.round(dy - a * Math.cos(tmpAl));
                _b = Math.round(dx + a * Math.sin(tmpAl));

                zInd = Math.round(tmpSC[1] * c);
                z = Math. floor(zInd / 30);
                c2 = c1 = c0 = c_c + z;
// 保存单位当前3D坐标
                ta_i = tagArr[i];
                ta_i[0] = _b;
                ta_i[1] = -_a;
                ta_i[2] = zInd;

                tagObj.style.zIndex = zInd;
                tagObj.style.fontSize = Math.round(zInd / 10) + fs_c + "px";
                tagObj.style.color = ["#", c0.toString(16), c1.toString(16), c2.toString(16)].join("");
                tagObj.style.left = o[0] + _b + "px";
                tagObj.style.top = o[1] + _a + "px";
                i++;
            }

            if (_deg == 360) {
                _deg = 0;
            }
            if (argLen == 1) { // Rotation3D 带参情况下为鼠标离开容器,触发转动渐停
                sivSeed += 1;
                sto = setTimeout(this.rotationFun, sivSeed);
                if (sivSeed > 100) {
                    clearTimeout(sto);
                    sto = null;
                    return;
                }
            }
        }

        this.runIt = function() {
            if (siv != null) {
                clearInterval(siv);
                siv = null;
            }
            if (sto != null) {
                clearTimeout(sto);
                sto = null;
            }
            if (argLen == 1) { // Rotation3D 带参情况下为鼠标离开容器,触发转动渐停
                setTagArrDegree();
                this.rotationFun();
            }
            else {
                siv = setInterval(this.rotationFun, sivSeed);
            }
        }

        this.runIt();
    }
// 鼠标
    var mouseRegion = function() {
        var main = jsBox.tagObj("dvMain");
        var x, y, _x, _y, xy, z, iy = 0, ix = 0, _iy, _ix;
        var deg, dtan, spd;
        main.onmousemove = function(event) {
            event = event || window.event;
            _x = event.clientX;
            _y = event.clientY;
    // 将鼠标位置转换成相对 2D 坐标
            x = _x - o[0]; 
            y = o[1] - _y;
    // 计算当前鼠标偏差角度
            dtan = Math.atan(x / y);
            deg = Math.round(dtan / (Math.PI / 180));
            if (x >= 0 && y >= 0) {
                deg += 0;
            }
            else if (y < 0) {
                deg += 180;
            }
            else {
                deg += 360;
            }

            _ix = Math.floor(x / 20);
            _iy = Math.floor(y / 20);            

            deg = Math.floor(deg / 10);
            deg = deg * 10;
            if (deg != rdegree || (_ix != ix || _iy != iy)) {
                z = Math.round(Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
                sivSeed = (Math.floor((284 - z) / 20) + 2) * 2; // 旋转强度
                ix = _ix;
                iy = _iy;
                rdegree = deg;
                setTagArrDegree();
                Rotation3D();
            }
        }

        main.onmouseout = function(event) {
            Rotation3D(1);
        }
    }
// 加载
    window.onload = function() {
        //init_tagArr();
        initTag();
        mouseRegion();
    }

===========================================================================
代码范本 有兴趣的朋友请copy下来并不用客气地玩弄它  >///< ....
===========================================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>斜向旋转</title>
    <style type="text/css">
        *{margin:0px; font-family:Tahoma; cursor:default;}
        body{background-color:#888888;} 
    </style>
</head>
<body>
    <div id="dvMain" style="background-color:#222222; width:400px; height:400px; overflow:hidden; position:absolute; z-index:-200;"></div>
</body>
</html>
<script type="text/javascript">
    var jsBox = {
        tagObj: function(id) {
            return document.getElementById(id);
        },

        strJoin: function(strArr) {
            return strArr.join("");
        }
    }

    //var tagArr = [];
    var tagArr = [[10, 100, 100, "A"], [49, 50, 0, "B"], [50, -50, 60, "C"], [-49, -50, 0, "D"], [-100, 50, 30, "E"], [0, 0, -100, "F"],[60,21,54,"G"]];
    //var tagArr = [[0, 0, 100, "A"], [0, 100, 0, "B"], [100, 0, 0, "C"], [0, -100, 0, "D"], [-100, 0, 0, "E"], [0, 0, -100, "F"]];
    var r = 100;
    var o = [200, 200];
    var fs_c = 20;
    var c_c = 10;
    var rdegree = 0;
    var siv = null, sto = null;
    var sivSeed;

    var init_tagArr = function() {
        var x, y, z;
        for (var i = 0, ilen = 26; i < ilen; i++) {
            x = Math.floor(Math.random() * 201) - 100;
            y = Math.floor(Math.random() * 201) - 100;
            z = Math.floor(Math.random() * 201) - 100;
            tagArr.push([x, y, z, i + "", 0, 0, 0, 0]);
        }
    };

    var tagUnit = function() {
        var span = document.createElement("span");
        span.style.position = "absolute";
        return span;
    };

    var initTag = function() {
        var i = 0;
        var main = jsBox.tagObj("dvMain");
        var taLen = tagArr.length;
        var tmpZ, tmpZM, tmpZD;
        var c0, c1, c2;
        var obj;
        var objStyle;
        while (i < taLen) {
            obj = tagUnit();
            obj.id = "sp" + i;
            if (obj.innerText != undefined) {
                obj.innerText = tagArr[i][3];
            }
            else {
                obj.textContent = tagArr[i][3];
            }
            tmpZ = Math.floor(tagArr[i][2] / 30);
            /*tmpZ = Math.round(tagArr[i][2] / 10);
            tmpZD = Math.floor(tmpZ / 3);
            tmpZM = tmpZ % 3;*/
            objStyle = obj.style;
            objStyle.zIndex = tagArr[i][2];
            objStyle.fontSize = Math.round((tagArr[i][2]) / 10) + fs_c + "px";
            c2 = c1 = c0 = c_c + tmpZ;

            objStyle.color = "#" + c0.toString(16) + "" + c1.toString(16) + "" + c2.toString(16);
            objStyle.top = o[1] - tagArr[i][1] + "px";
            objStyle.left = o[0] + tagArr[i][0] + "px";
            main.appendChild(obj);

            obj.onmouseover = function(ev) {
                var item;
                item = !ev ? window.event.srcElement : ev.target;
                item.style.backgroundColor = "#3300ff";
            }

            obj.onmouseout = function(ev) {
                var item;
                item = !ev ? window.event.srcElement : ev.target;
                item.style.backgroundColor = "";
            }

            i++;
        }
    };

    var reSinAndCos = function(degree) {
        var arg = degree * Math.PI / 180;
        var sinVar = Math.sin(arg);
        var cosVar = Math.cos(arg);
        var tanVar = Math.tan(arg);
        return [sinVar, cosVar, tanVar];
    };

    var reDegree = function(b, c) {
        var sArg, cArg, sDg, cDg;
        if (c != 0) {
            sArg = Math.asin(b / c);
            cArg = Math.acos(b / c);
            sDg = sArg / (Math.PI / 180);
            cDg = cArg / (Math.PI / 180);
        }
        else {
            sDg = 0;
            cDg = 0;
        }
        return [sDg, cDg];
    };

    var setTagArrDegree = function() {
        var i = 0;
        var tLen = tagArr.length;
        var x, y, z, xy, r, d2d, dy, dyz, d3d;
        while (i < tLen) {
            x = tagArr[i][0], y = tagArr[i][1], z = tagArr[i][2];
            xy = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
            r = Math.sqrt(Math.pow(xy, 2) + Math.pow(z, 2));
            d2d = Math.abs(reDegree(x, xy)[0]);
            if (x == 0 && y == 0 || x == 0 && y > 0 || x > 0 && y > 0) {
                d2d += 0;
            }
            else if (x > 0 && y == 0) {
                d2d = 90;
            }
            else if (x > 0 && y < 0) {
                d2d = 180 - d2d;
            }
            else if (x == 0 && y < 0) {
                d2d = 180;
            }
            else if (x < 0 && y < 0) {
                d2d += 180;
            }
            else if (x < 0 && y == 0) {
                d2d = 270;
            }
            else if (x < 0 && y > 0) {
                d2d = 360 - d2d;
            }
            d2d = xy > 0 ? d2d - rdegree : d2d;
            d2d = d2d < 0 ? 360 + d2d : d2d;

            dy = xy * reSinAndCos(d2d)[1];
            dyz = Math.sqrt(Math.pow(dy, 2) + Math.pow(z, 2));
            d3d = Math.abs(reDegree(dy, dyz)[0]);
            if (z == 0 && dy == 0 || z > 0 && dy == 0 || z > 0 && dy > 0) {
                d3d += 0;
            }
            else if (z == 0 && dy > 0) {
                d3d = 90;
            }
            else if (z < 0 && dy > 0) {
                d3d = 180 - d3d;
            }
            else if (z < 0 && dy == 0) {
                d3d = 180;
            }
            else if (z < 0 && dy < 0) {
                d3d += 180;
            }
            else if (z == 0 && dy < 0) {
                d3d = 270;
            }
            else if (z > 0 && dy < 0) {
                d3d = 360 - d3d;
            }

            tagArr[i][4] = d3d;
            tagArr[i][5] = d2d;
            tagArr[i][6] = xy;
            tagArr[i][7] = r;
            i++;
        }
    };


    var Rotation3D = function(lf) {
        var _deg = 0;
        var argLen = arguments.length;

        this.rotationFun = function() {
            var id3d, id2d, ixy, ir, dx, dy;
            var a, b, c, zInd, tmpSC, tmpAl;
            var _a, _b;
            var z, zd, zm, c0, c1, c2;
            var ta_i;
            var tagObj;
            var i = 0;
            var tLen = tagArr.length;

            _deg++;
            while (i < tLen) {
                tagObj = jsBox.tagObj("sp" + i);
                ta_i = tagArr[i];
                id3d = ta_i[4], id2d = ta_i[5], ixy = ta_i[6], ir = ta_i[7];

                tmpSC = reSinAndCos((id3d + _deg) % 360);
                b = reSinAndCos(id2d)[0] * ixy; // 定边
                c = Math.sqrt(Math.pow(ir, 2) - Math.pow(b, 2));
                a = tmpSC[0] * c; // 变边

                tmpAl = rdegree * Math.PI / 180;
                dx = b * Math.cos(tmpAl);
                dy = b * Math.sin(tmpAl);
                _a = Math.round(dy - a * Math.cos(tmpAl));
                _b = Math.round(dx + a * Math.sin(tmpAl));

                zInd = Math.round(tmpSC[1] * c);
                z = Math.floor(zInd / 30);
                /*z = Math.round(zInd / 10);
                zd = Math.floor(z / 3);
                zm = z % 3;*/
                c2 = c1 = c0 = c_c + z;

                ta_i = tagArr[i];
                ta_i[0] = _b;
                ta_i[1] = -_a;
                ta_i[2] = zInd;

                tagObj.style.zIndex = zInd;
                tagObj.style.fontSize = Math.round(zInd / 10) + fs_c + "px";
                tagObj.style.color = ["#", c0.toString(16), c1.toString(16), c2.toString(16)].join("");
                tagObj.style.left = o[0] + _b + "px";
                tagObj.style.top = o[1] + _a + "px";
                i++;
            }

            if (_deg == 360) {
                _deg = 0;
            }
            if (argLen == 1) {
                sivSeed += 1;
                sto = setTimeout(this.rotationFun, sivSeed);
                if (sivSeed > 100) {
                    clearTimeout(sto);
                    sto = null;
                    return;
                }
            }
        }

        this.runIt = function() {
            if (siv != null) {
                clearInterval(siv);
                siv = null;
            }
            if (sto != null) {
                clearTimeout(sto);
                sto = null;
            }
            if (argLen == 1) {
                setTagArrDegree();
                this.rotationFun();
            }
            else {
                siv = setInterval(this.rotationFun, sivSeed);
            }
        }

        this.runIt();
    }

    var mouseRegion = function() {
        var main = jsBox.tagObj("dvMain");
        var x, y, _x, _y, xy, z, iy = 0, ix = 0, _iy, _ix;
        var deg, dtan, spd;
        main.onmousemove = function(event) {
            event = event || window.event;
            _x = event.clientX;
            _y = event.clientY;
            x = _x - o[0];
            y = o[1] - _y;
            dtan = Math.atan(x / y);
            deg = Math.round(dtan / (Math.PI / 180));
            if (x >= 0 && y >= 0) {
                deg += 0;
            }
            else if (y < 0) {
                deg += 180;
            }
            else {
                deg += 360;
            }

            _ix = Math.floor(x / 20);
            _iy = Math.floor(y / 20);            

            deg = Math.floor(deg / 10);
            deg = deg * 10;
            if (deg != rdegree || (_ix != ix || _iy != iy)) {
                z = Math.round(Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
                sivSeed = (Math.floor((284 - z) / 20) + 2) * 2;
                ix = _ix;
                iy = _iy;
                rdegree = deg;
                setTagArrDegree();
                Rotation3D();
            }
        }

        main.onmouseout = function(event) {
            Rotation3D(1);
        }
    }

    window.onload = function() {
        //init_tagArr();
        initTag();
        mouseRegion();
    }
</script>
posted @ 2009-07-28 17:13  兼如  阅读(1488)  评论(3编辑  收藏  举报