HTML5实现3D球视觉特效
2013-06-21 01:28:48 -0400
<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="width: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>
Back to home
Subscribe |
Register |
Login
| N