Clipping and Masking
Clipping restricts drawing operations to specific regions of the canvas, creating masks that hide or reveal content. This powerful technique enables effects like cutouts, vignettes, and complex compositions by limiting where subsequent drawings appear.
Understanding Clipping
Clipping defines a region (the clipping path) outside of which nothing can be drawn. Any drawing operation will only affect pixels within the current clipping region. Clipping is part of the canvas state and can be saved and restored.
Creating Clipping Regions
The clip() method sets the current path as the clipping region:
// Create a circular clipping region
canvas.beginPath();
canvas.arc(100, 100, 50, 0, Math.PI * 2);
canvas.clip();
// Subsequent drawings are clipped to the circle
canvas.setFillStyle(new Color(255, 0, 0)); // red
canvas.fillRect(0, 0, 200, 200); // Only circular area is filledClipping with Shapes
Rectangular Clipping
// Clip to rectangle
canvas.beginPath();
canvas.rect(50, 50, 100, 100);
canvas.clip();
canvas.setFillStyle(new Color(0, 0, 255)); // blue
canvas.fillRect(0, 0, 200, 200); // Only rectangle area visibleElliptical Clipping
// Clip to ellipse
canvas.beginPath();
canvas.ellipse(100, 100, 60, 40, 0, 0, Math.PI * 2);
canvas.clip();
canvas.setFillStyle(new Color(0, 128, 0)); // green
canvas.fillRect(0, 0, 200, 200);Complex Path Clipping
// Create star-shaped clipping region
canvas.beginPath();
const spikes = 5;
const outerRadius = 50;
const innerRadius = 25;
for (let i = 0; i < spikes * 2; i++) {
const radius = i % 2 === 0 ? outerRadius : innerRadius;
const angle = (i * Math.PI) / spikes;
const x = 100 + Math.cos(angle) * radius;
const y = 100 + Math.sin(angle) * radius;
if (i === 0) canvas.moveTo(x, y);
else canvas.lineTo(x, y);
}
canvas.closePath();
canvas.clip();
// Draw image or content within star shape
canvas.drawImage(myImage, 0, 0);Clipping works with compositing for advanced effects; see Composite Operations.
Masking Techniques
Text as Mask
// Use text as clipping mask
canvas.setFont(new Font({size: 48, weight: 'bold', family: 'Arial', faces: []}));
canvas.beginPath();
canvas.fillText('MASK', 50, 100);
canvas.clip();
// Draw content through text mask
canvas.setFillStyle(new Color(255, 0, 0)); // red
canvas.fillRect(0, 0, 200, 200);Image Masking
// Use image as mask (assuming maskImage is black and white)
canvas.drawImage(maskImage, 0, 0);
canvas.setGlobalCompositeOperation('source-in');
canvas.drawImage(contentImage, 0, 0);
canvas.setGlobalCompositeOperation('source-over');Layered Clipping
canvas.save();
// First clip level
canvas.beginPath();
canvas.arc(100, 100, 80, 0, Math.PI * 2);
canvas.clip();
// Second clip level (intersection)
canvas.beginPath();
canvas.rect(50, 50, 100, 100);
canvas.clip();
// Content only appears in intersection
canvas.setFillStyle(new Color(128, 0, 128)); // purple
canvas.fillRect(0, 0, 200, 200);
canvas.restore();Managing Clipping State
Clipping is part of the canvas state and can be saved and restored:
canvas.save();
// Set clipping
canvas.beginPath();
canvas.arc(100, 100, 50, 0, Math.PI * 2);
canvas.clip();
// Draw clipped content
canvas.setFillStyle(new Color(0, 0, 255)); // blue
canvas.fillRect(0, 0, 200, 200);
canvas.restore();
// Clipping is removed - draw normally
canvas.setFillStyle(new Color(255, 0, 0)); // red
canvas.fillRect(150, 150, 50, 50);Advanced Clipping Techniques
Inverse Clipping (Masking Outside)
// Create mask for area outside circle
canvas.save();
// Fill entire area
canvas.setFillStyle(new Color(0, 0, 0)); // black
canvas.fillRect(0, 0, 200, 200);
// Erase circle (creating hole)
canvas.setGlobalCompositeOperation('destination-out');
canvas.beginPath();
canvas.arc(100, 100, 50, 0, Math.PI * 2);
canvas.fill();
canvas.restore();Clipping with Transformations
canvas.save();
// Apply transformation
canvas.translate(100, 100);
canvas.rotate(Math.PI / 4);
// Create transformed clipping region
canvas.beginPath();
canvas.rect(-30, -30, 60, 60);
canvas.clip();
// Draw within transformed clip
canvas.setFillStyle(new Color(255, 165, 0)); // orange
canvas.fillRect(-50, -50, 100, 100);
canvas.restore();Multiple Clipping Regions
// Create multiple separate clipping regions
function drawWithMultipleClips() {
// First region
canvas.save();
canvas.beginPath();
canvas.arc(50, 50, 30, 0, Math.PI * 2);
canvas.clip();
canvas.setFillStyle(new Color(255, 0, 0)); // red
canvas.fillRect(0, 0, 100, 100);
canvas.restore();
// Second region
canvas.save();
canvas.beginPath();
canvas.arc(150, 150, 30, 0, Math.PI * 2);
canvas.clip();
canvas.setFillStyle(new Color(0, 0, 255)); // blue
canvas.fillRect(120, 120, 100, 100);
canvas.restore();
}Clipping and masking enable sophisticated visual effects, from simple cutouts to complex compositions, making your FxCanvas applications more visually compelling.