 深度解析:獲取屏幕信息與屏幕模擬的 API 實(shí)現(xiàn))
Puppeteer Browser.screens() 深度解析獲取屏幕信息與屏幕模擬的 API 實(shí)現(xiàn)【免費(fèi)下載鏈接】puppeteerJavaScript API for Chrome and Firefox項(xiàng)目地址: https://gitcode.com/GitHub_Trending/puppeteer1/puppeteer在自動(dòng)化瀏覽器時(shí)多顯示器布局、設(shè)備像素比、屏幕方向等顯示屬性往往影響頁(yè)面渲染結(jié)果但標(biāo)準(zhǔn) API 并沒(méi)有直接暴露這些信息。本文基于 Puppeteer 官方 API 文檔中的Browser.screens()方法講解如何從Browser實(shí)例獲取完整的屏幕信息對(duì)象列表ScreenInfo[]并結(jié)合源碼說(shuō)明其底層如何通過(guò) CDPEmulation域?qū)崿F(xiàn)、在 BiDi 協(xié)議下的行為差異以及與addScreen/removeScreen構(gòu)成的屏幕模擬能力全貌幫助讀者在實(shí)際測(cè)試中準(zhǔn)確掌握顯示環(huán)境。1.Browser.screens()方法簽名與返回值官方 API 文檔puppeteer.browser.screens對(duì)該方法的定義非常明確Gets a list of screen information objects.class Browser { abstract screens(): PromiseScreenInfo[]; }要點(diǎn)接收方Browser實(shí)例通過(guò)puppeteer.launch()或puppeteer.connect()獲得方法定義在抽象基類 packages/puppeteer-core/src/api/Browser.ts 中聲明為abstract由各協(xié)議實(shí)現(xiàn)CDP / BiDi分別提供具體行為無(wú)參數(shù)調(diào)用時(shí)不需要任何配置返回值PromiseScreenInfo[]即瀏覽器當(dāng)前可見(jiàn)的全部屏幕信息對(duì)象數(shù)組每個(gè)對(duì)象描述一塊物理屏幕的幾何位置、可用區(qū)域、像素密度、色彩深度、方向與主屏/擴(kuò)展屏標(biāo)識(shí)等。最直接的用法示例const puppeteer require(puppeteer); (async () { const browser await puppeteer.launch(); const screens await browser.screens(); for (const screen of screens) { console.log( 屏幕 ${screen.label}${screen.width}x${screen.height} (${screen.left}, ${screen.top}), 主屏: ${screen.isPrimary}DPR: ${screen.devicePixelRatio}, ); } await browser.close(); })();2.ScreenInfo屏幕信息對(duì)象全字段說(shuō)明screens()返回的每個(gè)元素都是 ScreenInfo 接口對(duì)象。該接口在源碼中定義于 packages/puppeteer-core/src/api/Browser.ts官方文檔給出了完整的屬性表Description/Default 列在文檔中留空以下語(yǔ)義結(jié)合接口名與 Web 平臺(tái)通用屏幕概念說(shuō)明屬于對(duì)接口字段的合理對(duì)應(yīng)屬性類型含義leftnumber屏幕左邊緣在虛擬桌面坐標(biāo)系中的 X 坐標(biāo)topnumber屏幕上邊緣在虛擬桌面坐標(biāo)系中的 Y 坐標(biāo)widthnumber屏幕寬度邏輯像素heightnumber屏幕高度邏輯像素availLeftnumber可用區(qū)域工作區(qū)左邊緣坐標(biāo)扣除任務(wù)欄等系統(tǒng)占用后availTopnumber可用區(qū)域上邊緣坐標(biāo)availWidthnumber可用區(qū)域?qū)挾萢vailHeightnumber可用區(qū)域高度devicePixelRationumber設(shè)備像素比即物理像素與 CSS 邏輯像素的比值如 2 表示 Retina 屏colorDepthnumber屏幕色彩位深orientationScreenOrientation屏幕方向包含angle旋轉(zhuǎn)角度與type方向類型字符串兩個(gè)字段定義見(jiàn) packages/puppeteer-core/src/api/Browser.tsisExtendedboolean是否為擴(kuò)展屏非主屏的附加顯示器isInternalboolean是否為內(nèi)置屏幕如筆記本內(nèi)屏isPrimaryboolean是否為主屏labelstring屏幕標(biāo)識(shí)/名稱idstring屏幕唯一標(biāo)識(shí)是后續(xù)調(diào)用removeScreen(screenId)的入?yún)d字段與label字段是屏幕管理操作的關(guān)鍵獲取屏幕列表后可憑id精確移除某塊屏幕見(jiàn)第 5 節(jié)。3. 源碼級(jí)實(shí)現(xiàn)CDP 路徑下的screens()在 CDP 協(xié)議實(shí)現(xiàn)中screens()直接轉(zhuǎn)發(fā)到 DevTools 協(xié)議的Emulation域命令。實(shí)現(xiàn)位于 packages/puppeteer-core/src/cdp/Browser.tsoverride async screens(): PromiseScreenInfo[] { const {screenInfos} await this.#connection.send( Emulation.getScreenInfos, ); return screenInfos; }調(diào)用鏈為browser.screens()→CDPBrowserpackages/puppeteer-core/src/cdp/Browser.ts→ 底層connection.send(Emulation.getScreenInfos)→ Chrome DevTools 協(xié)議返回screenInfos數(shù)組。也就是說(shuō)該 API 本質(zhì)是 ChromeEmulation域中屏幕模擬功能的只讀查詢接口——Chrome 內(nèi)部的屏幕模擬狀態(tài)可被addScreen動(dòng)態(tài)修改的虛擬屏幕集合決定了這里返回的內(nèi)容因此在自動(dòng)化環(huán)境下查詢結(jié)果反映的是被模擬的屏幕環(huán)境而非宿主機(jī)真實(shí)顯示器配置這是使用該 API 時(shí)必須理解的前提。4. BiDi 路徑下的行為差異UnsupportedOperation并非所有瀏覽器/協(xié)議組合都支持屏幕 API。在 WebDriver BiDi 實(shí)現(xiàn)中packages/puppeteer-core/src/bidi/Browser.ts 對(duì)屏幕三件套的實(shí)現(xiàn)是顯式拋錯(cuò)override screens(): PromiseScreenInfo[] { throw new UnsupportedOperation(); } override addScreen(_params: AddScreenParams): PromiseScreenInfo { throw new UnsupportedOperation(); } override removeScreen(_screenId: string): Promisevoid { throw new UnsupportedOperation(); }從源碼結(jié)構(gòu)看BiDi 端尚未映射 Chrome 的Emulation屏幕模擬能力因此當(dāng)Browser實(shí)例的底層協(xié)議為 BiDi 時(shí)調(diào)用screens()會(huì)拋出UnsupportedOperation錯(cuò)誤。工程實(shí)踐建議在跨瀏覽器Chrome Firefox via BiDi腳本中對(duì)屏幕相關(guān)調(diào)用做try/catch或先判斷browser.browserVersion()/協(xié)議類型再執(zhí)行該能力目前應(yīng)以 CDP 連接Chrome/Chromium 系為準(zhǔn)。5. 配套能力addScreen與removeScreen組成完整屏幕模擬閉環(huán)screens()的文檔頁(yè)中雖只描述只讀查詢但在同一Browser抽象類中packages/puppeteer-core/src/api/Browser.ts與之配套的是屏幕的增刪操作abstract screens(): PromiseScreenInfo[]; // Adds a new screen, returns the added ScreenInfo. abstract addScreen(params: AddScreenParams): PromiseScreenInfo; abstract removeScreen(screenId: string): Promisevoid;其中addScreen的參數(shù)接口 AddScreenParams源碼定義見(jiàn) packages/puppeteer-core/src/api/Browser.ts字段如下參數(shù)類型必填說(shuō)明leftnumber是新屏幕左邊緣坐標(biāo)topnumber是新屏幕上邊緣坐標(biāo)widthnumber是寬度heightnumber是高度workAreaInsetsWorkAreaInsets否可用區(qū)域四周的縮進(jìn)top/left/bottom/right對(duì)應(yīng)任務(wù)欄等系統(tǒng) UI 占用devicePixelRationumber否設(shè)備像素比rotationnumber否屏幕旋轉(zhuǎn)colorDepthnumber否色彩位深labelstring否屏幕名稱isInternalboolean否是否標(biāo)記為內(nèi)置屏CDP 實(shí)現(xiàn)packages/puppeteer-core/src/cdp/Browser.ts分別映射到Emulation.addScreen與Emulation.removeScreen命令override async addScreen(params: AddScreenParams): PromiseScreenInfo { const {screenInfo} await this.#connection.send( Emulation.addScreen, params, ); return screenInfo; } override async removeScreen(screenId: string): Promisevoid { return await this.#connection.send(Emulation.removeScreen, {screenId}); }由此形成的典型多屏測(cè)試工作流是// 1. 添加一塊副屏1920x1080位于主屏右側(cè)DPR 2 const secondary await browser.addScreen({ left: 1920, top: 0, width: 1920, height: 1080, devicePixelRatio: 2, label: Test-Secondary, }); // 2. 查詢當(dāng)前全部屏幕確認(rèn)布局 const screens await browser.screens(); // 3. 測(cè)試結(jié)束后按 id 精確清理 await browser.removeScreen(secondary.id);這一添加 → 查詢 → 移除的模式可用于驗(yàn)證依賴window.screen、matchMedia或窗口放置邏輯的頁(yè)面在多顯示器場(chǎng)景下的表現(xiàn)。6. 使用注意與適用前提協(xié)議前提screens()在 CDP 實(shí)現(xiàn)中可用在 BiDi 實(shí)現(xiàn)中會(huì)拋出UnsupportedOperation見(jiàn) packages/puppeteer-core/src/bidi/Browser.ts??鐓f(xié)議腳本必須做防御性處理。返回的是模擬態(tài)屏幕集合CDP 實(shí)現(xiàn)查詢的是Emulation域維護(hù)的屏幕狀態(tài)addScreen修改的也是這一虛擬集合因此結(jié)果反映的是自動(dòng)化環(huán)境下的模擬屏幕而非宿主機(jī)真實(shí)顯示器由 CDP 命令實(shí)現(xiàn)可確認(rèn)該調(diào)用路徑具體返回內(nèi)容以 ChromeEmulation域行為為準(zhǔn)。id與label的用途區(qū)分label用于人類可讀標(biāo)識(shí)id是removeScreen的唯一有效入?yún)⒆詣?dòng)化腳本中應(yīng)保存addScreen返回值中的id以便清理。orientation子結(jié)構(gòu)ScreenOrientation只有anglenumber與typestring兩個(gè)字段見(jiàn) packages/puppeteer-core/src/api/Browser.ts如需更細(xì)的方向枚舉語(yǔ)義應(yīng)結(jié)合被測(cè)頁(yè)面的screen.orientationAPI 交叉驗(yàn)證。相關(guān)文檔可進(jìn)一步參考ScreenInfo 接口、ScreenOrientation、AddScreenParams、Browser.addScreen、Browser.removeScreen。7. 小結(jié)Browser.screens()是一個(gè)零參數(shù)、返回ScreenInfo[]的抽象方法其 CDP 實(shí)現(xiàn)直接調(diào)用 Chrome DevTools 協(xié)議的Emulation.getScreenInfos與addScreenEmulation.addScreen、removeScreenEmulation.removeScreen共同構(gòu)成完整的屏幕模擬查詢/變更能力BiDi 協(xié)議目前對(duì)該能力拋出UnsupportedOperation。掌握ScreenInfo的 16 個(gè)字段尤其是id、isPrimary、devicePixelRatio、orientation與AddScreenParams的可選參數(shù)即可在多顯示器布局、DPR 差異、屏幕方向等顯示相關(guān)測(cè)試場(chǎng)景中構(gòu)造并校驗(yàn)受控的屏幕環(huán)境。【免費(fèi)下載鏈接】puppeteerJavaScript API for Chrome and Firefox項(xiàng)目地址: https://gitcode.com/GitHub_Trending/puppeteer1/puppeteer創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考