如何让半透明颜色绘制时不进行叠加
================

#### 问题现象

使用CanvasRenderingContext2D.stroke绘制path时，重合的半透明笔迹会叠加。如何实现颜色不叠加效果？颜色叠加代码如下：

@Entry
@Component
struct Page {
  private settings: RenderingContextSettings \= new RenderingContextSettings(true);
  private context: CanvasRenderingContext2D \= new CanvasRenderingContext2D(this.settings);

  build() {
    Column() {
      Canvas(this.context)
        .onReady(() \=\> {
          this.context.lineWidth \= 40;
          this.context.strokeStyle \= '#5164fff0';
          this.context.moveTo(80, 20);
          this.context.lineTo(80, 220);
          this.context.stroke();
          this.context.beginPath();
          this.context.moveTo(20, 80);
          this.context.lineTo(220, 80);
          this.context.stroke();
          this.context.beginPath();
          this.context.moveTo(160, 20);
          this.context.lineTo(160, 220);
          this.context.stroke();
          this.context.beginPath();
          this.context.moveTo(20, 160);
          this.context.lineTo(220, 160);
          this.context.stroke();
        });
    }
    .height('100%')
    .width('100%');
  }
}

问题效果预览：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/61/v3/yTLm_JxESjKJmpfxlYkoVg/zh-cn_image_0000002628404770.png?HW-CC-KV=V1&HW-CC-Date=20260709T134100Z&HW-CC-Expire=86400&HW-CC-Sign=27D538C2641044343B2375D05AE997BBD1315890AFBB976CB0727B3D2302D706 "点击放大")

#### 效果预览

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/46/v3/HE_v_1StQfmA88yhlW-x0A/zh-cn_image_0000002628564676.png?HW-CC-KV=V1&HW-CC-Date=20260709T134100Z&HW-CC-Expire=86400&HW-CC-Sign=50D5A6CF311B340740BCDCD6A1F36EF42D76CC443B39289AAFB2507C4E9C6B42 "点击放大")

#### 背景知识

*   [CanvasRenderingContext2D](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-canvasrenderingcontext2d)对象实例可在[Canvas](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-components-canvas-canvas)画布组件上进行绘制，绘制对象可以是图形、文本、线段、图片等。
*   CanvasRenderingContext2D对象中有[stroke](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-canvasrenderingcontext2d#stroke)方法，可以根据当前的路径，进行边框绘制操作。

#### 解决方案

在绘制过程中如果让多个路径分别绘制，会让绘制出的图案颜色多次覆盖。如果是绘制用的颜色为半透明，颜色会进行叠加直到不透明。如果想让绘制的颜色不叠加有以下两种方式。

*   **方案一**：在同一个路径中绘制，颜色不叠加。
    
    @Entry
    @Component
    struct Page {
      private settings: RenderingContextSettings \= new RenderingContextSettings(true);
      private context: CanvasRenderingContext2D \= new CanvasRenderingContext2D(this.settings);
    
      build() {
        Column() {
          Canvas(this.context)
            .onReady(() \=\> {
              this.context.lineWidth \= 40;
              this.context.strokeStyle \= '#5164fff0';
              this.context.moveTo(80, 20);
              this.context.lineTo(80, 220);
              this.context.moveTo(20, 80);
              this.context.lineTo(220, 80);
              this.context.moveTo(160, 20);
              this.context.lineTo(160, 220);
              this.context.moveTo(20, 160);
              this.context.lineTo(220, 160);
              this.context.stroke();
            });
        }
        .height('100%')
        .width('100%');
      }
    }
    
*   **方案二**：在绘制第二段路径时，先设置[globalCompositeOperation](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-canvasrenderingcontext2d#globalcompositeoperation)属性为destination-out进行绘制，去除新路径上原有的颜色。再改回source-over绘制。
    
    @Entry
    @Component
    struct Page2 {
      private settings: RenderingContextSettings \= new RenderingContextSettings(true);
      private context: CanvasRenderingContext2D \= new CanvasRenderingContext2D(this.settings);
    
      build() {
        Column() {
          Canvas(this.context)
            .onReady(() \=\> {
           _   // 第一段，左边的垂直向下路径_
              this.context.lineWidth \= 40;
              this.context.strokeStyle \= '#5164fff0';
              this.context.moveTo(80, 20);
              this.context.lineTo(80, 220);
              this.context.stroke();
          _    // 第二段，上面的水平向右路径_
              this.context.beginPath();
              this.context.moveTo(20, 80);
              this.context.lineTo(220, 80);
              this.context.globalCompositeOperation \= 'destination-out';
              this.context.strokeStyle \= '#ff000000';
              this.context.stroke(); _// 去除路径上原有的颜色_
              this.context.globalCompositeOperation \= 'source-over';
              this.context.strokeStyle \= '#5164fff0';
              this.context.stroke(); _// 绘制路径_
            _  // 第三段，左边的垂直向下路径_
              this.context.beginPath();
              this.context.moveTo(160, 20);
              this.context.lineTo(160, 220);
              this.context.globalCompositeOperation \= 'destination-out';
              this.context.strokeStyle \= '#ff000000';
              this.context.stroke(); _// 去除路径上原有的颜色_
              this.context.globalCompositeOperation \= 'source-over';
              this.context.strokeStyle \= '#5164fff0';
              this.context.stroke(); _// 绘制路径_
            _  // 第四段，下面的水平向右路径_
              this.context.beginPath();
              this.context.moveTo(20, 160);
              this.context.lineTo(220, 160);
              this.context.globalCompositeOperation \= 'destination-out';
              this.context.strokeStyle \= '#ff000000';
              this.context.stroke(); _// 去除路径上原有的颜色_
              this.context.globalCompositeOperation \= 'source-over';
              this.context.strokeStyle \= '#5164fff0';
              this.context.stroke(); _// 绘制路径_
            });
        }
        .height('100%')
        .width('100%');
      }
    }