Canvas
"Hidden" Buffer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | (function() { // For description of this technique, see justindonato.com var canvas = document.getElementById('canvas'); var buffer = document.getElementById('buffer'); var canvasCtx = canvas.getContext('2d'); var bufferCtx = buffer.getContext('2d'); // This object holds our clickable items. It's keys wil be hex color values. var clickables = {}; // A quick ball class that can render itself on a canvas context var Ball = function(x, y, radius, color, idColor) { this.x = x; this.y = y; this.radius = radius; this.origRadius = radius; this.color = color; this.idColor = idColor; this.stroke = 0; this.velX = .5 + (Math.random()); this.velY = .5 + (Math.random()); }; Ball.prototype.move = function() { this.x += this.velX; this.y += this.velY; }; Ball.prototype.render = function(ctx, color) { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0 , 2 * Math.PI, false); ctx.fillStyle = color; ctx.fill(); if (this.radius > this.origRadius) this.radius -= .1; }; Ball.prototype.bounce = function bounce() { if (this.x > 300 - (this.radius)) this.velX = this.velX * -1; if (this.x < (this.radius)) this.velX = this.velX * -1; if (this.y > 100 - (this.radius)) this.velY = this.velY * -1; if (this.y < (this.radius)) this.velY = this.velY * -1; } // Create two balls. // Make up an id (a Number) and convert it to a color. var id1 = Math.floor(Math.random() * 200000); var idColor1 = colorFromInt(id1); var ball = new Ball(20, 20, 20, '#B1CBCC', idColor1); var id2 = Math.floor(Math.random() * 200000); var idColor2 = colorFromInt(id2); var ball2 = new Ball(105, 25, 20, '#7ABAD6', idColor2); // Add the balls to our set of clickables clickables[idColor1] = ball; clickables[idColor2] = ball2; // Define some helper functions // Given an int, convert to hex and append hash for css-style color function colorFromInt(i) { var hex = i.toString(16); return \"#\" + zeroPadLeft(hex, 6); } function zeroPadLeft(str, len) { while(str.length < len) { str = '0' + str; } return str; } // When the mouse is clicked, draw each of the clickables on the // hidden buffer whereever they happen to be. Then grab the color from the // pixel under the mouse and see if we have a clickable for that function checkHit(e) { var ball; for (id in clickables) { ball = clickables[id]; ball.render(bufferCtx, ball.idColor); } var pixel = bufferCtx.getImageData(e.offsetX, e.offsetY, 1, 1); // Convert the pixel color to a hex string var color = \"#\"; for (var i = 0; i < pixel.data.length - 1; i++) { color += zeroPadLeft(pixel.data[i].toString(16), 2); } var hit = clickables[color]; if (hit) hit.radius += 7; } // The main loop, move and render balls function run() { canvasCtx.clearRect(0, 0, 300, 100); bufferCtx.clearRect(0, 0, 300, 100); var ball; for (id in clickables) { ball = clickables[id]; ball.move(); ball.render(canvasCtx, ball.color); ball.bounce(); } } var startBtn = document.getElementById('start'); startBtn.addEventListener('click', function() { startBtn.style.display = 'none'; // Listen for mouse up events to check hits canvas.addEventListener('mouseup', checkHit); // Start a loop at 60fps setInterval(run, 1000 / 60); }); // Run once just to show some circles run(); })() |