var circle = {x: 50, y: 50, radius: 50, contour: []}; var box = {x: 20, y: 20, width: 300, height: 300}; for(var a = 0; a < Math.PI * 2; a += Math.PI / circle.radius){ circle.contour.push({ _x: Math.sin(a) * circle.radius, _y: Math.cos(a) * circle.radius }); } var canvas = document.body.appendChild(document.createElement("canvas")).getContext("2d"); canvas.canvas.width = 400; canvas.canvas.height = 400; var loop = function(){ canvas.canvas.width = canvas.canvas.width; canvas.save(); canvas.fillRect(box.x, box.y, box.width, box.height); canvas.globalCompositeOperation = "destination-out"; canvas.fillRect(box.x + 20, box.y + 20, box.width - 40, box.height - 40); canvas.restore(); var circleCanvas = document.createElement("canvas").getContext("2d"); circleCanvas.canvas.width = canvas.canvas.width; circleCanvas.canvas.height = canvas.canvas.height; circleCanvas.save(); circleCanvas.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2); circleCanvas.fillStyle = "#aaa"; circleCanvas.fill(); circleCanvas.globalCompositeOperation = "destination-in"; circleCanvas.fillRect(box.x + 20, box.y + 20, box.width - 40, box.height - 40); circleCanvas.restore(); canvas.drawImage(circleCanvas.canvas, 0, 0); if(circle._x < box.x + 20){ circle._x = box.x + 20; } if(circle._y < box.y + 20){ circle._y = box.y + 20; } if(circle._x > box.x + box.width - 20){ circle._x = box.x + box.width - 20; } if(circle._y > box.y + box.height - 20){ circle._y = box.y + box.height - 20; } circle.contour.forEach(function(p){ p.x = p._x; p.y = p._y; if(circle.x + p.x < box.x + 20){ p.x = box.x + 20 - circle.x; } if(circle.y + p.y < box.y + 20){ p.y = box.y + 20 - circle.y; } if(circle.x + p.x > box.x + box.width - 20){ p.x = box.x + box.width - 20 - circle.x; } if(circle.y + p.y > box.y + box.height - 20){ p.y = box.y + box.height - 20 - circle.y; } canvas.strokeStyle = "green"; canvas.lineWidth = 3; canvas.lineTo(p.x + circle.x, p.y + circle.y); }); canvas.stroke(); circle.x = circle._x; circle.y = circle._y; requestAnimationFrame(loop); }; loop(); document.onmousemove = function(event){ circle._x = event.layerX; circle._y = event.layerY; };