var canvas = document.getElementById('canvas'); var stage = new Stage(canvas); var createBall = function(radius) { radius = (radius === undefined) ? 20 : radius; var r = Math.floor(Math.random() * 255), g = Math.floor(Math.random() * 255), b = Math.floor(Math.random() * 255); return new Sprite(stage.ctx, { x: 0, y: 0, width: radius * 2, draw: function() { this.ctx.beginPath(); this.ctx.arc(0, 0, this.width / 2, 0, Math.PI * 2, true); this.ctx.closePath(); this.ctx.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + Math.min(1, this.width / (2 * radius)) + ')'; this.ctx.fill(); } }); }; var initialize = function() { var focalLength = 250, ballR = 5, ballN = 20, balls = [], vpx = 0, vpy = 0, angleY = 0, angleX = 0; for (var i = 0; i < ballN; i++) { var ball = createBall(ballR); stage.addChild(ball); ball.xpos = Math.random() * 200 - 100; ball.ypos = Math.random() * 200 - 100; ball.zpos = Math.random() * 200 - 100; balls.push(ball); } vpx = canvas.width / 2; vpy = canvas.height / 2; stage.addEventListener('mousemove', function(x, y) { angleY = (x - vpx) * .001; angleX = (y - vpy) * .001; }); function rotateY(ball, angleY) { var cosy = Math.cos(angleY), siny = Math.sin(angleY), x1 = ball.xpos * cosy - ball.zpos * siny, z1 = ball.zpos * cosy + ball.xpos * siny; ball.xpos = x1; ball.zpos = z1; } function rotateX(ball, angleX) { var cosx = Math.cos(angleX), sinx = Math.sin(angleX), y1 = ball.ypos * cosx - ball.zpos * sinx, z1 = ball.zpos * cosx + ball.ypos * sinx; ball.ypos = y1; ball.zpos = z1; } function render(ball) { if (ball.zpos > -focalLength) { var scale = focalLength / (focalLength + ball.zpos); ball.x = vpx + ball.xpos * scale; ball.y = vpy + ball.ypos * scale; ball.width = ballR * 2 * scale; var ck = document.getElementById('ck').checked; if (ck == false) ball.width = 0; } } function drawLinesBetweenBalls() { var ctx = stage.ctx; ctx.beginPath(); ctx.moveTo(balls[0].x, balls[0].y); for (var i = 0; i < balls.length; i++) { ctx.lineTo(balls[i].x, balls[i].y); } ctx.closePath(); ctx.stroke(); } function sortZ() { balls.sort(function(a, b) { return b.zpos - a.zpos }) stage.children.sort(function(a, b) { return b.zpos - a.zpos }) } stage.onRefresh = function() { for (var i = 0, ball; ball = balls[i]; i++) { rotateX(ball, angleX); rotateY(ball, angleY); render(ball); } //sortZ(); drawLinesBetweenBalls(); } stage.start(); }; onload = initialize;
<script src="http://hongru.github.com/js/JCanvas.js" ></script> <canvas id="canvas" width="600" height="400"></canvas> <p> <label for="ck">显示端点 </label> <input type="checkbox" checked="checked" id="ck" /> </p>
html {overflow:hidden} body {position: absolute; margin:0; padding:0;width:100%; height:100%;text-align:center} canvas {display:block;border:2px solid #ccc; margin:10px auto;} p {text-align: center; font-size:12px;color:#454545;}