You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据内容调整Phaser 3项目中模态框的高度?

问题:Phaser 3 模态框根据内容动态调整高度

我正在为Phaser 3项目创建模态框场景,当前modal.js代码如下:

class modal extends Phaser.Scene {

    // constructor
    constructor() {
        super("Modal");
    }

    preload() {
        this.load.image("header", "Assets/popUpTop.png");
        this.load.image("x", "Assets/x.png");
    }

    init(data) {
        this.modalName = data.modalName;
    }

    create() {
        // create a white rounded rectangle as modal background
        var bgGrafics = this.make.graphics();
        bgGrafics.fillStyle(0xffffff, 1);
        bgGrafics.fillRoundedRect(0, 0, gameConfig.width / 3, gameConfig.height / 1.7, 51);
        bgGrafics.generateTexture("modalBg", gameConfig.width / 3, gameConfig.height / 1.7);
        this.modalBg = this.add.sprite(gameConfig.width / 2, gameConfig.height / 2, "modalBg");
        
        this.modalBg.setScale(1.05);
        
        this.headerBg = this.add.image(0, 0, "header");
        this.headerBg.setScale((this.modalBg.width * 1.05 / this.headerBg.width), (1 + (0.05 * this.modalBg.height / this.headerBg.height)));
        
        this.closeBtn = new RoundedButton(this, 0, 0, 43, "x", 1.3, () => {this.close()}); // RoundedButton is a custom class that extends Phaser.GameObjects.Container
        this.add.existing(this.closeBtn);

        // help modal
        if(this.modalName === 'help') {
        // add content of help modal 
        }
        // profile modal
        else if(this.modalName === 'profile') {
        // add content of profile modal 
        }
        // confirm spin modal
        else if(this.modalName === 'spin') {
        // add content of confirm modal 
        }
        
        Phaser.Display.Align.In.TopRight(this.closeBtn, this.modalBg);
        Phaser.Display.Align.In.TopCenter( this.headerBg, this.modalBg );
    }

    close() {
        this.scene.stop('Modal');
        this.scene.run('PlayGame');
    }
}

如代码所示,我尝试根据modalName为模态框添加不同内容,但无法找到根据内容调整模态框高度的方法,该如何实现?


解决方案

方法1:预设不同模态框的高度配置

适合内容固定、高度可提前预估的场景,直接为每个模态框定义对应的高度参数:

// 在类外部或内部定义模态框配置
const modalConfigs = {
    help: { height: gameConfig.height / 1.5 }, // 帮助内容较多,高度稍大
    profile: { height: gameConfig.height / 2 }, // 个人信息内容适中
    spin: { height: gameConfig.height / 3 }     // 确认弹窗内容少,高度较小
};

class modal extends Phaser.Scene {
    // ... 其他代码不变
    
    create() {
        // 获取当前模态框的配置,默认使用原固定高度
        const config = modalConfigs[this.modalName] || { height: gameConfig.height / 1.7 };
        
        // 动态生成适配高度的背景
        var bgGrafics = this.make.graphics();
        bgGrafics.fillStyle(0xffffff, 1);
        bgGrafics.fillRoundedRect(0, 0, gameConfig.width / 3, config.height, 51);
        bgGrafics.generateTexture("modalBg", gameConfig.width / 3, config.height);
        this.modalBg = this.add.sprite(gameConfig.width / 2, gameConfig.height / 2, "modalBg");
        
        this.modalBg.setScale(1.05);
        
        // 调整headerBg缩放以适配新的背景高度
        this.headerBg = this.add.image(0, 0, "header");
        this.headerBg.setScale(
            (this.modalBg.width * 1.05 / this.headerBg.width), 
            (1 + (0.05 * this.modalBg.height / this.headerBg.height))
        );
        
        this.closeBtn = new RoundedButton(this, 0, 0, 43, "x", 1.3, () => {this.close()});
        this.add.existing(this.closeBtn);

        // 添加对应模态框内容
        if(this.modalName === 'help') {
            const helpText = this.add.text(0, 0, "这是帮助内容,包含游戏玩法、规则说明...", { fontSize: '16px', color: '#333', wordWrap: { width: gameConfig.width / 3 - 40 } });
            Phaser.Display.Align.In.Center(helpText, this.modalBg);
        }
        else if(this.modalName === 'profile') {
            const avatar = this.add.image(0, 0, 'avatar');
            Phaser.Display.Align.In.TopCenter(avatar, this.modalBg, 0, 50);
            const userName = this.add.text(0, 0, "玩家昵称", { fontSize: '18px', color: '#000' });
            Phaser.Display.Align.In.Center(userName, this.modalBg);
        }
        else if(this.modalName === 'spin') {
            const confirmText = this.add.text(0, 0, "确认消耗金币进行旋转吗?", { fontSize: '16px', color: '#333' });
            Phaser.Display.Align.In.Center(confirmText, this.modalBg);
            const confirmBtn = new RoundedButton(this, 0, 0, 60, "确认", 1, () => { /* 执行旋转逻辑 */ });
            this.add.existing(confirmBtn);
            Phaser.Display.Align.In.BottomCenter(confirmBtn, this.modalBg, 0, 30);
        }
        
        Phaser.Display.Align.In.TopRight(this.closeBtn, this.modalBg);
        Phaser.Display.Align.In.TopCenter( this.headerBg, this.modalBg );
    }
    
