BackgroundAdapter.ts 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. import { _decorator, Component, Node, screen, UITransform, Vec3, view } from 'cc';
  2. const { ccclass } = _decorator;
  3. /**
  4. * 使背景图始终覆盖父容器的高度,并保持图片原有宽高比。
  5. *
  6. * 建议挂在 Canvas(或全屏容器)下的背景节点上,且不要同时给该节点配置纵向拉伸 Widget。
  7. */
  8. @ccclass('BackgroundAdapter')
  9. export class BackgroundAdapter extends Component {
  10. private readonly baseScale = new Vec3();
  11. private uiTransform: UITransform | null = null;
  12. private targetTransform: UITransform | null = null;
  13. private sourceHeight = 0;
  14. private lastTargetHeight = -1;
  15. protected onLoad(): void {
  16. this.uiTransform = this.getComponent(UITransform);
  17. this.targetTransform = this.node.parent?.getComponent(UITransform) ?? null;
  18. if (!this.uiTransform) {
  19. console.warn('[BackgroundAdapter] 缺少 UITransform,无法进行背景适配。', this.node.name);
  20. return;
  21. }
  22. this.baseScale.set(this.node.scale);
  23. this.sourceHeight = this.uiTransform.height * Math.abs(this.baseScale.y);
  24. }
  25. protected onEnable(): void {
  26. screen.on('window-resize', this.adaptHeight, this);
  27. this.targetTransform?.node.on(Node.EventType.SIZE_CHANGED, this.adaptHeight, this);
  28. this.scheduleOnce(this.adaptHeight);
  29. }
  30. protected onDisable(): void {
  31. screen.off('window-resize', this.adaptHeight, this);
  32. this.targetTransform?.node.off(Node.EventType.SIZE_CHANGED, this.adaptHeight, this);
  33. }
  34. private readonly adaptHeight = (): void => {
  35. if (!this.uiTransform || this.sourceHeight <= 0) return;
  36. const targetHeight = this.targetTransform?.height ?? view.getVisibleSize().height;
  37. if (targetHeight <= 0 || Math.abs(targetHeight - this.lastTargetHeight) < 0.01) return;
  38. // 背景只放大不缩小:较矮屏幕裁剪上下区域,较高屏幕补足可见区域。
  39. const scale = Math.max(1, targetHeight / this.sourceHeight);
  40. this.node.setScale(
  41. this.baseScale.x * scale,
  42. this.baseScale.y * scale,
  43. this.baseScale.z * scale,
  44. );
  45. this.lastTargetHeight = targetHeight;
  46. };
  47. }