1# 请求自绘制内容绘制帧率 2<!--Kit: ArkGraphics 2D--> 3<!--Subsystem: Graphics--> 4<!--Owner: @hudi33--> 5<!--Designer: @hudi33--> 6<!--Tester: @zhaoxiaoguang2--> 7<!--Adviser: @ge-yafang--> 8 9对于基于[XComponent](../ui/napi-xcomponent-guidelines.md)进行Native开发的业务,可以请求独立的绘制帧率进行内容开发,如游戏、自绘制UI框架对接等场景。 10 11## 接口说明 12 13| 函数名称 | 说明 | 14|-----|--------| 15| OH_NativeXComponent_SetExpectedFrameRateRange (OH_NativeXComponent *component, OH_NativeXComponent_ExpectedRateRange *range) |设置帧期望的帧率范围。 16| OH_NativeXComponent_RegisterOnFrameCallback (OH_NativeXComponent *component, OH_NativeXComponent_OnFrameCallback *callback) | 设置每帧回调函数,同时启动每帧回调。 | 17| OH_NativeXComponent_UnRegisterOnFrameCallback (OH_NativeXComponent *component) | 取消注册的每帧回调函数,同时停止调用回调函数。 | 18 19详细的接口说明请参考[OH_NativeXComponent Native XComponent](../reference/apis-arkui/capi-oh-nativexcomponent-native-xcomponent.md)。 20 21## 开发步骤 22 23 > **说明:** 24 > 25 > 本范例是通过Drawing在Native侧实现图形的绘制,并将其呈现在NativeWindow上,具体可参考[使用Drawing实现图形绘制与显示](graphic-drawing-overview.md)。 26 271. 添加开发依赖。 28 29 CMakeLists.txt中添加以下lib。 30 31 ```txt 32 libace_napi.z.so 33 libace_ndk.z.so 34 libnative_window.so 35 libnative_drawing.so 36 ``` 37 38 导入依赖的相关头文件。 39 40 ```c++ 41 #include <ace/xcomponent/native_interface_xcomponent.h> 42 #include "napi/native_api.h" 43 #include <native_drawing/drawing_bitmap.h> 44 #include <native_drawing/drawing_color.h> 45 #include <native_drawing/drawing_canvas.h> 46 #include <native_drawing/drawing_pen.h> 47 #include <native_drawing/drawing_brush.h> 48 #include <native_drawing/drawing_path.h> 49 #include <native_drawing/drawing_text_typography.h> 50 #include <native_window/external_window.h> 51 #include <cmath> 52 #include <algorithm> 53 #include <stdint.h> 54 #include <sys/mman.h> 55 ``` 56 572. 定义ArkTS接口文件XComponentContext.ts,用来对接Native层。 58 ```ts 59 export default interface XComponentContext { 60 register(): void; 61 unregister(): void; 62 }; 63 ``` 64 653. 定义演示页面,包含两个XComponent组件。 66 67 ```ts 68 import XComponentContext from "../interface/XComponentContext"; 69 70 @Entry 71 @Component 72 struct Index { 73 private xComponentContext1: XComponentContext | undefined = undefined; 74 private xComponentContext2: XComponentContext | undefined = undefined; 75 76 build() { 77 Column() { 78 Row() { 79 XComponent({ id: 'xcomponentId_30', type: XComponentType.SURFACE, libraryname: 'entry' }) 80 .onLoad((xComponentContext) => { 81 this.xComponentContext1 = xComponentContext as XComponentContext; 82 }).width('832px') 83 }.height('40%') 84 85 Row() { 86 XComponent({ id: 'xcomponentId_120', type: XComponentType.SURFACE, libraryname: 'entry' }) 87 .onLoad((xComponentContext) => { 88 this.xComponentContext2 = xComponentContext as XComponentContext; 89 }).width('832px') // Multiples of 64 90 }.height('40%') 91 } 92 } 93 } 94 ``` 95 964. Native层配置帧率和注册回调函数。 97 98 ```ts 99 static void TestCallback(OH_NativeXComponent *component, uint64_t timestamp, uint64_t targetTimestamp) // 定义每帧的回调函数 100 { 101 // ... 102 // 获取XComponent的surface大小 103 int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, nativeWindow, &width, &height); 104 if ((xSize == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) && (render != nullptr)) { 105 render->Prepare(); 106 render->Create(); 107 if (id == "xcomponentId_30") { 108 // 30Hz绘制时,每帧移动的距离为16像素 109 render->ConstructPath(16, 16, render->defaultOffsetY); 110 } 111 if (id == "xcomponentId_120") { 112 // 120Hz绘制时,每帧移动的距离为4像素 113 render->ConstructPath(4, 4, render->defaultOffsetY); 114 } 115 // ... 116 } 117 } 118 ``` 119 120 > **说明:** 121 > 122 > - Callback回调函数运行于UI主线程,故涉及UI线程的耗时操作不应运行于回调函数中,以免影响性能。 123 > - 实例在调用OH_NativeXComponent_RegisterOnFrameCallback后,在不需要进行帧率控制时,应进行OH_NativeXComponent_UnregisterOnFrameCallback操作,避免内存泄漏及性能功耗影响。 124 > - API version 18之前,应用调用OH_NativeXComponent_RegisterOnFrameCallback接口设置回调函数,如果没有取消注册,在XComponent实例存在期间,能一直收到期望回调。 125 > - 从API version 18开始,应用调用OH_NativeXComponent_RegisterOnFrameCallback接口设置回调函数,如果没有取消注册,只在XComponent上树期间,能收到期望回调。 126 127 ```ts 128 void SampleXComponent::RegisterOnFrameCallback(OH_NativeXComponent *nativeXComponent) 129 { 130 OH_NativeXComponent_RegisterOnFrameCallback(nativeXComponent, TestCallback); // 注册回调函数,并使能每帧回调 131 } 132 133 napi_value SampleXComponent::NapiRegister(napi_env env, napi_callback_info info) 134 { 135 // ... 136 render->RegisterOnFrameCallback(nativeXComponent); // 在TS层使能注册与使能每帧回调 137 // ... 138 } 139 140 napi_value SampleXComponent::NapiUnregister(napi_env env, napi_callback_info info) 141 { 142 // ... 143 OH_NativeXComponent_UnregisterOnFrameCallback(nativeXComponent); // 在TS层取消注册每帧回调 144 // ... 145 } 146 ``` 147 1485. TS层注册和取消注册每帧回调。 149 150 ```ts 151 Row() { 152 Button('Start') 153 .id('Start') 154 .fontSize(14) 155 .fontWeight(500) 156 .margin({ bottom: 20, right: 6, left: 6 }) 157 .onClick(() => { 158 if (this.xComponentContext1) { 159 this.xComponentContext1.register(); 160 } 161 if (this.xComponentContext2) { 162 this.xComponentContext2.register(); 163 } 164 }) 165 .width('30%') 166 .height(40) 167 .shadow(ShadowStyle.OUTER_DEFAULT_LG) 168 169 Button('Stop') 170 .id('Stop') 171 .fontSize(14) 172 .fontWeight(500) 173 .margin({ bottom: 20, left: 6 }) 174 .onClick(() => { 175 if (this.xComponentContext1) { 176 this.xComponentContext1.unregister(); 177 } 178 if (this.xComponentContext2) { 179 this.xComponentContext2.unregister(); 180 } 181 }) 182 .width('30%') 183 .height(40) 184 .shadow(ShadowStyle.OUTER_DEFAULT_LG) 185 } 186 ``` 187 188<!--RP1--> 189## 相关实例 190 191- [DisplaySync (API14)](https://gitcode.com/openharmony/applications_app_samples/tree/master/code/DocsSample/graphic/DisplaySync) 192<!--RP1End-->