1# 请求UI绘制帧率
2
3如果开发者需要以独立的帧率绘制更新操作UI界面时,可以通过DisplaySync来实现。应用中绘制内容的帧率可以使用DisplaySync实例来控制,具体请查阅[@ohos.graphics.displaySync(可变帧率)](../reference/apis-arkgraphics2d/js-apis-graphics-displaySync.md)。
4
5## 开发步骤
6
7此处以不同帧率改变文件组件字体大小为例,来模拟不同UI绘制帧率的效果。
8
91. 导入模块。
10
11   ```ts
12   import { displaySync } from '@kit.ArkGraphics2D';
13   ```
14
152. 定义和构建DisplaySync对象。
16
17   ```ts
18   @Entry
19   @Component
20   struct Index {
21     // 定义两个DisplaySync变量,未初始化
22     private backDisplaySyncSlow: displaySync.DisplaySync | undefined = undefined;
23     private backDisplaySyncFast: displaySync.DisplaySync | undefined = undefined;
24   }
25   ```
26
273. 定义两个文本组件。
28
29   ```ts
30   @State drawFirstSize: number = 25;
31   @State drawSecondSize: number = 25;
32   @Builder doSomeRenderFirst() {
33    Text('30')
34      .fontSize(this.drawFirstSize)
35   }
36
37   @Builder doSomeRenderSecond() {
38    Text('60')
39      .fontSize(this.drawSecondSize)
40   }
41   ```
42
434. 通过DisplaySync实例设置帧率和注册订阅函数。
44
45   > **说明:**
46   >
47   > 订阅函数运行于UI主线程,故涉及UI线程的耗时操作不应运行于订阅函数中,以免影响性能。
48
49   ```ts
50   CreateDisplaySyncSlow() {
51       let range : ExpectedFrameRateRange = { // 创建和配置帧率参数
52         expected: 30, // 设置期望绘制帧率为30hz
53         min: 0, // 配置帧率范围
54         max: 120 // 配置帧率范围
55       };
56
57       let draw30 = (intervalInfo: displaySync.IntervalInfo) => { // 订阅回调函数,字体大小在25到150之间变化
58         if (this.isBigger_30) {
59           this.drawFirstSize += 1;
60           if (this.drawFirstSize > 150) {
61             this.isBigger_30 = false;
62           }
63         } else {
64           this.drawFirstSize -= 1;
65           if (this.drawFirstSize < 25) {
66             this.isBigger_30 = true;
67           }
68         }
69       };
70
71       this.backDisplaySyncSlow = displaySync.create(); // 创建DisplaySync实例
72       this.backDisplaySyncSlow.setExpectedFrameRateRange(range); // 设置帧率
73       this.backDisplaySyncSlow.on("frame", draw30); // 订阅frame事件和注册订阅函数
74   }
75   ```
76
775. 开始每帧回调。
78
79   ```ts
80   Button('Start')
81     .id('CustomDrawStart')
82     .fontSize(14)
83     .fontWeight(500)
84     .margin({ bottom: 10, left: 5 })
85     .fontColor(Color.White)
86     .onClick((): void => {
87         if (this.backDisplaySyncSlow == undefined) {
88           this.CreateDisplaySyncSlow();
89         }
90         if (this.backDisplaySyncFast == undefined) {
91           this.CreateDisplaySyncFast();
92         }
93         if (this.backDisplaySyncSlow) {
94           this.backDisplaySyncSlow.start();
95         }
96         if (this.backDisplaySyncFast) {
97           this.backDisplaySyncFast.start();
98         }
99       })
100       .width('20%')
101       .height(40)
102       .shadow(ShadowStyle.OUTER_DEFAULT_LG)
103   ```
104
105   > **说明:**
106   >
107   > 创建的DisplaySync实例在start使能后需要aboutToDisappear函数中进行stop操作并置空,避免内存泄漏问题。
108   ```ts
109   aboutToDisappear() {
110     if (this.backDisplaySyncSlow) {
111       this.backDisplaySyncSlow.stop();
112       this.backDisplaySyncSlow = undefined;
113     }
114     if (this.backDisplaySyncFast) {
115       this.backDisplaySyncFast.stop();
116       this.backDisplaySyncFast = undefined;
117     }
118   }
119   ```
120
1216. 结束每帧回调。
122
123   ```ts
124   Button('Stop')
125     .id('CustomDrawStop')
126     .fontSize(14)
127     .fontWeight(500)
128     .margin({ bottom: 10, left: 5 })
129     .fontColor(Color.White)
130     .onClick((): void => {
131       if (this.backDisplaySyncSlow) {
132           this.backDisplaySyncSlow.stop();
133       }
134       if (this.backDisplaySyncFast) {
135           this.backDisplaySyncFast.stop();
136       }
137     })
138     .width('20%')
139     .height(40)
140     .shadow(ShadowStyle.OUTER_DEFAULT_LG)
141   ```
142
143## 完整示例
144```ts
145import { displaySync } from '@kit.ArkGraphics2D';
146
147@Entry
148@Component
149struct Index {
150  @State drawFirstSize: number = 25;
151  @State drawSecondSize: number = 25;
152  private backDisplaySyncSlow: displaySync.DisplaySync | undefined = undefined;
153  private backDisplaySyncFast: displaySync.DisplaySync | undefined = undefined;
154  private isBigger_30:boolean = true;
155  private isBigger_60:boolean = true;
156
157  @Builder doSomeRenderFirst() {
158    Text('30')
159      .fontSize(this.drawFirstSize)
160  }
161
162  @Builder doSomeRenderSecond() {
163    Text('60')
164      .fontSize(this.drawSecondSize)
165  }
166
167  CreateDisplaySyncSlow() {
168    // 定义期望绘制帧率
169    let range : ExpectedFrameRateRange = {
170      expected: 30,
171      min: 0,
172      max: 120
173    };
174
175    let draw30 = (intervalInfo: displaySync.IntervalInfo) => {
176      if (this.isBigger_30) {
177        this.drawFirstSize += 1;
178        if (this.drawFirstSize > 150) {
179          this.isBigger_30 = false;
180        }
181      } else {
182        this.drawFirstSize -= 1;
183        if (this.drawFirstSize < 25) {
184          this.isBigger_30 = true;
185        }
186      }
187    };
188
189    this.backDisplaySyncSlow = displaySync.create(); // 创建DisplaySync实例
190    this.backDisplaySyncSlow.setExpectedFrameRateRange(range); // 设置帧率
191    this.backDisplaySyncSlow.on("frame", draw30); // 订阅frame事件和注册订阅函数
192  }
193
194  CreateDisplaySyncFast() {
195    // 定义期望绘制帧率
196    let range : ExpectedFrameRateRange = {
197      expected: 60,
198      min: 0,
199      max: 120
200    };
201
202    let draw60 = (intervalInfo: displaySync.IntervalInfo) => {
203      if (this.isBigger_60) {
204        this.drawSecondSize += 1;
205        if (this.drawSecondSize > 150) {
206          this.isBigger_60 = false;
207        }
208      } else {
209        this.drawSecondSize -= 1;
210        if (this.drawSecondSize < 25) {
211          this.isBigger_60 = true;
212        }
213      }
214
215    };
216
217    this.backDisplaySyncFast= displaySync.create(); // 创建DisplaySync实例
218    this.backDisplaySyncFast.setExpectedFrameRateRange(range); // 设置帧率
219    this.backDisplaySyncFast.on("frame", draw60); // 订阅frame事件和注册订阅函数
220  }
221
222  aboutToDisappear() {
223    if (this.backDisplaySyncSlow) {
224      this.backDisplaySyncSlow.stop(); // DisplaySync失能关闭
225      this.backDisplaySyncSlow = undefined; // 实例置空
226    }
227    if (this.backDisplaySyncFast) {
228      this.backDisplaySyncFast.stop(); // DisplaySync失能关闭
229      this.backDisplaySyncFast = undefined; // 实例置空
230    }
231  }
232
233  build() {
234    Column() {
235      Row() {
236        this.doSomeRenderFirst();
237      }
238      .height('40%')
239
240      Row() {
241        this.doSomeRenderSecond();
242      }
243      .height('40%')
244
245      Row() {
246        Button('Start')
247          .id('CustomDrawStart')
248          .fontSize(14)
249          .fontWeight(500)
250          .margin({ bottom: 10, left: 5 })
251          .fontColor(Color.White)
252          .onClick((): void => {
253            if (this.backDisplaySyncSlow == undefined) {
254              this.CreateDisplaySyncSlow();
255            }
256            if (this.backDisplaySyncFast == undefined) {
257              this.CreateDisplaySyncFast();
258            }
259            if (this.backDisplaySyncSlow) {
260              this.backDisplaySyncSlow.start(); // DisplaySync使能开启
261            }
262            if (this.backDisplaySyncFast) {
263              this.backDisplaySyncFast.start(); // DisplaySync使能开启
264            }
265          })
266          .width('20%')
267          .height(40)
268          .shadow(ShadowStyle.OUTER_DEFAULT_LG)
269
270        Button('Stop')
271          .id('CustomDrawStop')
272          .fontSize(14)
273          .fontWeight(500)
274          .margin({ bottom: 10, left: 5 })
275          .fontColor(Color.White)
276          .onClick((): void => {
277            if (this.backDisplaySyncSlow) {
278              this.backDisplaySyncSlow.stop(); // DisplaySync失能关闭
279            }
280            if (this.backDisplaySyncFast) {
281              this.backDisplaySyncFast.stop(); // DisplaySync失能关闭
282            }
283          })
284          .width('20%')
285          .height(40)
286          .shadow(ShadowStyle.OUTER_DEFAULT_LG)
287      }
288      .width('100%')
289      .justifyContent(FlexAlign.Center)
290      .shadow(ShadowStyle.OUTER_DEFAULT_SM)
291      .alignItems(VerticalAlign.Bottom)
292      .layoutWeight(1)
293    }
294  }
295}
296```
297
298## 相关实例
299
300针对可变帧率的开发,有以下相关实例可供参考:
301
302- [DisplaySync分级管控(ArkTS)(API11)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Graphics/DisplaySync)