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; }; }