在List组件中嵌套Canvas,滑动页面会出现轻微抖动。
问题代码示例参考如下:
import { display } from '@kit.ArkUI' @ComponentV2 @Entry export struct CanvasInListComponent { // 动画 @Local radianTest: number = 0 private settings: RenderingContextSettings = new RenderingContextSettings(true) private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings) private offCanvas: OffscreenCanvas = new OffscreenCanvas(600, 600) canvasTest = (): void => { let offContext = this.offCanvas.getContext('2d', this.settings) offContext.lineCap = 'round' offContext.lineWidth = 14 offContext.beginPath() offContext.arc( (this.getUIContext().px2vp(display.getDefaultDisplaySync().width) - 2 * 14) / 2.0, 180, 100, (225 - 90) * Math.PI / 180, (135 - 90) * Math.PI / 180 ) offContext.strokeStyle = '#EAF2FF' offContext.stroke() offContext.beginPath() offContext.arc( (this.getUIContext().px2vp(display.getDefaultDisplaySync().width) - 2 * 14) / 2.0, 180, 100, (225 - 90) * (Math.PI / 180), this.radianTest === 0 ? (135 - 90) * (Math.PI / 180) : (135 - 270 * (1 - this.radianTest) - 90) * (Math.PI / 180) ) offContext.strokeStyle = '#337DFF' offContext.stroke() let image = this.offCanvas.transferToImageBitmap() this.context.transferFromImageBitmap(image) // 使用setTimeout模拟帧刷新 setTimeout(() => { this.radianTest = Number(this.radianTest + 0.005) if (this.radianTest > 1) { this.radianTest = 0 } else { this.canvasTest() } }, 10) } build() { List() { ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9], (item: number) => { ListItem() { Row() { Text(item.toString()) } .height(200) } }) ListItem() { Canvas(this.context) .width('100%') .height(300) .onReady(this.canvasTest) .position({ x: 0, y: 0 }) } .onClick(() => { this.canvasTest() }) } .width('100%') .height('100%') .alignListItem(ListItemAlign.Center) } }
问题效果预览:

将Canvas绘制方法修改为在屏绘制。
完整示例参考如下:
import { display } from '@kit.ArkUI'; @ComponentV2 @Entry struct DrawWithScreen { // 动画 @Local radianTest: number = 0; private settings: RenderingContextSettings = new RenderingContextSettings(true); private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private offCanvas: OffscreenCanvas = new OffscreenCanvas(600, 600); canvasTest = (): void => { // 原先的离屏绘制改为在屏绘制 let ctx = this.context; ctx.reset(); ctx.lineCap = 'round'; ctx.lineWidth = 14; ctx.beginPath(); ctx.arc( (this.getUIContext().px2vp(display.getDefaultDisplaySync().width) - 2 * 14) / 2.0, 180, 100, (225 - 90) * Math.PI / 180, (135 - 90) * Math.PI / 180 ); ctx.strokeStyle = '#EAF2FF'; ctx.stroke(); ctx.beginPath(); ctx.arc( (this.getUIContext().px2vp(display.getDefaultDisplaySync().width) - 2 * 14) / 2.0, 180, 100, (225 - 90) * (Math.PI / 180), this.radianTest === 0 ? (135 - 90) * (Math.PI / 180) : (135 - 270 * (1 - this.radianTest) - 90) * (Math.PI / 180), ); ctx.strokeStyle = '#337DFF'; ctx.stroke(); // 使用setTimeout模拟帧刷新 setTimeout(() => { this.radianTest = Number(this.radianTest + 0.05); if (this.radianTest > 1) { this.radianTest = 0; } else { this.canvasTest(); } }, 20); }; build() { List() { ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9], (item: number) => { ListItem() { Row() { Text(item.toString()); } .height(200); }; }); ListItem() { Canvas(this.context) .width('100%') .height(300) .onReady(this.canvasTest) .position({ x: 0, y: 0 }); } .onClick(() => { this.canvasTest(); }); } .width('100%') .height('100%') .alignListItem(ListItemAlign.Center); } }