Cutting out shapes

by soulwire

HTML

<canvas id="canvas" width="500" height="500"></canvas>

CSS

html, body {
    background: #fff url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MkNBQThENjVEN0E3MTFFMEI1M0NBNkNEQjM5RUM0NDciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MkNBQThENjZEN0E3MTFFMEI1M0NBNkNEQjM5RUM0NDciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoyQ0FBOEQ2M0Q3QTcxMUUwQjUzQ0E2Q0RCMzlFQzQ0NyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoyQ0FBOEQ2NEQ3QTcxMUUwQjUzQ0E2Q0RCMzlFQzQ0NyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PhyxyZ4AAAAySURBVHjaYpRV1XVgwAMe3bp0AJ88EwOFYNSAwWAA4/////EqkFPTcxgNxGFvAECAAQBhwQfL5RW1rAAAAABJRU5ErkJggg==') repeat;
}

JavaScript

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

// Fill background
ctx.fillStyle = 'rgba(0,0,0,0.9)';
ctx.fillRect(0,0,500,500);

ctx.save();

    // Set to cut out
    ctx.globalCompositeOperation = 'destination-out';
    
    // Cut circle
    ctx.beginPath();
    ctx.arc(250,250,50,0,Math.PI * 2);
    ctx.closePath();
    ctx.fillStyle = '#fff';
    ctx.fill();

ctx.restore();

// Draw outline
ctx.beginPath();
ctx.arc(250,250,50,0,Math.PI * 2);
ctx.closePath();
ctx.lineWidth = 5;
ctx.strokeStyle = '#FFFF00';
ctx.stroke();