如何用JavaScript实现点击Canvas后填充指定区域的功能
实现方案
你可以通过坐标判断+Canvas路径奇偶填充规则实现需求,核心思路如下:
- 给Canvas绑定点击事件,获取点击位置相对于画布的坐标
- 对点击坐标做两层判断:是否在圆形范围内、是否不在正方形范围内
- 满足判断条件时,复用原有路径,使用
evenodd填充规则填充目标区域即可
完整可运行代码
<!DOCTYPE HTML> <html> <head> </head> <body> <canvas width="300" height="300" id="myCanvas" style="border:1px solid #000000;"></canvas> <script> const canvas = document.getElementById('myCanvas'); const context = canvas.getContext('2d'); const centerX = canvas.width / 2; const centerY = canvas.height / 2; const radius = 70; // 正方形边长与位置参数 const squareSize = 50; const squareLeft = centerX - squareSize/2; const squareTop = centerY - squareSize/2; // 绘制初始描边 function drawOutline() { context.beginPath(); context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); context.rect(squareLeft, squareTop, squareSize, squareSize); context.lineWidth = 5; context.strokeStyle = '#003300'; context.stroke(); } drawOutline(); // 判断点是否在圆内 function isPointInCircle(x, y) { const dx = x - centerX; const dy = y - centerY; return dx*dx + dy*dy <= radius*radius; } // 判断点是否在正方形内 function isPointInSquare(x, y) { return x >= squareLeft && x <= squareLeft + squareSize && y >= squareTop && y <= squareTop + squareSize; } // 点击事件绑定 canvas.addEventListener('click', function(e) { // 获取点击位置相对于canvas的坐标 const rect = canvas.getBoundingClientRect(); const clickX = e.clientX - rect.left; const clickY = e.clientY - rect.top; // 满足点击区域要求:圆内且正方形外 if (isPointInCircle(clickX, clickY) && !isPointInSquare(clickX, clickY)) { // 重绘路径后用evenodd规则填充,自动镂空正方形区域 context.beginPath(); context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); context.rect(squareLeft, squareTop, squareSize, squareSize); context.fillStyle = '#99cc99'; // 可自定义填充颜色 context.fill('evenodd'); // 重绘描边避免填充覆盖边框 drawOutline(); } }) </script> </body> </html>
核心实现说明
evenodd填充规则:计算路径重叠次数,奇数区域填充、偶数区域镂空,刚好适配你需要的「圆形扣掉正方形」的填充范围- 坐标判断逻辑避免了误触:只有点击目标区域才会触发填充,点击正方形内部、圆形外部都不会有反应
- 填充后重绘描边是为了避免填充色覆盖半透明的边框线条,保证显示效果和初始样式一致
内容的提问来源于stack exchange,提问作者Allen Ye
相关产品推荐
相关产品推荐

