| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- import { _decorator, Component, Node, screen, UITransform, Vec3, view } from 'cc';
- const { ccclass } = _decorator;
- /**
- * 使背景图始终覆盖父容器的高度,并保持图片原有宽高比。
- *
- * 建议挂在 Canvas(或全屏容器)下的背景节点上,且不要同时给该节点配置纵向拉伸 Widget。
- */
- @ccclass('BackgroundAdapter')
- export class BackgroundAdapter extends Component {
- private readonly baseScale = new Vec3();
- private uiTransform: UITransform | null = null;
- private targetTransform: UITransform | null = null;
- private sourceHeight = 0;
- private lastTargetHeight = -1;
- protected onLoad(): void {
- this.uiTransform = this.getComponent(UITransform);
- this.targetTransform = this.node.parent?.getComponent(UITransform) ?? null;
- if (!this.uiTransform) {
- console.warn('[BackgroundAdapter] 缺少 UITransform,无法进行背景适配。', this.node.name);
- return;
- }
- this.baseScale.set(this.node.scale);
- this.sourceHeight = this.uiTransform.height * Math.abs(this.baseScale.y);
- }
- protected onEnable(): void {
- screen.on('window-resize', this.adaptHeight, this);
- this.targetTransform?.node.on(Node.EventType.SIZE_CHANGED, this.adaptHeight, this);
- this.scheduleOnce(this.adaptHeight);
- }
- protected onDisable(): void {
- screen.off('window-resize', this.adaptHeight, this);
- this.targetTransform?.node.off(Node.EventType.SIZE_CHANGED, this.adaptHeight, this);
- }
- private readonly adaptHeight = (): void => {
- if (!this.uiTransform || this.sourceHeight <= 0) return;
- const targetHeight = this.targetTransform?.height ?? view.getVisibleSize().height;
- if (targetHeight <= 0 || Math.abs(targetHeight - this.lastTargetHeight) < 0.01) return;
- // 背景只放大不缩小:较矮屏幕裁剪上下区域,较高屏幕补足可见区域。
- const scale = Math.max(1, targetHeight / this.sourceHeight);
- this.node.setScale(
- this.baseScale.x * scale,
- this.baseScale.y * scale,
- this.baseScale.z * scale,
- );
- this.lastTargetHeight = targetHeight;
- };
- }
|