1# 模糊 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @CCFFWW--> 5<!--Designer: @yangfan229--> 6<!--Tester: @lxl007--> 7<!--Adviser: @HelloCrease--> 8 9动画效果可以丰富界面的细节,提升UI界面的真实感和品质感。例如,模糊和阴影效果可以让物体看起来更加立体,使得动画更加生动。ArkUI提供了丰富的效果接口,开发者可快速打造出精致、个性化的效果。本章中主要对常用的模糊、阴影和色彩效果等效果接口进行了介绍。 10 11 12模糊可以用来体现界面空间的纵深感,区分前后元素的层级关系。 13 14 15| 接口 | 说明 | 16| ------------------------------------------------------------ | -------------------------------------------- | 17| [backdropBlur](../reference/apis-arkui/arkui-ts/ts-universal-attributes-background.md#backdropblur) | 为当前组件添加背景模糊效果,入参为模糊半径。 | 18| [blur](../reference/apis-arkui/arkui-ts/ts-universal-attributes-image-effect.md#blur) | 为当前组件添加内容模糊效果,入参为模糊半径。 | 19| [backgroundBlurStyle](../reference/apis-arkui/arkui-ts/ts-universal-attributes-background.md#backgroundblurstyle9) | 为当前组件添加背景模糊效果,入参为模糊样式。 | 20| [foregroundBlurStyle](../reference/apis-arkui/arkui-ts/ts-universal-attributes-foreground-blur-style.md#foregroundblurstyle) | 为当前组件添加内容模糊效果,入参为模糊样式。 | 21| [motionBlur](../reference/apis-arkui/arkui-ts/ts-universal-attributes-motionBlur.md#motionblur) | 为当前组件添加由缩放大小或位移变化引起的运动过程中的动态模糊效果,入参为模糊半径和锚点坐标。 | 22 23> **说明:** 24> 25> 以上接口均为实时模糊接口,每帧执行实时渲染,性能负载较大。当模糊内容与模糊半径均无需变动时,推荐采用静态模糊接口[blur](../reference/apis-arkgraphics2d/js-apis-effectKit.md#blur)。最佳实践请参考:[图像模糊动效优化-使用场景](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-fuzzy-scene-performance-optimization#section4945532519)。 26 27## 使用backdropBlur为组件添加背景模糊 28 29 30```ts 31@Entry 32@Component 33struct BlurEffectsExample { 34 build() { 35 Column({ space: 10 }) { 36 Text('backdropBlur') 37 .width('90%') 38 .height('90%') 39 .fontSize(20) 40 .fontColor(Color.White) 41 .textAlign(TextAlign.Center) 42 .backdropBlur(10)// 对背景进行模糊 43 .backgroundImage($r('app.media.share')) 44 .backgroundImageSize({ width: 400, height: 300 }) 45 } 46 .width('100%') 47 .height('50%') 48 .margin({ top: 20 }) 49 } 50} 51``` 52 53 54 55 56 57 58## 使用blur为组件添加内容模糊 59 60 61```ts 62@Entry 63@Component 64struct Index1 { 65 @State radius: number = 0; 66 @State text: string = ''; 67 @State y: string = '手指不在屏幕上'; 68 69 aboutToAppear() { 70 this.text = "按住屏幕上下滑动\n" + "当前手指所在y轴位置 : " + this.y + 71 "\n" + "当前图片模糊程度为 : " + this.radius; 72 } 73 74 build() { 75 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) { 76 Text(this.text) 77 .height(200) 78 .fontSize(20) 79 .fontWeight(FontWeight.Bold) 80 .fontFamily("cursive") 81 .fontStyle(FontStyle.Italic) 82 Image($r("app.media.wall")) 83 .blur(this.radius)// 使用blur接口为照片组件添加内容模糊效果 84 .height('100%') 85 .width("100%") 86 .objectFit(ImageFit.Cover) 87 }.height('100%') 88 .width("100%") 89 .onTouch((event?: TouchEvent) => { 90 if (event) { 91 if (event.type === TouchType.Move) { 92 this.y = Number(event.touches[0].y.toString()).toString(); 93 this.radius = Number(this.y) / 10; // 根据跟手过程中的滑动距离修改模糊半径,配合模糊接口,形成跟手模糊效果 94 } 95 if (event.type === TouchType.Up) { 96 this.radius = 0; 97 this.y = '手指离开屏幕'; 98 } 99 } 100 this.text = "按住屏幕上下滑动\n" + "当前手指所在y轴位置 : " + this.y + 101 "\n" + "当前图片模糊程度为 : " + this.radius; 102 }) 103 } 104} 105``` 106 107 108 109 110 111 112## 使用backgroundBlurStyle为组件添加背景模糊效果 113 114 115```ts 116@Entry 117@Component 118struct BackDropBlurStyleDemo { 119 build() { 120 Grid() { 121 GridItem() { 122 Column() { 123 Column() { 124 Text('原图') 125 .fontSize(20) 126 .fontColor(Color.White) 127 .textAlign(TextAlign.Center) 128 .width('100%') 129 .height('100%') 130 } 131 .height(100) 132 .aspectRatio(1) 133 .borderRadius(10) 134 .backgroundImage($r('app.media.share')) 135 136 Text('原图') 137 .fontSize(12) 138 .fontColor(Color.Black) 139 } 140 .height('100%') 141 .justifyContent(FlexAlign.Start) 142 } 143 .width(200) 144 .height(200) 145 146 GridItem() { 147 Column() { 148 Column() { 149 Text('Thin') 150 .fontSize(20) 151 .fontColor(Color.White) 152 .textAlign(TextAlign.Center) 153 .width('100%') 154 .height('100%') 155 } 156 .height(100) 157 .aspectRatio(1) 158 .borderRadius(10) 159 .backgroundImage($r('app.media.share')) 160 // BlurStyle.Thin: 为组件添加轻薄材质模糊效果 161 // ThemeColorMode.LIGHT: 固定使用浅色模式效果 162 // AdaptiveColor.DEFAULT: 不使用取色模糊,使用默认的颜色作为蒙版颜色 163 // scale: 背景材质模糊效果程度,默认值是1 164 .backgroundBlurStyle(BlurStyle.Thin, { 165 colorMode: ThemeColorMode.LIGHT, 166 adaptiveColor: AdaptiveColor.DEFAULT, 167 scale: 0.1 168 }) 169 170 Text('Thin') 171 .fontSize(12) 172 .fontColor(Color.Black) 173 } 174 .height('100%') 175 .justifyContent(FlexAlign.Start) 176 } 177 .width(200) 178 .height(200) 179 180 GridItem() { 181 Column() { 182 Column() { 183 Text('Regular') 184 .fontSize(20) 185 .fontColor(Color.White) 186 .textAlign(TextAlign.Center) 187 .width('100%') 188 .height('100%') 189 } 190 .height(100) 191 .aspectRatio(1) 192 .borderRadius(10) 193 .backgroundImage($r('app.media.share')) 194 .backgroundBlurStyle(BlurStyle.Regular, { 195 colorMode: ThemeColorMode.LIGHT, 196 adaptiveColor: AdaptiveColor.DEFAULT, 197 scale: 0.1 198 }) 199 200 Text('Regular') 201 .fontSize(12) 202 .fontColor(Color.Black) 203 } 204 .height('100%') 205 .justifyContent(FlexAlign.Start) 206 } 207 .width(200) 208 .height(200) 209 210 GridItem() { 211 Column() { 212 Column() { 213 Text('Thick') 214 .fontSize(20) 215 .fontColor(Color.White) 216 .textAlign(TextAlign.Center) 217 .width('100%') 218 .height('100%') 219 } 220 .height(100) 221 .aspectRatio(1) 222 .borderRadius(10) 223 .backgroundImage($r('app.media.share')) 224 .backgroundBlurStyle(BlurStyle.Thick, { 225 colorMode: ThemeColorMode.LIGHT, 226 adaptiveColor: AdaptiveColor.DEFAULT, 227 scale: 0.1 228 }) 229 230 Text('Thick') 231 .fontSize(12) 232 .fontColor(Color.Black) 233 } 234 .height('100%') 235 .justifyContent(FlexAlign.Start) 236 } 237 .width(200) 238 .height(200) 239 240 GridItem() { 241 Column() { 242 Column() { 243 Text('BACKGROUND_THIN') 244 .fontSize(12) 245 .fontColor(Color.White) 246 .textAlign(TextAlign.Center) 247 .width('100%') 248 .height('100%') 249 } 250 .height(100) 251 .aspectRatio(1) 252 .borderRadius(10) 253 .backgroundImage($r('app.media.share')) 254 .backgroundBlurStyle(BlurStyle.BACKGROUND_THIN, { 255 colorMode: ThemeColorMode.LIGHT, 256 adaptiveColor: AdaptiveColor.DEFAULT, 257 scale: 0.1 258 }) 259 260 Text('BACKGROUND_THIN') 261 .fontSize(12) 262 .fontColor(Color.Black) 263 } 264 .height('100%') 265 .justifyContent(FlexAlign.Start) 266 } 267 .width(200) 268 .height(200) 269 270 GridItem() { 271 Column() { 272 Column() { 273 Text('BACKGROUND_REGULAR') 274 .fontSize(12) 275 .fontColor(Color.White) 276 .textAlign(TextAlign.Center) 277 .width('100%') 278 .height('100%') 279 } 280 .height(100) 281 .aspectRatio(1) 282 .borderRadius(10) 283 .backgroundImage($r('app.media.share')) 284 .backgroundBlurStyle(BlurStyle.BACKGROUND_REGULAR, { 285 colorMode: ThemeColorMode.LIGHT, 286 adaptiveColor: AdaptiveColor.DEFAULT, 287 scale: 0.1 288 }) 289 290 Text('BACKGROUND_REGULAR') 291 .fontSize(12) 292 .fontColor(Color.Black) 293 } 294 .height('100%') 295 .justifyContent(FlexAlign.Start) 296 } 297 .width(200) 298 .height(200) 299 300 GridItem() { 301 Column() { 302 Column() { 303 Text('BACKGROUND_THICK') 304 .fontSize(12) 305 .fontColor(Color.White) 306 .textAlign(TextAlign.Center) 307 .width('100%') 308 .height('100%') 309 } 310 .height(100) 311 .aspectRatio(1) 312 .borderRadius(10) 313 .backgroundImage($r('app.media.share')) 314 .backgroundBlurStyle(BlurStyle.BACKGROUND_THICK, { 315 colorMode: ThemeColorMode.LIGHT, 316 adaptiveColor: AdaptiveColor.DEFAULT, 317 scale: 0.1 318 }) 319 320 Text('BACKGROUND_THICK') 321 .fontSize(12) 322 .fontColor(Color.Black) 323 } 324 .height('100%') 325 .justifyContent(FlexAlign.Start) 326 } 327 .width(200) 328 .height(200) 329 330 GridItem() { 331 Column() { 332 Column() { 333 Text('BACKGROUND_ULTRA_THICK') 334 .fontSize(12) 335 .fontColor(Color.White) 336 .textAlign(TextAlign.Center) 337 .width('100%') 338 .height('100%') 339 } 340 .height(100) 341 .aspectRatio(1) 342 .borderRadius(10) 343 .backgroundImage($r('app.media.share')) 344 .backgroundBlurStyle(BlurStyle.BACKGROUND_ULTRA_THICK, { 345 colorMode: ThemeColorMode.LIGHT, 346 adaptiveColor: AdaptiveColor.DEFAULT, 347 scale: 0.1 348 }) 349 350 Text('BACKGROUND_ULTRA_THICK') 351 .fontSize(12) 352 .fontColor(Color.Black) 353 } 354 .height('100%') 355 .justifyContent(FlexAlign.Start) 356 } 357 .width(200) 358 .height(200) 359 } 360 .columnsTemplate('1fr 1fr') 361 .rowsTemplate('1fr 1fr 1fr 1fr') 362 .width('100%') 363 .height('100%') 364 .margin({ top: 40 }) 365 } 366} 367``` 368 369 370 371 372 373 374 375## 使用foregroundBlurStyle为组件添加内容模糊效果 376 377 378```ts 379@Entry 380@Component 381struct ForegroundBlurStyleDemo { 382 build() { 383 Grid() { 384 GridItem() { 385 Column() { 386 Column() { 387 Text('原图') 388 .fontSize(20) 389 .fontColor(Color.White) 390 .textAlign(TextAlign.Center) 391 .width('100%') 392 .height('100%') 393 } 394 .height(100) 395 .aspectRatio(1) 396 .borderRadius(10) 397 .backgroundImage($r('app.media.share')) 398 399 Text('原图') 400 .fontSize(12) 401 .fontColor(Color.Black) 402 } 403 .height('100%') 404 .justifyContent(FlexAlign.Start) 405 } 406 .width(200) 407 .height(200) 408 409 GridItem() { 410 Column() { 411 Column() { 412 Text('Thin') 413 .fontSize(20) 414 .fontColor(Color.White) 415 .textAlign(TextAlign.Center) 416 .width('100%') 417 .height('100%') 418 } 419 .height(100) 420 .aspectRatio(1) 421 .borderRadius(10) 422 .backgroundImage($r('app.media.share')) 423 // BlurStyle.Thin: 为组件添加轻薄材质模糊效果 424 // ThemeColorMode.LIGHT: 固定使用浅色模式效果 425 // AdaptiveColor.DEFAULT: 不使用取色模糊,使用默认的颜色作为蒙版颜色 426 // scale: 背景材质模糊效果程度,默认值是1 427 .foregroundBlurStyle(BlurStyle.Thin, { 428 colorMode: ThemeColorMode.LIGHT, 429 adaptiveColor: AdaptiveColor.DEFAULT, 430 scale: 0.1 431 }) 432 433 Text('Thin') 434 .fontSize(12) 435 .fontColor(Color.Black) 436 } 437 .height('100%') 438 .justifyContent(FlexAlign.Start) 439 } 440 .width(200) 441 .height(200) 442 443 GridItem() { 444 Column() { 445 Column() { 446 Text('Regular') 447 .fontSize(20) 448 .fontColor(Color.White) 449 .textAlign(TextAlign.Center) 450 .width('100%') 451 .height('100%') 452 } 453 .height(100) 454 .aspectRatio(1) 455 .borderRadius(10) 456 .backgroundImage($r('app.media.share')) 457 .foregroundBlurStyle(BlurStyle.Regular, { 458 colorMode: ThemeColorMode.LIGHT, 459 adaptiveColor: AdaptiveColor.DEFAULT, 460 scale: 0.1 461 }) 462 463 Text('Regular') 464 .fontSize(12) 465 .fontColor(Color.Black) 466 } 467 .height('100%') 468 .justifyContent(FlexAlign.Start) 469 } 470 .width(200) 471 .height(200) 472 473 GridItem() { 474 Column() { 475 Column() { 476 Text('Thick') 477 .fontSize(20) 478 .fontColor(Color.White) 479 .textAlign(TextAlign.Center) 480 .width('100%') 481 .height('100%') 482 } 483 .height(100) 484 .aspectRatio(1) 485 .borderRadius(10) 486 .backgroundImage($r('app.media.share')) 487 .foregroundBlurStyle(BlurStyle.Thick, { 488 colorMode: ThemeColorMode.LIGHT, 489 adaptiveColor: AdaptiveColor.DEFAULT, 490 scale: 0.1 491 }) 492 493 Text('Thick') 494 .fontSize(12) 495 .fontColor(Color.Black) 496 } 497 .height('100%') 498 .justifyContent(FlexAlign.Start) 499 } 500 .width(200) 501 .height(200) 502 503 GridItem() { 504 Column() { 505 Column() { 506 Text('BACKGROUND_THIN') 507 .fontSize(12) 508 .fontColor(Color.White) 509 .textAlign(TextAlign.Center) 510 .width('100%') 511 .height('100%') 512 } 513 .height(100) 514 .aspectRatio(1) 515 .borderRadius(10) 516 .backgroundImage($r('app.media.share')) 517 .foregroundBlurStyle(BlurStyle.BACKGROUND_THIN, { 518 colorMode: ThemeColorMode.LIGHT, 519 adaptiveColor: AdaptiveColor.DEFAULT, 520 scale: 0.1 521 }) 522 523 Text('BACKGROUND_THIN') 524 .fontSize(12) 525 .fontColor(Color.Black) 526 } 527 .height('100%') 528 .justifyContent(FlexAlign.Start) 529 } 530 .width(200) 531 .height(200) 532 533 GridItem() { 534 Column() { 535 Column() { 536 Text('BACKGROUND_REGULAR') 537 .fontSize(12) 538 .fontColor(Color.White) 539 .textAlign(TextAlign.Center) 540 .width('100%') 541 .height('100%') 542 } 543 .height(100) 544 .aspectRatio(1) 545 .borderRadius(10) 546 .backgroundImage($r('app.media.share')) 547 .foregroundBlurStyle(BlurStyle.BACKGROUND_REGULAR, { 548 colorMode: ThemeColorMode.LIGHT, 549 adaptiveColor: AdaptiveColor.DEFAULT, 550 scale: 0.1 551 }) 552 553 Text('BACKGROUND_REGULAR') 554 .fontSize(12) 555 .fontColor(Color.Black) 556 } 557 .height('100%') 558 .justifyContent(FlexAlign.Start) 559 } 560 .width(200) 561 .height(200) 562 563 GridItem() { 564 Column() { 565 Column() { 566 Text('BACKGROUND_THICK') 567 .fontSize(12) 568 .fontColor(Color.White) 569 .textAlign(TextAlign.Center) 570 .width('100%') 571 .height('100%') 572 } 573 .height(100) 574 .aspectRatio(1) 575 .borderRadius(10) 576 .backgroundImage($r('app.media.share')) 577 .foregroundBlurStyle(BlurStyle.BACKGROUND_THICK, { 578 colorMode: ThemeColorMode.LIGHT, 579 adaptiveColor: AdaptiveColor.DEFAULT, 580 scale: 0.1 581 }) 582 583 Text('BACKGROUND_THICK') 584 .fontSize(12) 585 .fontColor(Color.Black) 586 } 587 .height('100%') 588 .justifyContent(FlexAlign.Start) 589 } 590 .width(200) 591 .height(200) 592 593 GridItem() { 594 Column() { 595 Column() { 596 Text('BACKGROUND_ULTRA_THICK') 597 .fontSize(12) 598 .fontColor(Color.White) 599 .textAlign(TextAlign.Center) 600 .width('100%') 601 .height('100%') 602 } 603 .height(100) 604 .aspectRatio(1) 605 .borderRadius(10) 606 .backgroundImage($r('app.media.share')) 607 .foregroundBlurStyle(BlurStyle.BACKGROUND_ULTRA_THICK, { 608 colorMode: ThemeColorMode.LIGHT, 609 adaptiveColor: AdaptiveColor.DEFAULT, 610 scale: 0.1 611 }) 612 613 Text('BACKGROUND_ULTRA_THICK') 614 .fontSize(12) 615 .fontColor(Color.Black) 616 } 617 .height('100%') 618 .justifyContent(FlexAlign.Start) 619 } 620 .width(200) 621 .height(200) 622 } 623 .columnsTemplate('1fr 1fr') 624 .rowsTemplate('1fr 1fr 1fr 1fr') 625 .width('100%') 626 .height('100%') 627 .margin({ top: 40 }) 628 } 629} 630``` 631 632 633 634 635 636 637## 使用motionBlur为组件添加运动模糊效果 638 639```ts 640import { curves } from '@kit.ArkUI'; 641 642@Entry 643@Component 644struct motionBlurTest { 645 @State widthSize: number = 400; 646 @State heightSize: number = 320; 647 @State flag: boolean = true; 648 @State radius: number = 0; 649 @State x: number = 0; 650 @State y: number = 0; 651 652 build() { 653 Column() { 654 Column() { 655 Image($r('app.media.testImg')) 656 .width(this.widthSize) 657 .height(this.heightSize) 658 .onClick(() => { 659 this.radius = 5; 660 this.x = 0.5; 661 this.y = 0.5; 662 if (this.flag) { 663 this.widthSize = 100; 664 this.heightSize = 80; 665 } else { 666 this.widthSize = 400; 667 this.heightSize = 320; 668 } 669 this.flag = !this.flag; 670 }) 671 .animation({ 672 duration: 2000, 673 curve: curves.springCurve(10, 1, 228, 30), 674 onFinish: () => { 675 this.radius = 0; 676 } 677 }) 678 .motionBlur({ radius: this.radius, anchor: { x: this.x, y: this.y } }) 679 } 680 }.width('100%').margin({ top: 5 }) 681 } 682} 683``` 684 685