Canvas路径、Canvas状态及其他

618 阅读6分钟

Canvas路径

对路径的理解,可以通过canvas提供的三个相关方法帮助理解

方法说明
beginPath()开始一条新的路径
closePath()关闭当前路径
isPointPath()判断某一个点是否存在于当前路径内

其中,前两个方法需要着重理解

beginPath()方法

该方法的含义是开辟一条新的路径,canvas是基于状态绘制图形的,每次绘制(stroke和fill),canvas都会检查整个程序定义的所有的状态,,当状态值发生改变的时候,根据是否使用了beginPath(),会出现两种不同的处理方式:

  1. 如果使用了beginPath()方法开始一条新的路径,则不同路径使用不同的值
  2. 如果没有使用beginPath()方法,则后面的值会覆盖前面的

判断是否属于同一路径的标准:是否使用了beginPath()方法,而不是视觉上是否线条相连

也就是说,只要两次绘制中间没有使用beginPath()方法,那这两次绘制就是属于同一路径

比如说:

<script type="text/javascript">
        function $$(id) {
            return document.getElementById(id);
        }
        window.onload = function () {
            var cnv = $$("canvas");
            var cxt = cnv.getContext("2d");

            cxt.lineWidth = 5;

            //第1条直线
            cxt.moveTo(50, 40);
            cxt.lineTo(150, 40);
            cxt.strokeStyle = "red";
            cxt.stroke();

            //第2条直线
            cxt.moveTo(50, 80);
            cxt.lineTo(150, 80);
            cxt.strokeStyle = "green";
            cxt.stroke();

            //第3条直线
            cxt.moveTo(50, 120);
            cxt.lineTo(150, 120);
            cxt.strokeStyle = "blue";
            cxt.stroke();
        }
    </script>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray"></canvas>

下载.png

这三条直线,虽然看着是三条不相连的单独直线,但是在代码中,三条直线绘制的时候,中间并没有使用beginPath()开辟新的路径,所以这三条直线其实是在同一路径,最好的验证就是三条直线的颜色都被最后一次设置的蓝色覆盖了,当使用beginPath()开辟新的路径的时候,效果如下

<script type="text/javascript">
        function $$(id) {
            return document.getElementById(id);
        }
        window.onload = function () {
            var cnv = $$("canvas");
            var cxt = cnv.getContext("2d");

            cxt.lineWidth = 5;

            //第1条直线
            cxt.beginPath();
            cxt.moveTo(50, 40);
            cxt.lineTo(150, 40);
            cxt.strokeStyle = "red";
            cxt.stroke();

            //第2条直线
            cxt.beginPath();
            cxt.moveTo(50, 80);
            cxt.lineTo(150, 80);
            cxt.strokeStyle = "green";
            cxt.stroke();

            //第3条直线
            cxt.beginPath();
            cxt.moveTo(50, 120);
            cxt.lineTo(150, 120);
            cxt.strokeStyle = "blue";
            cxt.stroke();
        }
    </script>
<canvas id="canvas" width="200" height="150" style="border:1px dashed gray"></canvas>

下载 (1).png

当每条直线都是独立路径的时候,独立路径之间的设置是不互相影响的

closePath()方法

closePath()方法强调的重点主要是:首尾、闭合

closePath()方法是用来关闭当前路径,使得图形呈现闭合状态,而不是结束路径,结束路径是beginPath()的任务

举个例子

<script>
        function $$(id){
            return document.getElementById(id)
        }
        window.onload = function (){
            var cnv = $$('canvas')
            var cxt = cnv.getContext('2d')

            cxt.beginPath()
            cxt.moveTo(120,70)
            cxt.arc(70,120,50,0,-90 * Math.PI / 180,true)
            cxt.closePath()
            cxt.stroke()

        }
    </script>
<canvas id="canvas" width="200" height="200" style="border: 1px dashed gray;"></canvas>

下载 (2).png 标记: 9EDEB17C-8971-4C8F-8F86-45903F6AD3DA.png

根据代码,绘制的起点是蓝点,但是圆弧的绘制是绿点到红点,如果没有closePath(),图案将会是绿点到红点的一段圆弧,当使用closePath(),路径的起点(蓝点)会分别和图案的首(绿点)尾点(红点)相连,使得图形封闭,这种情况很少,一般情况下路径的首和图案的首是重合的。

以上只是用于理解closePath()的封闭,实际closePath()的定义是连接起点和终点,关闭图形

Canvas状态

canvas中的两个重要概念,除了路径以外的另一个就是:状态。Canvas是基于状态绘制图形的

clip()方法

在Canvas中,我们可以配合使用clip()方法和基本图形的绘制来指定一个剪切区域,这个剪切区域是由基本图形绘制出来的,当我们指定剪切区域后,后面绘制的图形如果超出这个剪切区域,则超出的部分不会被展示。

clip()方法不支持strokeRect()和fillRect()方法,只能用rect()方法代替

可以理解为在Canvas区域内使用基本图形框选出一块区域,选定之后只能在这块区域内绘制,超出这块区域就不会展示

clearRect()方法清空画布,并不能清除clip的剪切状态

save()方法和restore()方法

Canvas为我们提供了两个操作状态的方法:save()方法和restore()方法,这两个方法一般情况下成对使用。

save()方法:保存当前状态

restore()方法:恢复之前保存的状态

Canvas状态的保存和恢复,主要用于以下3种场合:

  1. 图形或图片剪切。在Canvas中,我们可以在图形或者图片剪切,即clip()之前使用save()方法来保持当前状态,然后在剪切,即clip()之后可以使用restore()方法恢复之前保存的状态。
  2. 图形或图片变形。在Canvas中,我们可以在图形或者图片变形,即clip()之前使用save()方法来保持当前状态,然后在变形,即clip()之后使用restore()方法恢复之前保存的状态。
  3. 状态属性的改变。如果状态属性发生改变,我们可以在这些状态改变之前使用save()方法来保存,然后可以使用restore()方法恢复此状态。

其他应用

globalAlpha属性

作用:定义Canvas环境的透明度,默认值1.0为完全不透明,0为完全透明

该属性定义之后,会对整个画布都起作用

globalCompositeOperation属性

在Canvas中,经常会看到不同的图形交叉在一起,正常情况下,浏览器会按照图形绘制的顺序,依次显示每个图形,遵循“后来者居上”的原则,后面绘制的会覆盖前面绘制的图形。

如果想要改变交叉图形的显示方式,可以使用globalCompositeOperation属性

该属性的取值有很多,常见如下 值 描述 source-over 默认。在目标图像上显示源图像。 source-atop 在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。 source-in 在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。 source-out 在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。 destination-over 在源图像上方显示目标图像。 destination-atop 在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。 destination-in 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。 destination-out 在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。 lighter 显示源图像 + 目标图像。 copy 显示源图像。忽略目标图像。 xor 使用异或操作对源图像与目标图像进行组合。

属性值描述
source-over默认。在目标图像上显示源图像。
source-atop在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。
source-in在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。
source-out在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。
destination-over在源图像上方显示目标图像。
destination-atop在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。
destination-in在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。
destination-out在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
lighter显示源图像 + 目标图像。
copy显示源图像。忽略目标图像。
xor使用异或操作对源图像与目标图像进行组合。
darker两种图形都展示,在重叠部分,颜色由两种图形的颜色值相减后行成

图片1.png