Canvas clip()方法之橡皮擦应用

6,133 阅读3分钟

前言

本节要讨论的内容可以说是Canvas之中最为有用的一个功能:剪辑区域(clipping region)。它是在canvas之中由路径所定义的一块区域,浏览器会将所有的绘图操作都限制在本区域内执行。默认情况下,剪辑区域大小与canvas一致。 ——《HTML5 Canvas核心指南》

canvas的clip()方法可以使绘图操作仅在某一区域内执行,这便给人带来无限的想象空间,本文学习应用之一:橡皮擦。
具体代码放在CodePen之中 Demo如下(忽略百度搜索):

CodePen打开

由于本文主要讲橡皮擦应用,所以会忽略画图部分的思路 本文目录如下:

  • clip()方法解释
  • Demo思路
  • 代码分割
    • mousedown
    • mousemove
    • mouseup
  • 结语
  • 参考资料

clip()方法解释

The CanvasRenderingContext2D.clip() method of the Canvas 2D API turns the current or given path into the current clipping region. It replaces any previous clipping region. In the image below, the red outline represents a clipping region shaped like a star. Only those parts of the checkerboard pattern that are within the clipping region get drawn.  ——MDN

如上,图片中用路径圈了五角星区域,再用clip()方法截取区域,之后所有的绘图操作都只会在五角星区域之内生效

那我们怎么管理和变化正在使用的剪辑区域呢?举个例子,初始时剪辑区域默认为整片canvas画布,现在我们的剪辑区域是五角星,怎么恢复到整片画布的状态继续剪辑呢?
使用ctx.save()及ctx.restore()方法即可:CanvasRenderingContext2D.save()——The drawing state

在选定剪辑区域前,我们先使用ctx.save()保存当前状态,剪辑区域并且绘图操作完成后,再使用ctx.restore()恢复先前的剪辑区域即可

👆在橡皮擦应用中我们也会使用到这个技巧

Demo思路

首先解释两个比较重要的变量:lastX与lastY。
这两个变量用于记录欲擦除区域的位置,用于在setsetErasePathForEraser()方法中设置对应剪辑区域
在mousedown及mousemove阶段均有更新

总的思路图如下:

擦除功能主要在于eraseLast()方法,我们再对eraseLast()方法的思路进行解释

关键代码解释——eraseLast()

        function eraseLast() {
            ctx.save();
            
            setErasePathForEraser();//设置擦除路径
            // 👆setErasePathForEraser()方法中的ctx.clip()指定了剪辑区域,下面的效果只会在剪辑区域里发生
            ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)

            ctx.restore();
        }

第一步,ctx.save()方法保存了当前的剪辑区域(即默认的canvas画布);
第二步,setErasePathForEraser()方法中用ctx.clip()制定了剪辑区域,之后的绘图效果只会在剪辑区域中发生;
第三步,ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)清空画布,但由于指定了剪辑区域,效果只会在剪辑区域内发生;
最后,ctx.restore()方法恢复保存的canvas状态,恢复原来的剪辑区域(考虑继续绘图等情况)

结语

此Demo并不难,是对clip()方法最基本的应用,即圈定范围——>清空,就完成了橡皮擦的功能

参考资料

《HTML5 Canvas核心技术》
MDN——CanvasRenderingContext2D.clip()

MDN——CanvasRenderingContext2D.save()