1e41f4b71Sopenharmony_ci# OffscreenCanvas 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ciOffscreenCanvas组件用于自定义绘制图形。 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci使用[Canvas](ts-components-canvas-canvas.md)组件或[Canvas API](ts-canvasrenderingcontext2d.md)时,渲染、动画和用户交互通常发生在应用程序的主线程上,与画布动画和渲染相关的计算可能会影响应用程序性能。OffscreenCanvas提供了一个可以在屏幕外渲染的画布,这样可以在单独的线程中运行一些任务,从而避免影响应用程序主线程性能。 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ci> **说明:** 8e41f4b71Sopenharmony_ci> 9e41f4b71Sopenharmony_ci> 该组件从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci## 子组件 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci不支持。 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci## 接口 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ciOffscreenCanvas(width: number, height: number, unit?: LengthMetricsUnit) 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ci**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。 20e41f4b71Sopenharmony_ci 21e41f4b71Sopenharmony_ci**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ci**系统能力:** SystemCapability.ArkUI.ArkUI.Full 24e41f4b71Sopenharmony_ci 25e41f4b71Sopenharmony_ci**参数:** 26e41f4b71Sopenharmony_ci 27e41f4b71Sopenharmony_ci| 参数名 | 类型 | 必填 | 说明 | 28e41f4b71Sopenharmony_ci| ------ | -------- | ---- | ------------------------------------- | 29e41f4b71Sopenharmony_ci| width | number | 是 | OffscreenCanvas组件的宽度。<br>默认单位为vp。 | 30e41f4b71Sopenharmony_ci| height | number | 是 | OffscreenCanvas组件的高度。<br>默认单位为vp。 | 31e41f4b71Sopenharmony_ci| unit<sup>12+</sup> | [LengthMetricsUnit](../js-apis-arkui-graphics.md#lengthmetricsunit12) | 否 | 用来配置OffscreenCanvas对象的单位模式,配置后无法动态更改,配置方法同[CanvasRenderingContext2D](ts-canvasrenderingcontext2d.md#lengthmetricsunit12)。<br>默认值:DEFAULT。 | 32e41f4b71Sopenharmony_ci 33e41f4b71Sopenharmony_ci## 属性 34e41f4b71Sopenharmony_ci 35e41f4b71Sopenharmony_ci**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ci**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 38e41f4b71Sopenharmony_ci 39e41f4b71Sopenharmony_ci**系统能力:** SystemCapability.ArkUI.ArkUI.Full 40e41f4b71Sopenharmony_ci 41e41f4b71Sopenharmony_ciOffscreenCanvas支持以下属性: 42e41f4b71Sopenharmony_ci 43e41f4b71Sopenharmony_ci| 名称 | 类型 | 只读 | 可选 | 说明 | 44e41f4b71Sopenharmony_ci| ------ | ------ | ------ | ------- | ---- | 45e41f4b71Sopenharmony_ci| width | number | 否 | 否 | OffscreenCanvas组件的宽度。<br>默认单位为vp。 | 46e41f4b71Sopenharmony_ci| height | number | 否 | 否 | OffscreenCanvas组件的高度。<br>默认单位为vp。 | 47e41f4b71Sopenharmony_ci 48e41f4b71Sopenharmony_ci### width 49e41f4b71Sopenharmony_ci 50e41f4b71Sopenharmony_ci```ts 51e41f4b71Sopenharmony_ci// xxx.ets 52e41f4b71Sopenharmony_ci@Entry 53e41f4b71Sopenharmony_ci@Component 54e41f4b71Sopenharmony_cistruct OffscreenCanvasPage { 55e41f4b71Sopenharmony_ci private settings: RenderingContextSettings = new RenderingContextSettings(true); 56e41f4b71Sopenharmony_ci private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); 57e41f4b71Sopenharmony_ci private offCanvas: OffscreenCanvas = new OffscreenCanvas(200, 300) 58e41f4b71Sopenharmony_ci 59e41f4b71Sopenharmony_ci build() { 60e41f4b71Sopenharmony_ci Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { 61e41f4b71Sopenharmony_ci Column() { 62e41f4b71Sopenharmony_ci Canvas(this.context) 63e41f4b71Sopenharmony_ci .width('100%') 64e41f4b71Sopenharmony_ci .height('100%') 65e41f4b71Sopenharmony_ci .borderWidth(5) 66e41f4b71Sopenharmony_ci .borderColor('#057D02') 67e41f4b71Sopenharmony_ci .backgroundColor('#FFFFFF') 68e41f4b71Sopenharmony_ci .onReady(() => { 69e41f4b71Sopenharmony_ci let offContext = this.offCanvas.getContext("2d", this.settings) 70e41f4b71Sopenharmony_ci offContext.fillStyle = '#CDCDCD' 71e41f4b71Sopenharmony_ci offContext.fillRect(0, 0, this.offCanvas.width, 150) 72e41f4b71Sopenharmony_ci let image = this.offCanvas.transferToImageBitmap() 73e41f4b71Sopenharmony_ci this.context.setTransform(1, 0, 0, 1, 50, 200) 74e41f4b71Sopenharmony_ci this.context.transferFromImageBitmap(image) 75e41f4b71Sopenharmony_ci }) 76e41f4b71Sopenharmony_ci } 77e41f4b71Sopenharmony_ci }.width('100%').height('100%') 78e41f4b71Sopenharmony_ci } 79e41f4b71Sopenharmony_ci} 80e41f4b71Sopenharmony_ci``` 81e41f4b71Sopenharmony_ci 82e41f4b71Sopenharmony_ci 83e41f4b71Sopenharmony_ci 84e41f4b71Sopenharmony_ci### height 85e41f4b71Sopenharmony_ci 86e41f4b71Sopenharmony_ci```ts 87e41f4b71Sopenharmony_ci// xxx.ets 88e41f4b71Sopenharmony_ci@Entry 89e41f4b71Sopenharmony_ci@Component 90e41f4b71Sopenharmony_cistruct OffscreenCanvasPage { 91e41f4b71Sopenharmony_ci private settings: RenderingContextSettings = new RenderingContextSettings(true); 92e41f4b71Sopenharmony_ci private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); 93e41f4b71Sopenharmony_ci private offCanvas: OffscreenCanvas = new OffscreenCanvas(200, 300) 94e41f4b71Sopenharmony_ci 95e41f4b71Sopenharmony_ci build() { 96e41f4b71Sopenharmony_ci Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { 97e41f4b71Sopenharmony_ci Column() { 98e41f4b71Sopenharmony_ci Canvas(this.context) 99e41f4b71Sopenharmony_ci .width('100%') 100e41f4b71Sopenharmony_ci .height('100%') 101e41f4b71Sopenharmony_ci .borderWidth(5) 102e41f4b71Sopenharmony_ci .borderColor('#057D02') 103e41f4b71Sopenharmony_ci .backgroundColor('#FFFFFF') 104e41f4b71Sopenharmony_ci .onReady(() => { 105e41f4b71Sopenharmony_ci let offContext = this.offCanvas.getContext("2d", this.settings) 106e41f4b71Sopenharmony_ci offContext.fillStyle = '#CDCDCD' 107e41f4b71Sopenharmony_ci offContext.fillRect(0, 0, 100, this.offCanvas.height) 108e41f4b71Sopenharmony_ci let image = this.offCanvas.transferToImageBitmap() 109e41f4b71Sopenharmony_ci this.context.setTransform(1, 0, 0, 1, 50, 200) 110e41f4b71Sopenharmony_ci this.context.transferFromImageBitmap(image) 111e41f4b71Sopenharmony_ci }) 112e41f4b71Sopenharmony_ci } 113e41f4b71Sopenharmony_ci }.width('100%').height('100%') 114e41f4b71Sopenharmony_ci } 115e41f4b71Sopenharmony_ci} 116e41f4b71Sopenharmony_ci``` 117e41f4b71Sopenharmony_ci 118e41f4b71Sopenharmony_ci 119e41f4b71Sopenharmony_ci 120e41f4b71Sopenharmony_ci## 方法 121e41f4b71Sopenharmony_ci 122e41f4b71Sopenharmony_ci### transferToImageBitmap 123e41f4b71Sopenharmony_ci 124e41f4b71Sopenharmony_citransferToImageBitmap(): ImageBitmap 125e41f4b71Sopenharmony_ci 126e41f4b71Sopenharmony_ci从OffscreenCanvas组件中最近渲染的图像创建一个ImageBitmap对象。 127e41f4b71Sopenharmony_ci 128e41f4b71Sopenharmony_ci**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。 129e41f4b71Sopenharmony_ci 130e41f4b71Sopenharmony_ci**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 131e41f4b71Sopenharmony_ci 132e41f4b71Sopenharmony_ci**系统能力:** SystemCapability.ArkUI.ArkUI.Full 133e41f4b71Sopenharmony_ci 134e41f4b71Sopenharmony_ci**返回值:** 135e41f4b71Sopenharmony_ci 136e41f4b71Sopenharmony_ci| 类型 | 描述 | 137e41f4b71Sopenharmony_ci| -------------------------------------------------- | ----------------------- | 138e41f4b71Sopenharmony_ci| [ImageBitmap](ts-components-canvas-imagebitmap.md) | 创建的ImageBitmap对象。 | 139e41f4b71Sopenharmony_ci 140e41f4b71Sopenharmony_ci**示例:** 141e41f4b71Sopenharmony_ci 142e41f4b71Sopenharmony_ci```ts 143e41f4b71Sopenharmony_ci// xxx.ets 144e41f4b71Sopenharmony_ci@Entry 145e41f4b71Sopenharmony_ci@Component 146e41f4b71Sopenharmony_cistruct OffscreenCanvasPage { 147e41f4b71Sopenharmony_ci private settings: RenderingContextSettings = new RenderingContextSettings(true) 148e41f4b71Sopenharmony_ci private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings) 149e41f4b71Sopenharmony_ci private offCanvas: OffscreenCanvas = new OffscreenCanvas(300, 500) 150e41f4b71Sopenharmony_ci 151e41f4b71Sopenharmony_ci build() { 152e41f4b71Sopenharmony_ci Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 153e41f4b71Sopenharmony_ci Canvas(this.context) 154e41f4b71Sopenharmony_ci .width('100%') 155e41f4b71Sopenharmony_ci .height('100%') 156e41f4b71Sopenharmony_ci .borderWidth(5) 157e41f4b71Sopenharmony_ci .borderColor('#057D02') 158e41f4b71Sopenharmony_ci .backgroundColor('#FFFFFF') 159e41f4b71Sopenharmony_ci .onReady(() => { 160e41f4b71Sopenharmony_ci let offContext = this.offCanvas.getContext("2d", this.settings) 161e41f4b71Sopenharmony_ci offContext.fillStyle = '#CDCDCD' 162e41f4b71Sopenharmony_ci offContext.fillRect(0, 0, 300, 500) 163e41f4b71Sopenharmony_ci offContext.fillStyle = '#000000' 164e41f4b71Sopenharmony_ci offContext.font = '70px serif bold' 165e41f4b71Sopenharmony_ci offContext.fillText("Offscreen : Hello World!", 20, 60) 166e41f4b71Sopenharmony_ci let image = this.offCanvas.transferToImageBitmap() 167e41f4b71Sopenharmony_ci this.context.transferFromImageBitmap(image) 168e41f4b71Sopenharmony_ci }) 169e41f4b71Sopenharmony_ci } 170e41f4b71Sopenharmony_ci .width('100%') 171e41f4b71Sopenharmony_ci .height('100%') 172e41f4b71Sopenharmony_ci } 173e41f4b71Sopenharmony_ci} 174e41f4b71Sopenharmony_ci``` 175e41f4b71Sopenharmony_ci 176e41f4b71Sopenharmony_ci 177e41f4b71Sopenharmony_ci 178e41f4b71Sopenharmony_ci### getContext<sup>10+</sup> 179e41f4b71Sopenharmony_ci 180e41f4b71Sopenharmony_cigetContext(contextType: "2d", options?: RenderingContextSettings): OffscreenCanvasRenderingContext2D 181e41f4b71Sopenharmony_ci 182e41f4b71Sopenharmony_ci返回OffscreenCanvas组件的绘图上下文。 183e41f4b71Sopenharmony_ci 184e41f4b71Sopenharmony_ci**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 185e41f4b71Sopenharmony_ci 186e41f4b71Sopenharmony_ci**系统能力:** SystemCapability.ArkUI.ArkUI.Full 187e41f4b71Sopenharmony_ci 188e41f4b71Sopenharmony_ci**参数:** 189e41f4b71Sopenharmony_ci 190e41f4b71Sopenharmony_ci| 参数名 | 类型 | 必填 | 说明 | 191e41f4b71Sopenharmony_ci| ----------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | 192e41f4b71Sopenharmony_ci| contextType | string | 是 | OffscreenCanvas组件绘图上下文的类型,当前仅支持"2d"类型。| 193e41f4b71Sopenharmony_ci| options | [RenderingContextSettings](ts-canvasrenderingcontext2d.md#renderingcontextsettings) | 否 | 用来配置OffscreenCanvasRenderingContext2D对象的参数,见[RenderingContextSettings](ts-canvasrenderingcontext2d.md#renderingcontextsettings)。<br>默认值:null。 | 194e41f4b71Sopenharmony_ci 195e41f4b71Sopenharmony_ci**返回值:** 196e41f4b71Sopenharmony_ci 197e41f4b71Sopenharmony_ci| 类型 | 描述 | 198e41f4b71Sopenharmony_ci| ------------------------------------------------------------ | --------------------------------- | 199e41f4b71Sopenharmony_ci| [OffscreenCanvasRenderingContext2D](ts-offscreencanvasrenderingcontext2d.md) | OffscreenCanvas组件的绘图上下文。如果getContext方法的入参contextType为"2d"以外类型(包括null或者undefined),返回null。 | 200e41f4b71Sopenharmony_ci 201e41f4b71Sopenharmony_ci**示例:** 202e41f4b71Sopenharmony_ci 203e41f4b71Sopenharmony_ci```ts 204e41f4b71Sopenharmony_ci@Entry 205e41f4b71Sopenharmony_ci@Component 206e41f4b71Sopenharmony_cistruct OffscreenCanvasExamplePage { 207e41f4b71Sopenharmony_ci private settings: RenderingContextSettings = new RenderingContextSettings(true); 208e41f4b71Sopenharmony_ci private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); 209e41f4b71Sopenharmony_ci private offscreenCanvas: OffscreenCanvas = new OffscreenCanvas(600, 800) 210e41f4b71Sopenharmony_ci 211e41f4b71Sopenharmony_ci build() { 212e41f4b71Sopenharmony_ci Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { 213e41f4b71Sopenharmony_ci Column() { 214e41f4b71Sopenharmony_ci Canvas(this.context) 215e41f4b71Sopenharmony_ci .width('100%') 216e41f4b71Sopenharmony_ci .height('100%') 217e41f4b71Sopenharmony_ci .backgroundColor('#FFFFFF') 218e41f4b71Sopenharmony_ci .onReady(() => { 219e41f4b71Sopenharmony_ci let offContext = this.offscreenCanvas.getContext("2d", this.settings) 220e41f4b71Sopenharmony_ci offContext.font = '70px sans-serif' 221e41f4b71Sopenharmony_ci offContext.fillText("Offscreen : Hello World!", 20, 60) 222e41f4b71Sopenharmony_ci offContext.fillStyle = "#0000ff" 223e41f4b71Sopenharmony_ci offContext.fillRect(230, 350, 50, 50) 224e41f4b71Sopenharmony_ci offContext.fillStyle = "#EE0077" 225e41f4b71Sopenharmony_ci offContext.translate(70, 70) 226e41f4b71Sopenharmony_ci offContext.fillRect(230, 350, 50, 50) 227e41f4b71Sopenharmony_ci offContext.fillStyle = "#77EE0077" 228e41f4b71Sopenharmony_ci offContext.translate(-70, -70) 229e41f4b71Sopenharmony_ci offContext.fillStyle = "#00ffff" 230e41f4b71Sopenharmony_ci offContext.rotate(45 * Math.PI / 180); 231e41f4b71Sopenharmony_ci offContext.fillRect(180, 120, 50, 50); 232e41f4b71Sopenharmony_ci offContext.rotate(-45 * Math.PI / 180); 233e41f4b71Sopenharmony_ci offContext.beginPath() 234e41f4b71Sopenharmony_ci offContext.moveTo(10, 150) 235e41f4b71Sopenharmony_ci offContext.bezierCurveTo(20, 100, 200, 100, 200, 20) 236e41f4b71Sopenharmony_ci offContext.stroke() 237e41f4b71Sopenharmony_ci offContext.fillStyle = '#FF00FF' 238e41f4b71Sopenharmony_ci offContext.fillRect(100, 100, 60, 60) 239e41f4b71Sopenharmony_ci let imageData = this.offscreenCanvas.transferToImageBitmap() 240e41f4b71Sopenharmony_ci this.context.transferFromImageBitmap(imageData) 241e41f4b71Sopenharmony_ci }) 242e41f4b71Sopenharmony_ci }.width('100%').height('100%') 243e41f4b71Sopenharmony_ci } 244e41f4b71Sopenharmony_ci .width('100%') 245e41f4b71Sopenharmony_ci .height('100%') 246e41f4b71Sopenharmony_ci } 247e41f4b71Sopenharmony_ci} 248e41f4b71Sopenharmony_ci``` 249e41f4b71Sopenharmony_ci 250e41f4b71Sopenharmony_ci 251e41f4b71Sopenharmony_ci 252e41f4b71Sopenharmony_ci 253e41f4b71Sopenharmony_ci## OffscreenCanvas支持并发线程绘制 254e41f4b71Sopenharmony_ci 255e41f4b71Sopenharmony_ci从API version 11开始,当应用创建[Worker线程](../../../arkts-utils/worker-introduction.md),支持使用postMessage将OffscreenCanvas实例传到Worker中进行绘制,并使用onmessage接收Worker线程发送的绘制结果进行显示。 256e41f4b71Sopenharmony_ci 257e41f4b71Sopenharmony_ci> **说明:** 258e41f4b71Sopenharmony_ci> 259e41f4b71Sopenharmony_ci> OffscreenCanvas对象使用getContext获取绘图上下文后,不允许通过postMessage传该对象给其他线程,否则抛出异常。 260e41f4b71Sopenharmony_ci> 261e41f4b71Sopenharmony_ci> 已经通过postMessage传OffscreenCanvas对象到某一线程,声明该对象的线程不允许该对象使用getContext和transferToImageBitmap方法,否则抛出异常。 262e41f4b71Sopenharmony_ci> 263e41f4b71Sopenharmony_ci> 已经通过postMessage传OffscreenCanvas对象到某一线程,不允许再将该对象通过postMessage传给其他线程,否则抛出异常。 264e41f4b71Sopenharmony_ci 265e41f4b71Sopenharmony_ci**示例:** 266e41f4b71Sopenharmony_ci 267e41f4b71Sopenharmony_ci```ts 268e41f4b71Sopenharmony_ciimport { worker } from '@kit.ArkTS'; 269e41f4b71Sopenharmony_ci 270e41f4b71Sopenharmony_ci@Entry 271e41f4b71Sopenharmony_ci@Component 272e41f4b71Sopenharmony_cistruct OffscreenCanvasExamplePage { 273e41f4b71Sopenharmony_ci private settings: RenderingContextSettings = new RenderingContextSettings(true); 274e41f4b71Sopenharmony_ci private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); 275e41f4b71Sopenharmony_ci private myWorker = new worker.ThreadWorker('entry/ets/workers/Worker.ts'); 276e41f4b71Sopenharmony_ci 277e41f4b71Sopenharmony_ci build() { 278e41f4b71Sopenharmony_ci Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { 279e41f4b71Sopenharmony_ci Column() { 280e41f4b71Sopenharmony_ci Canvas(this.context) 281e41f4b71Sopenharmony_ci .width('100%') 282e41f4b71Sopenharmony_ci .height('100%') 283e41f4b71Sopenharmony_ci .borderWidth(5) 284e41f4b71Sopenharmony_ci .borderColor('#057D02') 285e41f4b71Sopenharmony_ci .backgroundColor('#FFFFFF') 286e41f4b71Sopenharmony_ci .onReady(() => { 287e41f4b71Sopenharmony_ci let offCanvas = new OffscreenCanvas(600, 800) 288e41f4b71Sopenharmony_ci this.myWorker.postMessage({ myOffCanvas: offCanvas }); 289e41f4b71Sopenharmony_ci this.myWorker.onmessage = (e): void => { 290e41f4b71Sopenharmony_ci if (e.data.myImage) { 291e41f4b71Sopenharmony_ci let image: ImageBitmap = e.data.myImage 292e41f4b71Sopenharmony_ci this.context.transferFromImageBitmap(image) 293e41f4b71Sopenharmony_ci } 294e41f4b71Sopenharmony_ci } 295e41f4b71Sopenharmony_ci 296e41f4b71Sopenharmony_ci }) 297e41f4b71Sopenharmony_ci }.width('100%').height('100%') 298e41f4b71Sopenharmony_ci } 299e41f4b71Sopenharmony_ci .width('100%') 300e41f4b71Sopenharmony_ci .height('100%') 301e41f4b71Sopenharmony_ci } 302e41f4b71Sopenharmony_ci} 303e41f4b71Sopenharmony_ci``` 304e41f4b71Sopenharmony_ci 305e41f4b71Sopenharmony_ciWorker线程在onmessage中接收到主线程postMessage发送的OffscreenCanvas,并进行绘制。 306e41f4b71Sopenharmony_ci 307e41f4b71Sopenharmony_ci```ts 308e41f4b71Sopenharmony_ciworkerPort.onmessage = (e: MessageEvents) => { 309e41f4b71Sopenharmony_ci if (e.data.myOffCanvas) { 310e41f4b71Sopenharmony_ci let offCanvas: OffscreenCanvas = e.data.myOffCanvas 311e41f4b71Sopenharmony_ci let offContext = offCanvas.getContext("2d") 312e41f4b71Sopenharmony_ci offContext.fillStyle = '#CDCDCD' 313e41f4b71Sopenharmony_ci offContext.fillRect(0, 0, 200, 150) 314e41f4b71Sopenharmony_ci let image = offCanvas.transferToImageBitmap() 315e41f4b71Sopenharmony_ci workerPort.postMessage({ myImage: image }); 316e41f4b71Sopenharmony_ci } 317e41f4b71Sopenharmony_ci} 318e41f4b71Sopenharmony_ci``` 319e41f4b71Sopenharmony_ci 320e41f4b71Sopenharmony_ci 321e41f4b71Sopenharmony_ci 322