    // ... 其他代码不变
}

方法2:自动计算内容高度(更灵活)

适合内容长度不确定的场景,通过容器包裹内容后,动态计算实际高度来生成背景:

class modal extends Phaser.Scene {
    // ... 其他代码不变
    
    create() {
        const modalWidth = gameConfig.width / 3;
        // 创建内容容器,用于统一管理模态框内的所有元素
        const contentContainer = this.add.container(gameConfig.width / 2, gameConfig.height / 2);
        
        // 根据模态框类型添加内容到容器
        if(this.modalName === 'help') {
            const helpText = this.add.text(0, 0, "这是帮助内容,可能包含多行文本,长度不固定...", { fontSize: '16px', color: '#333', wordWrap: { width: modalWidth - 40 } });
            contentContainer.add(helpText);
            // 为内容添加上下边距
            helpText.setPosition(0, 0);
        }
        else if(this.modalName === 'profile') {
            const avatar = this.add.image(0, -50, 'avatar');
            const userName = this.add.text(0, 20, "玩家昵称", { fontSize: '18px', color: '#000' });
            const levelText = this.add.text(0, 50, "等级:10", { fontSize: '14px', color: '#666' });
            contentContainer.add([avatar, userName, levelText]);
        }
        else if(this.modalName === 'spin') {
            const confirmText = this.add.text(0, 0, "确认消耗金币进行旋转吗?", { fontSize: '16px', color: '#333' });
            const confirmBtn = new RoundedButton(this, 0, 40, 60, "确认", 1, () => { /* 执行旋转逻辑 */ });
            contentContainer.add([confirmText, confirmBtn]);
        }
        
        // 获取内容容器的实际高度,加上上下边距
        const contentBounds = contentContainer.getBounds();
        const modalHeight = contentBounds.height + 80; // 80为上下边距
        
        // 生成适配高度的背景
        var bgGrafics = this.make.graphics();
        bgGrafics.fillStyle(0xffffff, 1);
        bgGrafics.fillRoundedRect(0, 0, modalWidth, modalHeight, 51);
        bgGrafics.generateTexture("modalBg", modalWidth, modalHeight);
        this.modalBg = this.add.sprite(gameConfig.width / 2, gameConfig.height / 2, "modalBg");
        this.modalBg.setScale(1.05);
        
        // 调整header和关闭按钮
        this.headerBg = this.add.image(0, 0, "header");
        this.headerBg.setScale(
            (this.modalBg.width * 1.05 / this.headerBg.width), 
            (1 + (0.05 * this.modalBg.height / this.headerBg.height))
        );
        this.closeBtn = new RoundedButton(this, 0, 0, 43, "x", 1.3, () => {this.close()});
        this.add.existing(this.closeBtn);
        
        // 确保内容在背景之上
        contentContainer.setDepth(this.modalBg.depth + 1);
        
        Phaser.Display.Align.In.TopRight(this.closeBtn, this.modalBg);
        Phaser.Display.Align.In.TopCenter( this.headerBg, this.modalBg );
    }
    
    // ... 其他代码不变
}

内容的提问来源于stack exchange,提问作者Faezeh Keshmiri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 01:45:36