# 深浅色模式切换页面渲染失败

#### 问题现象

在Tabs的tabBar中使用Canvas，当深浅色模式切换后，tabBar中的内容消失。

问题效果预览：

#### 效果预览

#### 背景知识

*   Canvas提供画布组件，用于自定义绘制图形，开发者使用CanvasRenderingContext2D对象和OffscreenCanvasRenderingContext2D对象在Canvas组件上进行绘制，绘制对象可以是基础形状、文本、图片等。
*   组件树指的是用户界面（UI）的组件层次结构。在ArkTS开发环境中，UI组件是组成应用界面的基本元素，它们按照一定的层次关系组织在一起，形成了组件树。组件树的根节点通常是应用的主窗口，而子节点则是各种UI组件，如按钮、文本框、图像等。

#### 解决方案

出现上述问题是因为在切换深浅色模式时，Canvas组件会被销毁并重新创建，此时在tabBar中使用的Canvas组件会在短时间内重新渲染并重新加载到组件树中，从而使得CanvasRenderingContext2D被旧的Canvas组件绑定，而新的Canvas组件无法正确绘制内容。为了解决上述问题，可以将CanvasRenderingContext2D和Canvas组件封装为一个自定义组件，以避免这种情况。

```
interface ITabs {
  name: string;
  currentName?: string;
  previousName?: string;
  canvasRenderingContext: CanvasRenderingContext2D;
}

const tabList: ITabs[] = [
  { name: 'home', canvasRenderingContext: new CanvasRenderingContext2D() },
  {
    name: 'category',
    canvasRenderingContext: new CanvasRenderingContext2D()
  },
  { name: 'cart', canvasRenderingContext: new CanvasRenderingContext2D() },
  { name: 'my', canvasRenderingContext: new CanvasRenderingContext2D() },
];

@Component
struct TabBuilderLottie {
  @Prop index: number;

  build() {
    Canvas(tabList[this.index].canvasRenderingContext)
      .onReady(() => {
        let path = new Path2D();
        path.moveTo(150, 50);
        path.lineTo(50, 150);
        path.lineTo(100, 250);
        path.lineTo(200, 250);
        path.lineTo(250, 150);
        path.closePath();
        // 设定填充色为蓝色
        tabList[this.index].canvasRenderingContext.fillStyle = '#0097D4';
        // 使用填充的方式，将Path2D描述的五边形绘制在canvas组件内部
        tabList[this.index].canvasRenderingContext.fill(path);
        tabList[this.index].canvasRenderingContext.fillStyle = '#0097D4';
        // 以(50,50)为左上顶点，画一个宽高200的矩形
        tabList[this.index].canvasRenderingContext.fillRect(50, 50, 200, 200);
        // 以(70,70)为左上顶点，清除宽150高100的区域
        tabList[this.index].canvasRenderingContext.clearRect(70, 70, 150, 100);
        tabList[this.index].canvasRenderingContext.restore();
      });
  }
}

@Entry
@Component
struct TabBuilderLottiePage {
  @State tabs: ITabs[] = tabList;

  build() {
    Tabs({ barPosition: BarPosition.End }) {
      ForEach(this.tabs, (item: ITabs, index: number) => {
        TabContent() {
          Text(item.name);
        }
        .tabBar(this.TabBuilderLottie(index));
      });
    }
    .width('100%')
    .height('100%')
    .barMode(BarMode.Fixed)
    .barHeight(60)
    .fadingEdge(false)
    .scrollable(false);
  }

  @Builder
  TabBuilderLottie(index: number) {
    TabBuilderLottie({ index: index });
  }
}
```