首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >OPPO 快游戏在浏览器复现运行(五)之竖屏适配

OPPO 快游戏在浏览器复现运行(五)之竖屏适配

作者头像
LiesAuer
发布2026-08-10 09:09:03
发布2026-08-10 09:09:03
1050
举报
文章被收录于专栏:LiesAuer's BlogLiesAuer's Blog

大部分竖屏快游戏都很少有兼顾宽屏分辨率的情况,Laya 游戏会有一个自动横屏的机制,会将整个画面横向显示,而像 CC 游戏,基本都是 UI 位置大小严重失调,要么导致某些区域点不了,要么导致 UI 飞出屏幕外,根本看不到点不着。针对这两个常见的游戏框架做了一个竖屏适配修复,可以用修复代码在启动阶段将游戏画面按设定好的比例强制自适配调整。推荐比例:9:1610:169:20

代码语言:javascript
复制
fixPortrait() {
    if (window.cc) {
        _fixCCPortrait();
    } else if (Laya) {
        _fixLayaPortrait();
    }
}

_fixLayaPortrait() {
    if (!Laya) return;

    const bestRatio = window.sdkConfig?.bestRatio;
    let maxRatio = 9 / 20;

    if (bestRatio) {
        const [w, h] = bestRatio.split(':').map(Number);
        maxRatio = w / h;
    }

    Laya._stage = Laya.stage;

    Object.defineProperty(Laya, 'stage', {
        set: function(val) {
            Laya._stage = val;

            const setScreenSize = val.setScreenSize;

            let _rawWidth = 0;
            let _rawHeight = 0;

            val.setScreenSize = function(width, height) {
                const pixelRatio = Laya.Browser.pixelRatio;
                let rawWidth = width / pixelRatio;
                let rawHeight = height / pixelRatio;

                if (rawWidth / rawHeight > maxRatio) {
                    rawWidth = rawHeight * maxRatio;

                    width = rawWidth * pixelRatio;
                    height = rawHeight * pixelRatio;
                }

                _rawWidth = rawWidth;
                _rawHeight = rawHeight;

                setScreenSize.apply(val, [width, height]);
            };

            const identity = val._canvasTransform.identity;

            val._canvasTransform.identity = function(...args) {
                identity.apply(val._canvasTransform, args);
                val._canvasTransform.tx = (Laya.Browser.clientWidth - _rawWidth) / 2;

                return val._canvasTransform;
            };

            const scale = val._canvasTransform.scale;

            val._canvasTransform.scale = function(...args) {
                scale.apply(val._canvasTransform, args);
                val._canvasTransform.tx = (Laya.Browser.clientWidth - _rawWidth) / 2;

                return val._canvasTransform;
            };
        },
        get: function() {
            return Laya._stage;
        },
        configurable: true,
        enumerable: true,
    });
}

_fixCCPortrait() {
    const cc = window.cc;
    const view = cc?.view;
    const canvas = cc?.game?.canvas;

    if (!view || !canvas) return;

    const bestRatio = window.sdkConfig?.bestRatio;
    let maxRatio = 9 / 20;

    if (bestRatio) {
        const [w, h] = bestRatio.split(':').map(Number);
        maxRatio = w / h;
    }

    const getViewport = (width?: number, height?: number) => {
        const viewportWidth = width || window.innerWidth || document.documentElement.clientWidth;
        const viewportHeight = height || window.innerHeight || document.documentElement.clientHeight;

        return {
            width: Math.max(1, viewportWidth),
            height: Math.max(1, viewportHeight),
        };
    };

    const applyViewportStyle = (viewportWidth?: number, viewportHeight?: number) => {
        const viewport = getViewport(viewportWidth, viewportHeight);
        const width = Math.min(viewport.width, viewport.height * maxRatio);
        const height = viewport.height;

        if (view._frameSize) {
            view._frameSize.width = width;
            view._frameSize.height = height;
        }

        if (canvas.style) {
            canvas.style.position = "fixed";
            canvas.style.left = `${Math.round((viewport.width - width) / 2)}px`;
            canvas.style.top = "0px";
            canvas.style.width = `${Math.round(width)}px`;
            canvas.style.height = `${Math.round(height)}px`;
            canvas.style.margin = "0px";
        }
    };

    const initFrameSize = view._initFrameSize;
    view._initFrameSize = function() {
        initFrameSize.apply(this, arguments);
        applyViewportStyle();
    };

    const setDesignResolutionSize = view.setDesignResolutionSize;
    view.setDesignResolutionSize = function() {
        const result = setDesignResolutionSize.apply(this, arguments);
        applyViewportStyle();
        return result;
    };

    const setCanvasSize = view.setCanvasSize;
    if (typeof setCanvasSize === "function") {
        view.setCanvasSize = function(width: number, height: number) {
            const viewport = getViewport(width, height);
            const result = setCanvasSize.call(this, viewport.width, viewport.height);
            applyViewportStyle(viewport.width, viewport.height);
            return result;
        };
    }

    const refreshResolution = () => {
        applyViewportStyle();

        const resolution = view._originalDesignResolutionSize || view._designResolutionSize;
        if (!resolution || resolution.width <= 0 || resolution.height <= 0) return;

        view.setDesignResolutionSize(
            resolution.width,
            resolution.height,
            view._resolutionPolicy,
        );
    };

    window.addEventListener("resize", refreshResolution);
    window.addEventListener("orientationchange", refreshResolution);
    this.onWindowResize(refreshResolution);

    if (typeof view._resizeEvent === "function") {
        view._resizeEvent(true);
    } else {
        refreshResolution();
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档