(function () { function Garden(canvas) { this.canvas = canvas; this.ctx = this.canvas.getContext('2d'); // 三维系在二维上的原点 this.vpx = undefined; this.vpy = undefined; this.balls = []; this.angleY = 0; this.angleX = 0; } Garden.prototype = { setBasePoint: function (x, y) { this.vpx = x; this.vpy = y; }, createBall: function (x, y, z, ballR) { this.balls.push(new Ball(this, x, y, z, ballR)); }, render: function () { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); this.balls.sort(function (a, b) { return b.z - a.z }); for (var i = 0; i < this.balls.length; i++) { this.balls[i].rotateY(); this.balls[i].rotateX(); this.balls[i].draw(i); } }, setListener: function () { var that = this; document.addEventListener('mousemove', function (event) { var x = event.clientX - that.vpx; var y = event.clientY - that.vpy; that.angleY = -x * 0.0001; that.angleX = y * 0.0001; }); } }; function Ball(garden, x, y, z, ballR) { this.garden = garden; // 三维上坐标 this.x = x === undefined ? Math.random() * 200 - 100 : x; this.y = y === undefined ? Math.random() * 200 - 100 : y; this.z = z === undefined ? Math.random() * 200 - 100 : z; this.r = Math.floor(Math.random() * 255); this.g = Math.floor(Math.random() * 255); this.b = Math.floor(Math.random() * 255); // 三维上半径 this.ballR = ballR === undefined ? 10 + Math.random() * 10 : ballR; // 二维上半径 this.radius = undefined; // 二维上坐标 this.x2 = undefined; this.y2 = undefined; } Ball.prototype = { // 绕y轴变化,得出新的x,z坐标 rotateY: function () { var cosy = Math.cos(this.garden.angleY); var siny = Math.sin(this.garden.angleY); var x1 = this.z * siny + this.x * cosy; var z1 = this.z * cosy - this.x * siny; this.x = x1; this.z = z1; }, // 绕x轴变化,得出新的y,z坐标 rotateX: function () { var cosx = Math.cos(this.garden.angleX); var sinx = Math.sin(this.garden.angleX); var y1 = this.y * cosx - this.z * sinx; var z1 = this.y * sinx + this.z * cosx; this.y = y1; this.z = z1; }, draw: function (a) { // focalLength 表示当前焦距,一般可设为一个常量 var focalLength = 300; // 把z方向扁平化 var scale = focalLength / (focalLength + this.z); this.x2 = this.garden.vpx + this.x * scale; this.y2 = this.garden.vpy + this.y * scale; this.radius = this.ballR * scale; this.garden.ctx.beginPath(); this.garden.ctx.fillStyle = 'rgba(' + this.r + ',' + this.g + ',' + this.b + ',' + Math.min(1, scale) + ')'; this.garden.ctx.arc(this.x2, this.y2, this.radius, 0, Math.PI * 2, true); this.garden.ctx.fill(); } }; $(function () { var canvas = $('#canvas')[0]; var garden = new Garden(canvas); // 设置原点(一般为画布中心) garden.setBasePoint(250, 250); // 构造三维系上的点 for (var i = 0; i < 10; i++) garden.createBall(); // 设置监听 garden.setListener(); // 渲染 setInterval(function () { garden.render(); }, 1000 / 60); }); })();
<canvas id='canvas' width=500 height=600 style='background-color:rgb(0,0,0)'> This browser does not support html5. </canvas>
body { background:#000; }