1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15import Matrix4 from '@ohos.matrix4' 16import { NavigationBar } from '../../../common/components/navigationBar' 17 18@Entry 19@Component 20struct TransformExample { 21 @State rotate: any = { x: 200, y: 200, z: 275 } 22 @State translate: any = { x: 200, y: 200, z: 200 } 23 @State transform: any = { x: 200, y: 200, z: 200 } 24 @State scale: any = { x: 1, y: 1, z: 1 } 25 @State rotateCenter: any = { X: 150, Y: 150 } 26 @State scaleCenter: any = { X: 150, Y: 150 } 27 @State angle: number = 360 28 @State index: number = 0 29 private controller: TabsController = new TabsController() 30 private init() { 31 this.rotate = { x: 200, y: 200, z: 275 } 32 this.transform = { x: 200, y: 200, z: 200 } 33 this.translate = { x: 200, y: 200, z: 200 } 34 this.scale = { x: 1, y: 1, z: 1 } 35 this.rotateCenter = { X: 150, Y: 150 } 36 this.scaleCenter = { X: 150, Y: 150 } 37 this.angle = 360 38 } 39 40 build() { 41 Column() { 42 NavigationBar({ title: '图形变换' }) 43 Column() { 44 Scroll() { 45 Column() { 46 Column() { 47 Row() 48 .rotate({ 49 x: this.rotate.x - 200, 50 y: this.rotate.y - 200, 51 z: this.rotate.z - 200, 52 centerX: `${this.rotateCenter.X - 100}%`, 53 centerY: `${this.rotateCenter.Y - 100}%`, 54 angle: this.angle - 360 55 }) 56 57 .translate({ 58 x: this.translate.x - 200, 59 y: this.translate.y - 200, 60 z: this.translate.z - 200 61 }) 62 63 .scale({ 64 x: this.scale.x, 65 y: this.scale.y, 66 z: this.scale.z, 67 centerX: `${this.scaleCenter.X - 100}%`, 68 centerY: `${this.scaleCenter.Y - 100}%` 69 }) 70 71 .transform(Matrix4.identity) 72 .translate({ 73 x: this.transform.x - 200, 74 y: this.transform.y - 200, 75 z: this.transform.z - 200 76 }) 77 .gesture( 78 PanGesture() 79 .onActionUpdate((event: GestureEvent) => { 80 this.translate.x = event.offsetX + 200 81 this.translate.y = event.offsetY + 200 82 }) 83 ) 84 .width(150) 85 .height(150) 86 .zIndex(999) 87 .backgroundColor('red') 88 } 89 .width('100%') 90 .height('100%') 91 .alignItems(HorizontalAlign.Center) 92 .justifyContent(FlexAlign.Start) 93 .gesture( 94 RotationGesture() 95 .onActionUpdate((event: GestureEvent) => { 96 this.angle = event.angle + 360 97 }) 98 ) 99 } 100 .width('100%') 101 .height('100%') 102 .backgroundColor('#FFB6C1') 103 .zIndex(999) 104 .gesture( 105 PinchGesture() 106 .onActionUpdate((event: GestureEvent) => { 107 this.scale.x = event.scale 108 this.scale.y = event.scale 109 this.scale.z = event.scale 110 }) 111 ) 112 } 113 } 114 .height('30%') 115 .width('100%') 116 .padding(18) 117 .backgroundColor('#FFFFFF') 118 119 Column() { 120 Tabs({ barPosition: BarPosition.Start, index: this.index, controller: this.controller }) { 121 TabContent() { 122 Column() { 123 Column() { 124 Row({ space: FlexAlign.SpaceBetween }) { 125 Text('X') 126 .fontWeight(FontWeight.Medium) 127 .fontColor('#182431') 128 .opacity(0.5) 129 .fontSize('16fp') 130 131 Blank() 132 133 Text(`${(this.rotate.x - 200).toFixed(0)}`) 134 .fontWeight(FontWeight.Regular) 135 .fontColor('#000000') 136 .fontSize('16fp') 137 } 138 139 Slider({ 140 value: this.rotate.x, 141 min: 0, 142 max: 400, 143 step: 1, 144 style: SliderStyle.OutSet 145 }) 146 .blockColor('#FFFFFF') 147 .trackColor('#182431') 148 .selectedColor('#007DFF') 149 .width('100%') 150 .showSteps(true) 151 .showTips(false) 152 .onChange((value: number) => { 153 this.rotate.x = value 154 }) 155 } 156 .width('100%') 157 .justifyContent(FlexAlign.Center) 158 .padding({ left: '3%', right: '3%' }) 159 .borderRadius(24) 160 .backgroundColor('#FFFFFF') 161 .margin(8) 162 163 Column() { 164 Row({ space: FlexAlign.SpaceBetween }) { 165 Text('Y') 166 .fontWeight(FontWeight.Medium) 167 .fontColor('#182431') 168 .opacity(0.5) 169 .fontSize('16fp') 170 171 Blank() 172 173 Text(`${(this.rotate.y - 200).toFixed(0)}`) 174 .fontWeight(FontWeight.Regular) 175 .fontColor('#000000') 176 .fontSize('16fp') 177 } 178 179 Slider({ 180 value: this.rotate.y, 181 min: 0, 182 max: 400, 183 step: 1, 184 style: SliderStyle.OutSet 185 }) 186 .blockColor('#FFFFFF') 187 .trackColor('#182431') 188 .selectedColor('#007DFF') 189 .width('100%') 190 .showSteps(true) 191 .showTips(false) 192 .onChange((value: number) => { 193 this.rotate.y = value 194 }) 195 } 196 .width('100%') 197 .justifyContent(FlexAlign.Center) 198 .padding({ left: '3%', right: '3%' }) 199 .borderRadius(24) 200 .backgroundColor('#FFFFFF') 201 .margin({ top: 8 }) 202 203 Column() { 204 Row({ space: FlexAlign.SpaceBetween }) { 205 Text('Z') 206 .fontWeight(FontWeight.Medium) 207 .fontColor('#182431') 208 .opacity(0.5) 209 .fontSize('16fp') 210 211 Blank() 212 213 Text(`${(this.rotate.z - 200).toFixed(0)}`) 214 .fontWeight(FontWeight.Regular) 215 .fontColor('#000000') 216 .fontSize('16fp') 217 } 218 219 Slider({ 220 value: this.rotate.z, 221 min: 0, 222 max: 400, 223 step: 1, 224 style: SliderStyle.OutSet 225 }) 226 .blockColor('#FFFFFF') 227 .trackColor('#182431') 228 .selectedColor('#007DFF') 229 .width('100%') 230 .showSteps(true) 231 .showTips(false) 232 .onChange((value: number) => { 233 this.rotate.z = value 234 }) 235 } 236 .justifyContent(FlexAlign.Center) 237 .width('100%') 238 .padding({ left: '3%', right: '3%' }) 239 .borderRadius(24) 240 .backgroundColor('#FFFFFF') 241 .margin({ top: 8 }) 242 243 Column() { 244 Row({ space: FlexAlign.SpaceBetween }) { 245 Text('angle') 246 .fontWeight(FontWeight.Medium) 247 .fontColor('#182431') 248 .opacity(0.5) 249 .fontSize('16fp') 250 251 Blank() 252 253 Text(`${(this.angle - 360).toFixed(0)}`) 254 .fontWeight(FontWeight.Regular) 255 .fontColor('#000000') 256 .fontSize('16fp') 257 } 258 259 Slider({ 260 value: this.angle, 261 min: 0, 262 max: 720, 263 step: 1, 264 style: SliderStyle.OutSet 265 }) 266 .blockColor('#FFFFFF') 267 .trackColor('#182431') 268 .selectedColor('#007DFF') 269 .width('100%') 270 .showSteps(true) 271 .showTips(false) 272 .onChange((value: number) => { 273 this.angle = value 274 }) 275 } 276 .justifyContent(FlexAlign.Center) 277 .width('100%') 278 .padding({ left: '3%', right: '3%' }) 279 .borderRadius(24) 280 .backgroundColor('#FFFFFF') 281 .margin({ top: 8 }) 282 283 Column() { 284 Row({ space: FlexAlign.SpaceBetween }) { 285 Text('centerX') 286 .fontWeight(FontWeight.Medium) 287 .fontColor('#182431') 288 .opacity(0.5) 289 .fontSize('16fp') 290 291 Blank() 292 293 Text('' + (this.rotateCenter.X - 100).toFixed(0) + '%') 294 .fontWeight(FontWeight.Regular) 295 .fontColor('#000000') 296 .fontSize('16fp') 297 } 298 .justifyContent(FlexAlign.Center) 299 300 Slider({ 301 value: this.rotateCenter.X, 302 min: 0, 303 max: 200, 304 step: 1, 305 style: SliderStyle.OutSet 306 }) 307 .blockColor('#FFFFFF') 308 .trackColor('#182431') 309 .selectedColor('#007DFF') 310 .width('100%') 311 .showSteps(true) 312 .showTips(false) 313 .onChange((value: number) => { 314 this.rotateCenter.X = value 315 }) 316 } 317 .width('100%') 318 .padding({ left: '3%', right: '3%', top: 12, bottom: 12 }) 319 .borderRadius(24) 320 .backgroundColor('#FFFFFF') 321 .margin({ top: 8 }) 322 323 Column() { 324 Row({ space: FlexAlign.SpaceBetween }) { 325 Text('centerY') 326 .fontWeight(FontWeight.Medium) 327 .fontColor('#182431') 328 .opacity(0.5) 329 .fontSize('16fp') 330 331 Blank() 332 333 Text('' + (this.rotateCenter.Y - 100).toFixed(0) + '%') 334 .fontWeight(FontWeight.Regular) 335 .fontColor('#000000') 336 .fontSize('16fp') 337 } 338 339 Slider({ 340 value: this.rotateCenter.Y, 341 min: 0, 342 max: 200, 343 step: 1, 344 style: SliderStyle.OutSet 345 }) 346 .blockColor('#FFFFFF') 347 .trackColor('#182431') 348 .selectedColor('#007DFF') 349 .width('100%') 350 .showSteps(true) 351 .showTips(false) 352 .onChange((value: number) => { 353 this.rotateCenter.Y = value 354 }) 355 } 356 .justifyContent(FlexAlign.Center) 357 .width('100%') 358 .padding({ left: '3%', right: '3%' }) 359 .borderRadius(24) 360 .backgroundColor('#FFFFFF') 361 .margin({ top: 8 }) 362 } 363 }.tabBar('rotate') 364 365 TabContent() { 366 Column() { 367 Column() { 368 Row({ space: FlexAlign.SpaceBetween }) { 369 Text('X') 370 .fontWeight(FontWeight.Medium) 371 .fontColor('#182431') 372 .opacity(0.5) 373 .fontSize('16fp') 374 375 Blank() 376 377 Text('' + (this.translate.x - 200).toFixed(0)) 378 .fontSize('16fp') 379 .fontWeight(FontWeight.Medium) 380 } 381 382 Slider({ 383 value: this.translate.x, 384 min: 0, 385 max: 400, 386 step: 0.1, 387 style: SliderStyle.OutSet 388 }) 389 .blockColor('#FFFFFF') 390 .trackColor('#182431') 391 .selectedColor('#007DFF') 392 .width('100%') 393 .showSteps(true) 394 .showTips(false) 395 .onChange((value: number) => { 396 this.translate.x = value 397 }) 398 } 399 .width('100%') 400 .padding({ left: '3%', right: '3%', top: 12, bottom: 12 }) 401 .borderRadius(24) 402 .backgroundColor('#FFFFFF') 403 .margin(8) 404 405 Column() { 406 Row({ space: FlexAlign.SpaceBetween }) { 407 Text('Y') 408 .fontWeight(FontWeight.Medium) 409 .fontColor('#182431') 410 .opacity(0.5) 411 .fontSize('16fp') 412 413 Blank() 414 415 Text('' + (this.translate.y - 200).toFixed(0)) 416 .fontSize('16fp') 417 .fontWeight(FontWeight.Medium) 418 } 419 420 Slider({ 421 value: this.translate.y, 422 min: 0, 423 max: 400, 424 step: 1, 425 style: SliderStyle.OutSet 426 }) 427 .blockColor('#FFFFFF') 428 .trackColor('#182431') 429 .selectedColor('#007DFF') 430 .width('100%') 431 .showSteps(true) 432 .showTips(false) 433 .onChange((value: number) => { 434 this.translate.y = value 435 }) 436 } 437 .width('100%') 438 .padding({ left: '3%', right: '3%', top: 12, bottom: 12 }) 439 .borderRadius(24) 440 .backgroundColor('#FFFFFF') 441 .margin(8) 442 443 Column() { 444 Row({ space: FlexAlign.SpaceBetween }) { 445 Text('Z') 446 .fontWeight(FontWeight.Medium) 447 .fontColor('#182431') 448 .opacity(0.5) 449 .fontSize('16fp') 450 451 Blank() 452 453 Text('' + (this.translate.z - 200).toFixed(0)) 454 .fontSize('16fp') 455 .fontWeight(FontWeight.Medium) 456 } 457 458 Slider({ 459 value: this.translate.z, 460 min: 0, 461 max: 400, 462 step: 1, 463 style: SliderStyle.OutSet 464 }) 465 .blockColor('#FFFFFF') 466 .trackColor('#182431') 467 .selectedColor('#007DFF') 468 .width('100%') 469 .showSteps(true) 470 .showTips(false) 471 .onChange((value: number) => { 472 this.translate.z = value 473 }) 474 } 475 .width('100%') 476 .padding({ left: '3%', right: '3%', top: 12, bottom: 12 }) 477 .borderRadius(24) 478 .backgroundColor('#FFFFFF') 479 .margin(8) 480 } 481 }.tabBar('translate') 482 483 TabContent() { 484 Column() { 485 Row({ space: FlexAlign.SpaceBetween }) { 486 Text('X') 487 .fontWeight(FontWeight.Medium) 488 .fontColor('#182431') 489 .opacity(0.5) 490 .fontSize('16fp') 491 492 Blank() 493 494 Column() { 495 Counter() { 496 Text(this.scale.x.toFixed(1).toString()).fontSize(16) 497 } 498 .height(24) 499 .onInc(() => { 500 this.scale.x < 5 ? this.scale.x += 0.1 : this.scale.x 501 502 }) 503 .onDec(() => { 504 this.scale.x > 0.1 ? this.scale.x -= 0.1 : this.scale.x 505 }) 506 } 507 } 508 .alignItems(VerticalAlign.Center) 509 .width('100%') 510 .padding({ left: '3%', right: '3%', top: 12, bottom: 12 }) 511 .borderRadius(24) 512 .backgroundColor('#FFFFFF') 513 .margin(8) 514 515 Row({ space: FlexAlign.SpaceBetween }) { 516 Text('Y') 517 .fontWeight(FontWeight.Medium) 518 .fontColor('#182431') 519 .opacity(0.5) 520 .fontSize('16fp') 521 522 Blank() 523 524 Column() { 525 Counter() { 526 Text(this.scale.y.toFixed(1).toString()).fontSize(16) 527 } 528 .height(24) 529 .onInc(() => { 530 this.scale.y < 5 ? this.scale.y += 0.1 : this.scale.y 531 532 }) 533 .onDec(() => { 534 this.scale.y > 0.1 ? this.scale.y -= 0.1 : this.scale.y 535 }) 536 } 537 } 538 .alignItems(VerticalAlign.Center) 539 .width('100%') 540 .padding({ left: '3%', right: '3%', top: 12, bottom: 12 }) 541 .borderRadius(24) 542 .backgroundColor('#FFFFFF') 543 .margin(8) 544 545 Row({ space: FlexAlign.SpaceBetween }) { 546 Text('Z') 547 .fontWeight(FontWeight.Medium) 548 .fontColor('#182431') 549 .opacity(0.5) 550 .fontSize('16fp') 551 552 Blank() 553 554 Column() { 555 Counter() { 556 Text(this.scale.z.toFixed(1).toString()).fontSize(16) 557 } 558 .height(24) 559 .onInc(() => { 560 this.scale.z < 5 ? this.scale.z += 0.1 : this.scale.z 561 562 }) 563 .onDec(() => { 564 this.scale.z > 0.1 ? this.scale.z -= 0.1 : this.scale.z 565 }) 566 } 567 } 568 .alignItems(VerticalAlign.Center) 569 .width('100%') 570 .padding({ left: '3%', right: '3%', top: 12, bottom: 12 }) 571 .borderRadius(24) 572 .backgroundColor('#FFFFFF') 573 .margin(8) 574 575 Column() { 576 Row({ space: FlexAlign.SpaceBetween }) { 577 Text('centerX') 578 .fontWeight(FontWeight.Medium) 579 .fontColor('#182431') 580 .opacity(0.5) 581 .fontSize('16fp') 582 583 Blank() 584 585 Text('' + (this.scaleCenter.X - 100).toFixed(0) + '%') 586 .fontSize('16fp') 587 .fontWeight(FontWeight.Medium) 588 } 589 590 Slider({ 591 value: this.scaleCenter.X, 592 min: 0, 593 max: 200, 594 step: 1, 595 style: SliderStyle.OutSet 596 }) 597 .blockColor('#FFFFFF') 598 .trackColor('#182431') 599 .selectedColor('#007DFF') 600 .width('100%') 601 .showSteps(true) 602 .showTips(false) 603 .onChange((value: number) => { 604 this.scaleCenter.X = value 605 }) 606 } 607 .width('100%') 608 .padding({ left: '3%', right: '3%', top: 12, bottom: 12 }) 609 .borderRadius(24) 610 .backgroundColor('#FFFFFF') 611 .margin(8) 612 613 Column() { 614 Row({ space: FlexAlign.SpaceBetween }) { 615 Text('centerY') 616 .fontWeight(FontWeight.Medium) 617 .fontColor('#182431') 618 .opacity(0.5) 619 .fontSize('16fp') 620 621 Blank() 622 623 Text('' + (this.scaleCenter.Y - 100).toFixed(0) + '%') 624 .fontSize('16fp') 625 .fontWeight(FontWeight.Medium) 626 } 627 628 Slider({ 629 value: this.scaleCenter.Y, 630 min: 0, 631 max: 200, 632 step: 1, 633 style: SliderStyle.OutSet 634 }) 635 .blockColor('#FFFFFF') 636 .trackColor('#182431') 637 .selectedColor('#007DFF') 638 .width('100%') 639 .showSteps(true) 640 .showTips(false) 641 .onChange((value: number) => { 642 this.scaleCenter.Y = value 643 }) 644 } 645 .width('100%') 646 .padding({ left: '3%', right: '3%', top: 12, bottom: 12 }) 647 .borderRadius(24) 648 .backgroundColor('#FFFFFF') 649 .margin(8) 650 } 651 }.tabBar('scale') 652 653 TabContent() { 654 Column() { 655 Column() { 656 Row({ space: FlexAlign.SpaceBetween }) { 657 Text('X:') 658 .fontWeight(FontWeight.Medium) 659 .fontColor('#182431') 660 .opacity(0.5) 661 .fontSize('16fp') 662 663 Blank() 664 665 Text('' + (this.transform.x - 200).toFixed(0)) 666 .fontSize('16fp') 667 .fontWeight(FontWeight.Medium) 668 } 669 670 Slider({ 671 value: this.transform.x, 672 min: 0, 673 max: 400, 674 step: 1, 675 style: SliderStyle.OutSet 676 }) 677 .blockColor('#FFFFFF') 678 .trackColor('#182431') 679 .selectedColor('#007DFF') 680 .width('100%') 681 .showSteps(true) 682 .showTips(false) 683 .onChange((value: number) => { 684 this.transform.x = value 685 }) 686 } 687 .width('100%') 688 .padding({ left: '3%', right: '3%', top: 12, bottom: 12 }) 689 .borderRadius(24) 690 .backgroundColor('#FFFFFF') 691 .margin(8) 692 693 Column() { 694 Row({ space: FlexAlign.SpaceBetween }) { 695 Text('Y') 696 .fontWeight(FontWeight.Medium) 697 .fontColor('#182431') 698 .opacity(0.5) 699 .fontSize('16fp') 700 701 Blank() 702 703 Text('' + (this.transform.y - 200).toFixed(0)) 704 .fontSize('16fp') 705 .fontWeight(FontWeight.Medium) 706 } 707 708 Slider({ 709 value: this.transform.y, 710 min: 0, 711 max: 400, 712 step: 1, 713 style: SliderStyle.OutSet 714 }) 715 .blockColor('#FFFFFF') 716 .trackColor('#182431') 717 .selectedColor('#007DFF') 718 .width('100%') 719 .showSteps(true) 720 .showTips(false) 721 .onChange((value: number) => { 722 this.transform.y = value 723 }) 724 } 725 .width('100%') 726 .padding({ left: '3%', right: '3%', top: 12, bottom: 12 }) 727 .borderRadius(24) 728 .backgroundColor('#FFFFFF') 729 .margin(8) 730 731 Column() { 732 Row({ space: FlexAlign.SpaceBetween }) { 733 Text('Z') 734 .fontWeight(FontWeight.Medium) 735 .fontColor('#182431') 736 .opacity(0.5) 737 .fontSize('16fp') 738 739 Blank() 740 741 Text('' + (this.transform.z - 200).toFixed(0)) 742 .fontSize('16fp') 743 .fontWeight(FontWeight.Medium) 744 } 745 746 Slider({ 747 value: this.transform.z, 748 min: 0, 749 max: 400, 750 step: 1, 751 style: SliderStyle.OutSet 752 }) 753 .blockColor('#FFFFFF') 754 .trackColor('#182431') 755 .selectedColor('#007DFF') 756 .width('100%') 757 .showSteps(true) 758 .showTips(false) 759 .onChange((value: number) => { 760 this.transform.z = value 761 }) 762 } 763 .width('100%') 764 .padding({ left: '3%', right: '3%', top: 12, bottom: 12 }) 765 .borderRadius(24) 766 .backgroundColor('#FFFFFF') 767 .margin(8) 768 } 769 }.tabBar('transform') 770 } 771 .vertical(false) 772 .scrollable(true) 773 .barMode(BarMode.Fixed) 774 .barWidth(360) 775 .animationDuration(400) 776 .width('100%') 777 .backgroundColor(0xF5F5F5) 778 .onChange((index: number) => { 779 this.init() 780 }) 781 } 782 .width('100%') 783 .height('65%') 784 .margin({ top: 10 }) 785 } 786 .height('100%') 787 .backgroundColor('#F1F3F5') 788 .padding({ left: '3%', right: '3%', bottom: 10 }) 789 } 790 791 pageTransition() { 792 PageTransitionEnter({ duration: 370, curve: Curve.Friction }) 793 .slide(SlideEffect.Bottom) 794 .opacity(0.0) 795 796 PageTransitionExit({ duration: 370, curve: Curve.Friction }) 797 .slide(SlideEffect.Bottom) 798 .opacity(0.0) 799 } 800}