美文网首页
三、Canvas基本绘图

三、Canvas基本绘图

作者: zdxhxh | 来源:发表于2020-10-10 11:01 被阅读0次

    Canvas绘图(二)

    本章将学习Canvas绘图的以下技巧

    • 裁剪区域
    • 图象合成
    • 简单的Canvas变换

    一、设置裁切区域

    使用Canvas裁切区域可以限制路径以及子路径的绘制区域,通过rect()函数设置一个用来绘图的矩形区域环境属性;然后调用clip()函数用rect()函数定义的矩形区域设置为裁切区域。那么,无论当前环境绘制什么内容,他只显示裁切区域以内的部分,也可以理解成绘图操作的一种蒙版。例如

    drawClip() {
        // 绘制一个大方块
        this.context.fillStyle = "#66ccff";
        this.context.fillRect(10, 10, 200, 200);
        this.context.save();
        this.context.beginPath();
    
        // 裁切画布从(0,0)点到50 x 50的正方形
        this.context.rect(0, 0, 50, 50);
        this.context.clip();
    
        // 红色圆
        this.context.beginPath();
        this.context.strokeStyle = "red";
        this.context.lineWidth = 5;
        this.context.arc(100, 100, 100, 0, (Math.PI / 180) * 360, false);
    
        // 整圆
        this.context.stroke();
        this.context.closePath();
    
        this.context.restore();
    
        // 再次裁切整个画布
        this.context.beginPath();
        this.context.rect(0, 0, 500, 500);
        this.context.clip();
    
        // 裁切一个没有 裁切的 蓝线
        this.context.beginPath();
        this.context.strokeStyle = "blue";
        this.context.lineWidth = 5;
        this.context.arc(100, 100, 50, 0, (Math.PI / 180) * 360, false);
        this.context.stroke();
        this.context.closePath();
    }
    
    image-20200927115701655.png

    首先,我们创建了50*50的矩形区域作为裁切区域,然后绘制一个红色圆弧形,但是所画的红色圆弧线只能看到在这个矩形以内的部分(有点类似overflow :hidden),最后将裁切区域调整为500 * 500,画一个蓝色圆弧。

    二、合成

    合成是指如何精细控制画布上对象的透明层与分层效果,有两个属性可以控制。 在Canvas中,默认情况下把Canvas之中的某个物体源绘制到另一个物体(目标)上时,浏览器就会简单的把源物体叠放在目标图像上。

    另外,Canvas每次绘制一个图形,就会将原有的Canvas图像作为目标图像,将将要绘制的图像作为源图像

    • globalAlpha : 该属性的默认值为1.0(完全不透明),取值范围为0.,0 ~1.0
    • globalCompositeOperation : 该属性在globalAlpah以及所有变换生效后,控制如何在当前Canvas位图中绘制图形,它由以下枚举值
    属性 说明
    source-over(默认) 默认。在目标图像上显示源图像。
    source-atop 在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。
    source-out 在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。
    source-in 在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。
    destination-over 在源图像上方显示目标图像。
    destination-atop 在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。
    destination-in 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的
    destination-out 在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
    copy 显示源图像。忽略目标图像。
    xor 使用异或操作对源图像与目标图像进行组合。
    lighter 显示源图像 + 目标图像。

    A. souce-over

    this.context.fillStyle = "black";
    this.context.fillRect(10, 10, 200, 200);
    // 红色正方形会叠加到黑色上面
    this.context.globalCompositeOperation = "source-over";
    this.context.fillStyle = "red";
    this.context.fillRect(1, 1, 50, 50);
    
    image-20200927143312392.png

    B. souce-atop

    this.context.globalCompositeOperation = "source-atop";
    this.context.fillRect(60, 1, 50, 50);
    
    image-20200927143414050.png

    C. source-in

    只有目标图像内的源图像部分会显示,目标图像是透明的

    this.context.globalCompositeOperation = "source-in";
    this.context.fillRect(1, 60, 50, 50);
    
    image-20200927143533513.png

    D. destination-over

    this.context.globalCompositeOperation = 'destination-over'
    this.context.fillRect(1, 1, 50, 50);
    
    image-20200927143654071.png

    E. destination-atop

    this.context.globalCompositeOperation = 'destination-atop'
    this.context.fillRect(1, 1, 50, 50);
    
    image-20200927143920874.png

    F. destination-in

    this.context.globalCompositeOperation = 'destination-in'
    this.context.fillRect(1, 1, 50, 50);
    
    image-20200927144044802.png

    G.destination-out

    this.context.globalCompositeOperation = 'destination-out'
    this.context.fillRect(1, 1, 50, 50);
    
    image-20200927144140182.png

    三、简单画布转换

    画布变换是指用数学方法调整绘制形状的物理数学,例如缩放与旋转,所有变换依赖后台的数学矩阵运算,我们不必去理解这些运算,我们将讨论如何调整Canvas属性来应用旋转和缩放变换。

    这里说一下 Canvas坐标变换的方式 :

    • 平移 : translate
    • 缩放 : scale
    • 旋转 : rotate

    而上面三种方式,都可以通过transform()矩阵变换做到,transform(m11,m12,m22,dx,dy),这个之后单独开一章节讲。

    A. 旋转和平移变换

    例如,我们对一个正方形进行旋转 .

    const x = 100,
          y = 100,
          width = 50,
          height = 50,
          angleRadians = (45 * Math.PI) / 180;
    this.context.translate(x + 0.5 * width, y + 0.5 * height);
    this.context.rotate(angleRadians);
    this.context.fillStyle = "red";
    this.context.fillRect(-0.5 *width, -0.5 * height, width, height);
    
    image-20200927153307450.png

    值得注意以下几点 :

    • translate() : 可以设置画布的原点,默认(0,0),这里设置为红色正方形的中点,那么就可以实现围绕中心点进行旋转了
    • fillRect(-05 * width,-0.5 * height...): 为什么绘制的原点是(-25,-25)呢?是因为原点改变了,现在是(125,125),所以要从(-25,-25)开始绘制

    例如绘制多个正方形

    drawRotateRects() {
        this.drawRect(50, 100, 40, 40, 45);
        this.drawRect(100, 100, 40, 40, 75);
        this.drawRect(150, 100, 40, 40, 90);
        this.drawRect(200, 100, 40, 40, 120);
    }
    
    drawRect(x, y, width, height, angle) {
        this.context.setTransform(1, 0, 0, 1, 0, 0);
        const angleInRadians = (angle * Math.PI) / 180;
        this.context.translate(x + 0.5 * width, y + 0.5 * height);
        this.context.rotate(angleInRadians);
        this.context.fillStyle = "red";
        this.context.fillRect(-0.5 * width, -0.5 * height, width, height);
    }
    
    image-20200927164013384.png

    this.context.setTransform(1, 0, 0, 1, 0, 0);这段代码你可以理解为重置Canvas变换设置

    B. 缩放变换

    接口 说明
    context.scale(x,y) x为x轴的缩放属性,y为y轴缩放属性,默认为1
    如果要把一个对象放大两倍,则可以将两个参数都设为2
    drawScaleRect() {
        this.context.fillRect(100, 100, 50, 50);
        this.context.setTransform(1, 0, 0, 1, 0, 0);
        this.context.scale(2, 2);
        this.context.fillStyle = "red";
        this.context.fillRect(100, 100, 50, 50);
    }
    
    image-20200927170139949.png

    这段代码工作方式与旋转差不多,由于没有平移原点对正方形进行缩放,而仍然用画布左上角作为原点,因此红色的正方形向右下方移动了。可以从中心点进行缩放,代码如下所示

    drawScaleRectByCenter() {
        this.context.fillRect(100, 100, 50, 50);
        this.context.globalCompositeOperation = 'destination-over'
        this.context.setTransform(1, 0, 0, 1, 0, 0);
        const x = 100,
        y = 100,
        width = 50,
        height = 50;
        this.context.translate(x + 0.5 * width, y + 0.5 * height);
        this.context.scale(2, 2);
        this.context.fillStyle = "red";
        this.context.fillRect(-0.5 * width, -0.5 * height, width, height);
    }
    
    image-20200927170539764.png

    最佳实践 : 任何形状的中心点都是(x + 0.5 * width, y + 0.5 * height)

    相关文章

      网友评论

          本文标题:三、Canvas基本绘图

          本文链接:https://www.haomeiwen.com/subject/cvfrpktx.html