html实现3d视觉特效

<html>
<head>
<title>HTML5实现3D球效果</title>
<style type="text/css">  
#box{   
border:2px solid #f60; margin:0 auto;  
}  
</style>  
<script>
            var spaceX = 30; //X方向的密度
            var spaceY = 30; //Y方向的密度
            var PI = Math.PI; //数学角度π
            var radius = 200; //球的半径
            var radian = PI / 180; //弧度
            var speedX = 0; //X方向的速度
            var speedY = 0; //Y方向的速度
            var offsetX = 300; //X方向的偏移量相当于将球的中心X坐标移之到画布中央
            var offsetY = 300; //Y方向的偏移量相当于将球的中心Y坐标移之到画布中央
            var spheres = new Array(); //存储像素点
            var canvas; //画布
            var context; //上下文
            var focalLength = 300; //控制球距离屏幕的距离
            var start = true; //是否启动
            var sx = 0; //sinx
            var cx = 0; //cosx
            var sy = 0; //siny
            var cy = 0; //cosy
            var sz = 0; //sinz
            var cz = 0; //cosz
            var innerStaColor = "GREEN"; //表示内部颜色
            var outerStaColor = "RED"; //外部颜色
            var objectRadius = 10; //绘制原点半径
            var scaleRatio = 0;
            
            var cameraView = {
                x: 0,
                y: 0,
                z: 0,
                rotX: 0,
                rotY: 0,
                rotZ: 0
            }; //视角角度
            /**
            author:qingfeilee
            date:2012-03-28
            description:初始化系统画布信息
        **/
            function initCanvas() {
                try{ 
                    canvas = document.getElementById("sphere");
                    context = canvas.getContext("2d");
                }catch(e){
                     document.getElementById("tip_info").innerHTML = "您的浏览器不支持!";  
                }
            }
            /**
            author:qingfeilee
            date:2012-03-28
            description:初始化小球实体
        **/
            function initSphere() {
                for (var i = spaceY; i < 180; i += spaceY) {
                    for (var angle = 0; angle < 360; angle += spaceX) {
                        var object = {};
                        var x = Math.sin(radian * i) * radius;

                        object.x = Math.cos(angle * radian) * x;
                        object.y = Math.cos(radian * i) * radius;
                        object.z = Math.sin(angle * radian) * x;
                        object.glow = .5; //亮度的范围
                        spheres.push(object);
                    }
                }
            }
            /**
            author:qingfeilee
            date:2012-03-28
            description:初始化系统函数
        **/
            function init() {
                initCanvas();
                initSphere();
                setInterval(this.update, 1000 / 60, this);
                setTimeout(function() {
                    start = false;
                },
                1000);
            }
            /**
            author:qingfeilee
            date:2012-03-28
            description:设置整个大球的运转速度
        **/
            function setSpeed(speedX, speedY) {
                this.speedX = speedX;
                this.speedY = speedY;
            }
            /**
            author:qingfeilee
            date:2012-03-28
            description:更新整个球的状态以实现动态效果
        **/
            function update() {
                if (start) {
                    setParam();
                }
            }
            /**
            author:qingfeilee
            date:2012-03-28
            description:设置各个小球的属性
        **/
            function setParam() {
                //根据速度大小计算出一次旋转的角度大小
                var rotYstep = speedX / 10000;
                var rotXstep = speedY / 10000;
                cameraView.rotY = rotYstep;
                cameraView.rotX = -rotXstep;
                //计算出对应的cos和sin
                sx = Math.sin(cameraView.rotX);
                cx = Math.cos(cameraView.rotX);
                sy = Math.sin(cameraView.rotY);
                cy = Math.cos(cameraView.rotY);
                sz = Math.sin(cameraView.rotZ);
                cz = Math.cos(cameraView.rotZ);

                // 设置画布的效果
                context.fillStyle = 'rgba(0,0,0,0.1)';
                context.fillRect(0, 0, canvas.width, canvas.height);

                var l = spheres.length - 1;

                for (var i = l,
                obj; obj = spheres[i]; i--) {
                    render(obj);
                }
            }
            /**
            author:qingfeilee
            date:2012-03-28
            description:渲染整个画布
        **/
            function render(object) {
                var xy, xz, yx, yz, zx, zy;

                // 计算出物体的相对于照相机的位置
                var x = object.x - cameraView.x;
                var y = object.y - cameraView.y;
                var z = object.z - cameraView.z;
                
                // 绕X轴旋转
                xy = cx * y - sx * z;
                xz = sx * y + cx * z;
                // 绕Y轴旋转
                yz = cy * xz - sy * x;
                yx = sy * xz + cy * x;
                // 绕Z轴旋转
                zx = cz * yx - sz * xy;
                zy = sz * yx + cz * xy;
                //给各个球重新定位
                object.x = zx;
                object.y = zy;
                object.z = yz;

                //根据z轴数据来缩放球
                scaleRatio = focalLength / (focalLength + yz);
                scale = scaleRatio;

                if (object.glow > .5) {
                    object.glow -= .02;
                }

                var sphereStyle = context.createRadialGradient(offsetX + object.x * scaleRatio, offsetY + object.y * scaleRatio, 
                scaleRatio * .5, offsetX + object.x * scaleRatio, offsetY + object.y * scaleRatio, scaleRatio * objectRadius * .5);
                sphereStyle.addColorStop(0, innerStaColor);
                sphereStyle.addColorStop(object.glow, outerStaColor);
                sphereStyle.addColorStop(1, 'rgba(0,0,0,0)');

                context.fillStyle = sphereStyle;
                context.fillRect(offsetX + object.x * scaleRatio - scaleRatio * objectRadius * .5, 
                offsetY + object.y * scaleRatio - scaleRatio * objectRadius * .5, scaleRatio * objectRadius, scaleRatio * objectRadius);
                 document.getElementById("tip_info").innerHTML = "当前速度:"+speedX+"  "+ speedY+"   小球半径:"+objectRadius;  
                
            }
            /**
            author:qingfeilee
            date:2012-03-28
            description:冻结/激活真个大球状态
        **/
            function startOrPause() {
                if (start) {
                    setTimeout(function() {
                        start = false;
                    },
                    2000);
                    document.getElementById("swi").innerHTML = "激活";
                    innerStaColor = "GREEN";
                    outerStaColor = "RED";
                } else {
                    start = true;
                    document.getElementById("swi").innerHTML = "2秒后冻结";
                    innerStaColor = "RED";
                    outerStaColor = "GREEN";
                }
            }
            function changeObjectRadius(val) {
                this.objectRadius = val;
            }
            window.addEventListener("load", init, true);
        </script>
    </head>
    <body>
        <div id="box" style="600px; height:600px">  
            <canvas id="sphere" width="600" height="600" style="background:#0066FF">
            </canvas>
            <div align="center">
                <button id="swi" onclick="startOrPause()">激活</button>
                <button onclick="setSpeed(-150,0)">向东</button>
                <button onclick="setSpeed(150,0)">向西</button>
                <button onclick="setSpeed(0,-150)">向南</button>
                <button onclick="setSpeed(0,150)">向北</button>
                小球大小:    <input type="range" min="10" max="30" value="10" step="2" onchange="changeObjectRadius(this.value)"/>
            </div>
            <div align="center">
                <a id="tip_info">
                </a>
            </div>
            
        </div>
    </body>
</html>
原文地址:https://www.cnblogs.com/objects/p/7127325.html