技術(shù)解析:從圖層疊加到實(shí)時(shí)合成)
第一次看到“綿綿很好_overlay”這個(gè)項(xiàng)目名時(shí)我的第一反應(yīng)是這應(yīng)該又是一個(gè)隨手練手的小項(xiàng)目。名字像是一句碎碎念但“overlay”這個(gè)關(guān)鍵詞把主題說得很清楚——疊加層。再配合最近“overlay相機(jī)”這個(gè)熱詞你會(huì)發(fā)現(xiàn)這類東西其實(shí)指向同一件事把文字、貼紙、濾鏡、水印這些圖層實(shí)時(shí)地疊到相機(jī)畫面或照片上。聽起來很簡單。真動(dòng)手做過的人會(huì)明白“把一個(gè)圖層蓋上去”這句話有多天真。圖層疊上去之后可能導(dǎo)致預(yù)覽錯(cuò)位、畫面旋轉(zhuǎn)、透明區(qū)域變黑、預(yù)覽卡頓、內(nèi)存暴漲甚至相機(jī)生命周期一亂整個(gè)畫面直接黑屏。Overlay 真正難的地方從來不是素材好不好看而是這一整套圖層的坐標(biāo)、透明、渲染時(shí)機(jī)、性能開銷和生命周期管理。這篇文章我想借“overlay 相機(jī)”這個(gè)場景把 overlay 從概念到落地拆開講清楚。核心判斷是overlay 表面上是“疊圖”本質(zhì)上是一套圖層管理與實(shí)時(shí)合成流程。能不能把一個(gè) overlay 項(xiàng)目從能跑的 demo 做成能長期使用、能維護(hù)、能擴(kuò)展的工具取決于你對(duì)這套流程的理解程度。1. 先搞清楚 overlay 到底在解決哪種“疊”1.1 三種被混為一談的 overlayOverlay 這個(gè)詞在不同語境里差別很大很多人一開始混著用結(jié)果調(diào)試時(shí)找錯(cuò)方向。第一種是前端和 UI 里的 overlay。它指的是頁面層級(jí)上的浮層比如彈窗、遮罩、引導(dǎo)蒙層。它解決的是“交互元素如何壓在其他內(nèi)容上面”的問題核心是 z-index、層級(jí)樹和事件穿透。這類 overlay 和相機(jī) overlay 雖然都叫“疊”技術(shù)棧完全不是一回事。第二種是圖像和視頻合成里的 overlay。比如給一張照片加水印、加字幕、加貼紙或者給視頻疊加 logo。它解決的是“兩個(gè)或多個(gè)圖像如何按像素混合成一個(gè)畫面”的問題核心是 alpha 通道、混合模式和合成順序。這類 overlay 不需要實(shí)時(shí)可以離線慢慢算出錯(cuò)也容易重來。第三種是相機(jī)實(shí)時(shí) overlay。它把第二類的合成能力放到實(shí)時(shí)預(yù)覽流里要求每一幀都能在幾十毫秒內(nèi)完成合成同時(shí)還要處理相機(jī)輸出的旋轉(zhuǎn)、鏡像、裁剪以及 overlay 圖層的坐標(biāo)隨設(shè)備方向變化。這才是“overlay 相機(jī)”這類項(xiàng)目真正在做的。三種 overlay 的差異可以簡單對(duì)比一下類型核心問題關(guān)鍵機(jī)制典型場景難度UI overlay層級(jí)和交互z-index、事件穿透彈窗、引導(dǎo)層低圖像合成 overlay像素混合alpha、混合模式水印、貼紙、字幕中相機(jī)實(shí)時(shí) overlay每幀實(shí)時(shí)合成坐標(biāo)系、性能、生命周期相機(jī)特效、動(dòng)態(tài)貼紙高1.2 為什么相機(jī) overlay 比普通 UI 疊層難UI overlay 和相機(jī) overlay 最根本的差別是“靜態(tài)層級(jí)”和“實(shí)時(shí)合成”的差別。UI overlay 只需要畫一次或者只在交互發(fā)生時(shí)重畫。它的坐標(biāo)系是固定的左上角是原點(diǎn)屏幕多寬就多寬。你只要保證層級(jí)正確它就不會(huì)出大問題。相機(jī) overlay 有兩個(gè)額外變量。第一個(gè)是時(shí)間每一幀相機(jī)畫面都在變overlay 必須跟上這個(gè)節(jié)奏合成速度跟不上就會(huì)卡頓、掉幀。第二個(gè)是坐標(biāo)系相機(jī)的預(yù)覽畫面輸出到屏幕時(shí)會(huì)經(jīng)過旋轉(zhuǎn)、鏡像、裁剪同一個(gè)物理點(diǎn)在屏幕里和傳感器原始畫面里坐標(biāo)是不對(duì)應(yīng)的。如果你直接拿屏幕坐標(biāo)往紋理坐標(biāo)上套貼紙會(huì)偏到離譜的位置。很多人第一次做 overlay 相機(jī)遇到貼紙和畫面對(duì)不上第一反應(yīng)是調(diào)“偏移量”。調(diào)來調(diào)去發(fā)現(xiàn)不同機(jī)型、不同方向又壞了。這不是參數(shù)問題是坐標(biāo)系沒有統(tǒng)一。這里可以先建立第一個(gè)判斷任何 overlay 相機(jī)項(xiàng)目第一步先把坐標(biāo)系理清楚再談素材和特效。坐標(biāo)系亂了后面所有圖層都會(huì)跟著亂。2. 從“貼一張 PNG”到理解圖層合成2.1 透明不是“沒有顏色”是“第四通道”新手最容易誤解的一個(gè)點(diǎn)認(rèn)為透明 PNG 就是把背景“摳掉”了疊加的時(shí)候背景自然就不見了。實(shí)際上透明信息靠的是 alpha 通道。一張 RGBA 圖片每個(gè)像素由 R、G、B、A 四個(gè)值組成。Alpha 決定這個(gè)像素的不透明度。疊加時(shí)合成器會(huì)按照 alpha 值把前景和背景混合起來。在非預(yù)乘 alpha 的常見表示里src-over 模式的合成公式大致是output.RGB source.RGB * source.A destination.RGB * (1 - source.A)這個(gè)公式看著簡單但很多程序上的 bug 都出在這里。最典型的現(xiàn)象是overlay 透明區(qū)域在預(yù)覽里是透明的導(dǎo)出照片后卻變成黑色。為什么會(huì)這樣因?yàn)楹铣蛇^程中如果某個(gè)環(huán)節(jié)用的是不帶 alpha 的 RGB 格式透明區(qū)域沒有被正確保留黑色或者默認(rèn)值就會(huì)被填充進(jìn)去。所以在搭相機(jī) overlay 流程之前先確認(rèn)你拿到的圖像格式是 RGBA 還是 RGB以及你的合成管線是否全程保留了 alpha。這是第一道關(guān)卡。2.2 合成順序和混合模式Overlay 圖層不是簡單的“先畫的在下后畫的在上”。當(dāng)有多個(gè)圖層時(shí)合成順序會(huì)直接影響最終效果。順序規(guī)則很簡單從底層到上層逐層合成。常見做法是先把相機(jī)畫面作為最底層再按圖層配置依次疊上貼紙、文字、濾鏡。每個(gè)圖層可以有自己的 alpha 不透明度?;旌夏J絼t是另一個(gè)維度。正常的src_over模式就是直接覆蓋而multiply正片疊底、screen濾色這些模式會(huì)按照不同算法混合上下兩個(gè)像素適合做濾鏡、光影效果。如果只是做文字貼紙水印用src_over就夠了想做特效再去研究混合模式。對(duì)大部分 overlay 相機(jī)項(xiàng)目來說順序管理比混合模式重要得多。建議從一開始就把圖層列表設(shè)計(jì)成數(shù)組每個(gè)圖層對(duì)象包含類型、資源路徑、位置、大小、旋轉(zhuǎn)角度、alpha、是否可見這些字段。這樣順序、替換、刪除都只是數(shù)據(jù)操作而不是在渲染代碼里硬編碼。2.3 坐標(biāo)系是你第一個(gè)會(huì)遇到的真問題這是整個(gè) overlay 相機(jī)里最容易出錯(cuò)、也最值得先想清楚的地方。相機(jī)傳感器輸出的原始圖像有自己的坐標(biāo)系。屏幕顯示也有一個(gè)坐標(biāo)系。中間經(jīng)過旋轉(zhuǎn)、鏡像、裁剪后坐標(biāo)系會(huì)出現(xiàn)三種常見差異旋轉(zhuǎn)手機(jī)橫豎屏切換時(shí)相機(jī)圖像需要旋轉(zhuǎn) 90 度或 180 度overlay 圖層如果不跟著轉(zhuǎn)就會(huì)錯(cuò)位。鏡像前置攝像頭通常輸出鏡像畫面后置不鏡像。overlay 如果沒有跟隨鏡像文字會(huì)左右相反。裁剪相機(jī)預(yù)覽為了適配屏幕寬高比會(huì)裁剪邊緣。overlay 的坐標(biāo)如果基于未被裁剪的原始圖像貼紙就會(huì)被裁掉一部分。操作系統(tǒng)通常提供變換矩陣來處理這些差異。許多相機(jī)框架都有現(xiàn)成的坐標(biāo)變換接口建議優(yōu)先使用平臺(tái)提供的接口不要自己手工推公式。一個(gè)更穩(wěn)妥的思路把 overlay 圖層的坐標(biāo)統(tǒng)一定義在“預(yù)覽畫面”的坐標(biāo)系里而不是相機(jī)原始圖像坐標(biāo)系里。這樣無論底層相機(jī)怎么旋轉(zhuǎn)、鏡像、裁剪你只需要在合成或顯示時(shí)應(yīng)用一次變換矩陣。這里可以記住第二個(gè)判斷坐標(biāo)系統(tǒng)的統(tǒng)一是 overlay 項(xiàng)目能不能在不同機(jī)型、不同方向下穩(wěn)定的分水嶺。寧可多花一小時(shí)把矩陣變換做對(duì)也不要靠偏移量去救。3. 搭一個(gè)最小可用的相機(jī) overlay 流程3.1 方案選型直接加 View 還是渲染到紋理在移動(dòng)端做相機(jī) overlay有兩條典型路線。第一種是“預(yù)覽 上層 View”。相機(jī)預(yù)覽單獨(dú)占一個(gè)底層視圖overlay 圖層用普通 UI 控件或自定義 View 畫上去。這種方案簡單、見效快普通貼紙和文字完全夠用而且可以直接復(fù)用系統(tǒng)的觸摸事件。第二種是“渲染到紋理”。相機(jī)輸出不是直接顯示而是先送到紋理overlay 圖層也在同一套渲染管線里合成最終一幀畫面再輸出到屏幕或編碼器。這種方案適合做濾鏡、美顏、特效因?yàn)樗袌D像處理都發(fā)生在統(tǒng)一的渲染管線里可控性更強(qiáng)但復(fù)雜度明顯更高。對(duì)個(gè)人練手項(xiàng)目和大多數(shù) overlay 相機(jī)需求我的建議是先走第一種方案把上層 View 的坐標(biāo)系、生命周期、性能問題搞清楚確定需要做像素級(jí)特效后再升級(jí)到第二種方案。3.2 最小流程五步走無論是哪種方案一個(gè)完整的相機(jī) overlay 流程都可以拆成五步初始化相機(jī)預(yù)覽源拿到一幀一幀的圖像流。把圖像流渲染到底層視圖或紋理上。在預(yù)覽之上創(chuàng)建一個(gè) overlay 容器用于承載圖層。把圖層坐標(biāo)綁定到預(yù)覽畫面的坐標(biāo)系處理旋轉(zhuǎn)、鏡像、裁剪。當(dāng)需要導(dǎo)出、截圖或錄制時(shí)把所有圖層和背景合成到一塊畫布輸出最終圖像。這五步的順序很重要。新手經(jīng)常跳過第 2 步和第 4 步直接開始畫貼紙結(jié)果后面返工。下面給一個(gè)通用的結(jié)構(gòu)示意不綁定具體平臺(tái)方便理解整體數(shù)據(jù)流// 以常見移動(dòng)端相機(jī)預(yù)覽為例展示整體結(jié)構(gòu) class OverlayCameraScene { // 1. 相機(jī)畫面作為最底層 val background: Texture CameraPreviewTexture() // 2. 一組可配置的 overlay 圖層 val layers: MutableListOverlayLayer mutableListOf() // 3. 每次刷新時(shí)按順序合成 fun renderFrame() { renderer.clear() renderer.draw(background) // 先畫底層相機(jī)畫面 for (layer in layers) { renderer.drawLayer(layer) // 再按配置疊上層 } } } data class OverlayLayer( val type: LayerType, // 貼紙 / 文字 / 濾鏡 val resourceId: String, val position: PointF, // 在預(yù)覽坐標(biāo)系中的位置 val scale: Float, val alpha: Float, val visible: Boolean )3.3 關(guān)鍵參數(shù)不要一開始就追求復(fù)雜跑通最小流程時(shí)參數(shù)不需要多四個(gè)夠用圖層位置position定義在預(yù)覽坐標(biāo)系里。縮放比例scale圖片原始尺寸和顯示尺寸的比例用來控制貼紙大小。透明度alpha控制整個(gè)圖層的半透明效果。層級(jí)順序order決定圖層誰在上、誰在下。其他參數(shù)比如旋轉(zhuǎn)角度、混合模式、邊框陰影等最小流程跑通后再逐步加。不要一上來就做一個(gè)參數(shù)面板那樣只會(huì)讓排查問題變難。運(yùn)行時(shí)的默認(rèn)值可以先保守一點(diǎn)alpha 設(shè)為 1.0scale 設(shè)為 1.0position 放在預(yù)覽畫面的中心。跑通后再調(diào)整。3.4 關(guān)于“導(dǎo)出”這件事要提前想好很多 overlay 相機(jī)項(xiàng)目在預(yù)覽階段一切正常一到導(dǎo)出就出問題。原因通常是預(yù)覽時(shí)你可以用上層 View 來疊加圖層但導(dǎo)出時(shí)上層 View 的內(nèi)容不會(huì)自動(dòng)出現(xiàn)在相機(jī)照片里。你必須把相機(jī)圖像和所有 overlay 圖層重新合成到一張新的圖像上。所以流程設(shè)計(jì)時(shí)要在開始時(shí)就把“合成導(dǎo)出”作為獨(dú)立模塊而不是最后再貼。導(dǎo)出的合成操作和預(yù)覽的顯示操作可以共用同一份圖層配置數(shù)據(jù)但渲染路徑不同。一個(gè)簡單的做法是預(yù)覽鏈路用 UI 疊加導(dǎo)出鏈路用離屏渲染把圖層繪制到相機(jī)圖像上。確保兩個(gè)鏈路讀取的是同一個(gè)圖層配置導(dǎo)出結(jié)果才會(huì)和預(yù)覽看到的一致。4. 單次跑通不等于能穩(wěn)定使用4.1 性能幀率、內(nèi)存、紋理大小先跑通再優(yōu)化。這個(gè)原則在 overlay 相機(jī)里尤其重要因?yàn)椤芭芡ā焙汀澳芊€(wěn)定用”之間的差距往往不是功能而是性能。預(yù)覽鏈路里每一幀都要完成背景渲染和所有 overlay 圖層的繪制。圖層越多、紋理越大單幀耗時(shí)越長。如果單幀耗時(shí)超過 33 毫秒對(duì)應(yīng) 30fps畫面就會(huì)開始卡頓。實(shí)際落地時(shí)有幾個(gè)容易拖慢幀率的點(diǎn)overlay 圖片過大。一張 4000×3000 的貼紙即使顯示區(qū)域只有 100×100紋理上傳和合成開銷仍然按原始尺寸算。建議加載時(shí)就做縮放。每幀都重新加載資源。應(yīng)該緩存紋理而不是每幀從磁盤讀一遍。透明區(qū)域很大的貼紙。像素合成時(shí)不會(huì)因?yàn)?alpha 為 0 就跳過仍然要遍歷像素。遇到這種情況可以把多個(gè)貼紙合到一張紋理圖集里減少繪制調(diào)用。內(nèi)存方面最容易踩的坑是反復(fù)創(chuàng)建圖像對(duì)象、紋理或渲染緩沖區(qū)導(dǎo)致 GC 頻繁觸發(fā)、內(nèi)存抖動(dòng)。建議做好對(duì)象復(fù)用。4.2 生命周期相機(jī)和 overlay 必須同步相機(jī)不是普通的 UI 組件它有嚴(yán)格的生命周期。攝像頭在后臺(tái)、被占用、被切換時(shí)都可能產(chǎn)生異常。Overlay 如果獨(dú)立于相機(jī)生命周期最容易出現(xiàn)的問題就是相機(jī)已經(jīng)釋放overlay 還在繪制或者相機(jī)重新啟動(dòng)后overlay 配置沒有恢復(fù)。正確的做法是讓相機(jī)預(yù)覽和 overlay 場景共享同一個(gè)生命周期。具體來說頁面進(jìn)入前臺(tái)時(shí)一起初始化相機(jī)和 overlay 圖層。頁面退到后臺(tái)時(shí)一起停止預(yù)覽和合成。相機(jī)出異常時(shí)overlay 圖層狀態(tài)要保留等相機(jī)恢復(fù)后直接重繪。這里的核心不是“每個(gè)組件各自弄好”而是“整個(gè)場景狀態(tài)要統(tǒng)一管理”。4.3 兼容性你永遠(yuǎn)不知道用戶用什么設(shè)備不同手機(jī)的相機(jī)傳感器、屏幕比例、系統(tǒng)版本差異很大。常見的坑包括屏幕比例 16:9 和 18:9 的設(shè)備預(yù)覽裁剪區(qū)域不同overlay 位置可能偏移。前置和后置攝像頭的鏡像規(guī)則不同。某些機(jī)型在切換前后攝像頭時(shí)輸出尺寸會(huì)變化需要重新計(jì)算 overlay 的坐標(biāo)變換。開發(fā)階段至少要準(zhǔn)備兩到三臺(tái)不同比例、不同廠商的真機(jī)測試。模擬器上跑通不等于真機(jī)沒問題因?yàn)橄鄼C(jī)硬件差異模擬器無法模擬。4.4 從 demo 到工程的差距日志、狀態(tài)、可配置化最后一步是把 demo 變成工程。這個(gè)階段要補(bǔ)三件事。第一日志。每一幀合成、每次相機(jī)狀態(tài)切換、每個(gè) overlay 圖層的加載失敗都要有可查的日志。不然出了問題只能對(duì)著屏幕猜。第二狀態(tài)管理。相機(jī)狀態(tài)、預(yù)覽狀態(tài)、圖層狀態(tài)建議用一個(gè)狀態(tài)機(jī)或統(tǒng)一的狀態(tài)容器管理避免多線程下狀態(tài)不一致。第三可配置化。把 overlay 圖層的來源、位置、大小、順序做成外部配置比如 JSON 或接口返回。這樣后續(xù)添加貼紙、修改布局時(shí)不需要重新改代碼。配置結(jié)構(gòu)大致像這樣{ layers: [ { type: image, url: assets/stickers/cat.png, x: 0.5, y: 0.3, scale: 0.8, alpha: 1.0, order: 1 }, { type: text, content: Hello Overlay, x: 0.5, y: 0.7, fontSize: 48, color: #FFFFFF, order: 2 } ] }這里把 x 和 y 定義為相對(duì)坐標(biāo)0~1好處是適配不同屏幕尺寸。預(yù)覽時(shí)用“相對(duì)坐標(biāo) × 預(yù)覽寬高”換算成像素導(dǎo)出時(shí)再用“相對(duì)坐標(biāo) × 最終輸出寬高”換算這樣預(yù)覽和導(dǎo)出能保持一致。5. 當(dāng) overlay 不顯示、錯(cuò)位、卡頓時(shí)按這個(gè)順序排查5.1 先看現(xiàn)象再沿著鏈路逐層找Overlay 相機(jī)的問題往往不是單點(diǎn)原因而是多個(gè)環(huán)節(jié)疊加造成。建議按下面的順序排查不要跳步看現(xiàn)象。是 overlay 完全不顯示、顯示但位置錯(cuò)亂、顏色不對(duì)還是預(yù)覽卡頓不同現(xiàn)象對(duì)應(yīng)的排查方向不同。看輸入。貼紙資源是否存在、格式是否支持 alpha、路徑是否正確、圖片尺寸是否過大??春铣涉溌贰1尘笆欠裣犬嫛verlay 是否按順序畫、合成時(shí)有沒有丟 alpha??醋鴺?biāo)系變換。是否處理了旋轉(zhuǎn)、鏡像、裁剪圖層坐標(biāo)定義在哪個(gè)坐標(biāo)系??瓷芷?。相機(jī)是否還在活動(dòng)狀態(tài)、overlay 是否在相機(jī)釋放后繼續(xù)繪制??葱阅?。單幀耗時(shí)、內(nèi)存占用、是否頻繁 GC、紋理是否過大。最后看工具和平臺(tái)邊界。當(dāng)前系統(tǒng)版本、相機(jī)輸出格式、平臺(tái) API 差異。一個(gè)簡單的判斷表現(xiàn)象優(yōu)先排查方向常見原因overlay 完全不顯示輸入和層序資源路徑錯(cuò)誤、圖層 alpha0、圖層順序被蓋住overlay 位置錯(cuò)亂坐標(biāo)系變換未處理旋轉(zhuǎn)/鏡像、坐標(biāo)定義不統(tǒng)一透明區(qū)域變黑alpha 通道合成管線丟 alpha、圖像格式錯(cuò)用 RGB預(yù)覽卡頓性能和紋理單幀耗時(shí)過長、貼紙紋理過大、內(nèi)存抖動(dòng)切換前后攝像頭后錯(cuò)亂生命周期和坐標(biāo)輸出尺寸變化未重算、鏡像規(guī)則未更新退出頁面后黑屏或崩潰生命周期相機(jī)未釋放、overlay 還在繪制5.2 三個(gè)最容易反復(fù)踩的坑第一個(gè)坑是“透明區(qū)域變黑”。這個(gè)前面說過核心是 alpha 通道丟失。排查時(shí)先確認(rèn)加載的貼紙本身帶透明通道再確認(rèn)合成時(shí)使用的圖像格式是 RGBA_8888 而不是 RGB_565。第二個(gè)坑是“預(yù)覽位置正確導(dǎo)出位置偏了”。原因是預(yù)覽坐標(biāo)和導(dǎo)出坐標(biāo)定義不一致。解決辦法就是統(tǒng)一用相對(duì)坐標(biāo)0~1預(yù)覽和導(dǎo)出各自換算避免在不同環(huán)節(jié)硬編碼像素值。第三個(gè)坑是“貼紙?jiān)谪Q屏正常橫屏或者翻轉(zhuǎn)后就亂”。原因是坐標(biāo)系沒有跟隨相機(jī)旋轉(zhuǎn)。處理方式是把相機(jī)變換矩陣傳給 overlay 場景讓所有圖層坐標(biāo)在渲染時(shí)應(yīng)用同一套矩陣而不是分別調(diào)位置。排查問題時(shí)要記住先動(dòng)數(shù)據(jù)再動(dòng)視圖。先把圖層配置打印出來確認(rèn)位置、alpha、順序都是對(duì)的再去懷疑渲染代碼。大多數(shù)問題出在數(shù)據(jù)而不是繪制。6. 這類項(xiàng)目真正值得長期關(guān)注的地方6.1 從一次合成變成一套可復(fù)用流程Overlay 相機(jī)項(xiàng)目最吸引人的地方不是某個(gè)濾鏡多好看而是它把“圖像合成”這件事做成了一套可復(fù)用的流程。同樣的 overlay 機(jī)制可以做相機(jī)貼紙、照片水印、視頻字幕、直播特效甚至在更廣泛的渲染場景里復(fù)用。所以做這類項(xiàng)目時(shí)不要只盯著“這個(gè)貼紙好不好看”而要把注意力放在圖層數(shù)據(jù)結(jié)構(gòu)是否清晰、合成流程是否解耦、坐標(biāo)變換是否統(tǒng)一、導(dǎo)出是否符合預(yù)期。這些能力是可以遷移到其他項(xiàng)目的。6.2 overlay 的下一個(gè)階段現(xiàn)在常見的實(shí)時(shí)貼紙、AR 特效、AI 美顏本質(zhì)上都是 overlay 的延伸。它們沒有推翻 overlay 的基本框架只是在圖層類型上增加了幾類“動(dòng)態(tài)圖層”基于人臉關(guān)鍵點(diǎn)定位的貼紙、基于深度信息的特效、基于模型推理生成的濾鏡。這意味著如果你現(xiàn)在把 overlay 相機(jī)的基礎(chǔ)流程真正吃透將來接觸 AR 或 AI 特效時(shí)你的知識(shí)不是從零開始而是多了一層“動(dòng)態(tài)內(nèi)容如何適配到合成管線”的增量。6.3 適用邊界什么時(shí)候不該用這套思路最后也說說邊界。Overlay 合成不是所有場景的最優(yōu)解。如果你只是做照片后期加個(gè)水印不需要實(shí)時(shí)預(yù)覽完全可以直接用離屏合成不需要搭相機(jī)預(yù)覽鏈路。如果你要做的是復(fù)雜的視頻剪輯特效建議直接使用成熟的渲染引擎或視頻編輯 SDK而不是從零寫 overlay 管線。如果你只是想在頁面里做一個(gè)彈窗浮層那其實(shí)和相機(jī) overlay 關(guān)系不大屬于前端層級(jí)管理問題。適合用本文這套流程的場景是有實(shí)時(shí)相機(jī)預(yù)覽需要在預(yù)覽畫面疊加可交互的文字、貼紙或?yàn)V鏡且需要保證預(yù)覽和導(dǎo)出結(jié)果一致。這個(gè)場景下坐標(biāo)系、透明通道、圖層順序、生命周期、性能這五件事才是真正的核心。回到開頭那個(gè)項(xiàng)目名?!熬d綿很好_overlay”具體實(shí)現(xiàn)了什么功能我沒有辦法替作者確認(rèn)但它的命名方式反映了一個(gè)事實(shí)這類 overlay 項(xiàng)目正從“隨手玩玩”走向更多人的關(guān)注。真正決定它們價(jià)值的不是名字好不好聽而是把疊加層從一次偶然的成功變成一套穩(wěn)定、可解釋、可維護(hù)的流程。如果你也想做類似的工具我的建議很簡單先找一個(gè)最小場景把相機(jī)畫面和一張貼紙疊起來跑通預(yù)覽再跑通導(dǎo)出然后畫出坐標(biāo)系和生命周期。這五件小事做完你對(duì) overlay 的理解會(huì)比之前大部分教程能教你的更深。