1# 请求自绘制内容绘制帧率 2 3对于基于[XComponent](../ui/napi-xcomponent-guidelines.md)进行Native开发的业务,可以请求独立的绘制帧率进行内容开发,如游戏、自绘制UI框架对接等场景。 4 5## 接口说明 6 7| 函数名称 | 说明 | 8|-----|--------| 9| OH_NativeXComponent_SetExpectedFrameRateRange (OH_NativeXComponent *component, OH_NativeXComponent_ExpectedRateRange *range) |设置帧期望的帧率范围。 10| OH_NativeXComponent_RegisterOnFrameCallback (OH_NativeXComponent *component, OH_NativeXComponent_OnFrameCallback *callback) | 设置每帧回调函数,同时启动每帧回调。 | 11| OH_NativeXComponent_UnRegisterOnFrameCallback (OH_NativeXComponent *component) | 取消注册的每帧回调函数,同时停止调用回调函数。 | 12 13## 开发步骤 14 15 > **说明:** 16 > 17 > 本范例是通过Drawing在Native侧实现图形的绘制,并将其呈现在NativeWindow上,具体可参考[使用Drawing实现图形绘制与显示](graphic-drawing-overview.md)。 18 191. 定义ArkTS接口文件XComponentContext.ts,用来对接Native层。 20 ```ts 21 export default interface XComponentContext { 22 register(): void; 23 unregister(): void; 24 }; 25 ``` 26 272. 定义演示页面,包含两个XComponent组件。 28 29 ```ts 30 import XComponentContext from "../interface/XComponentContext"; 31 32 @Entry 33 @Component 34 struct Index { 35 private xComponentContext1: XComponentContext | undefined = undefined; 36 private xComponentContext2: XComponentContext | undefined = undefined; 37 38 build() { 39 Column() { 40 Row() { 41 XComponent({ id: 'xcomponentId_30', type: 'surface', libraryname: 'entry' }) 42 .onLoad((xComponentContext) => { 43 this.xComponentContext1 = xComponentContext as XComponentContext; 44 }).width('832px') 45 }.height('40%') 46 47 Row() { 48 XComponent({ id: 'xcomponentId_120', type: 'surface', libraryname: 'entry' }) 49 .onLoad((xComponentContext) => { 50 this.xComponentContext2 = xComponentContext as XComponentContext; 51 }).width('832px') // Multiples of 64 52 }.height('40%') 53 } 54 } 55 } 56 ``` 57 583. Native层配置帧率和注册回调函数。 59 60 ```ts 61 static void TestCallback(OH_NativeXComponent *component, uint64_t timestamp, uint64_t targetTimestamp) // 定义每帧的回调函数 62 { 63 // ... 64 // 获取XComponent的surface大小 65 int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, nativeWindow, &width, &height); 66 if ((xSize == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) && (render != nullptr)) { 67 render->Prepare(); 68 render->Create(); 69 if (id == "xcomponentId_30") { 70 // 30Hz绘制时,每帧移动的距离为16像素 71 render->ConstructPath(16, 16, render->defaultOffsetY); 72 } 73 if (id == "xcomponentId_120") { 74 // 120Hz绘制时,每帧移动的距离为4像素 75 render->ConstructPath(4, 4, render->defaultOffsetY); 76 } 77 // ... 78 } 79 } 80 ``` 81 82 > **说明:** 83 > 84 > - Callback回调函数运行于UI主线程,故涉及UI线程的耗时操作不应运行于回调函数中,以免影响性能。 85 > - 实例在调用OH_NativeXComponent_RegisterOnFrameCallback后,在不需要进行帧率控制时,应进行OH_NativeXComponent_UnregisterOnFrameCallback操作,避免内存泄漏及性能功耗影响。 86 > - API version 18之前,应用调用OH_NativeXComponent_RegisterOnFrameCallback接口设置回调函数,如果没有取消注册,在XComponent实例存在期间,能一直收到期望回调。 87 > - 从API version 18开始,应用调用OH_NativeXComponent_RegisterOnFrameCallback接口设置回调函数,如果没有取消注册,只在XComponent上树期间,能收到期望回调。 88 89 ```ts 90 void SampleXComponent::RegisterOnFrameCallback(OH_NativeXComponent *nativeXComponent) 91 { 92 OH_NativeXComponent_RegisterOnFrameCallback(nativeXComponent, TestCallback); // 注册回调函数,并使能每帧回调 93 } 94 95 napi_value SampleXComponent::NapiRegister(napi_env env, napi_callback_info info) 96 { 97 // ... 98 render->RegisterOnFrameCallback(nativeXComponent); // 在TS层使能注册与使能每帧回调 99 // ... 100 } 101 102 napi_value SampleXComponent::NapiUnregister(napi_env env, napi_callback_info info) 103 { 104 // ... 105 OH_NativeXComponent_UnregisterOnFrameCallback(nativeXComponent); // 在TS层取消注册每帧回调 106 // ... 107 } 108 ``` 109 1104. TS层注册和取消注册每帧回调。 111 112 ```ts 113 Row() { 114 Button('Start') 115 .id('Start') 116 .fontSize(14) 117 .fontWeight(500) 118 .margin({ bottom: 20, right: 6, left: 6 }) 119 .onClick(() => { 120 if (this.xComponentContext1) { 121 this.xComponentContext1.register(); 122 } 123 if (this.xComponentContext2) { 124 this.xComponentContext2.register(); 125 } 126 }) 127 .width('30%') 128 .height(40) 129 .shadow(ShadowStyle.OUTER_DEFAULT_LG) 130 131 Button('Stop') 132 .id('Stop') 133 .fontSize(14) 134 .fontWeight(500) 135 .margin({ bottom: 20, left: 6 }) 136 .onClick(() => { 137 if (this.xComponentContext1) { 138 this.xComponentContext1.unregister(); 139 } 140 if (this.xComponentContext2) { 141 this.xComponentContext2.unregister(); 142 } 143 }) 144 .width('30%') 145 .height(40) 146 .shadow(ShadowStyle.OUTER_DEFAULT_LG) 147 } 148 ``` 149 150## 相关实例 151 152针对可变帧率的开发,有以下相关实例可供参考: 153 154- [DisplaySync分级管控(ArkTS)(API11)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Graphics/DisplaySync)