提升前端工程化,攜程Design2Code從零到一的實踐
一、背景
在軟體開發過程中,團隊協作效率的提高是我們共同關注的問題。為了解決這一問題,許多團隊都開始使用智慧化工具。Design2Code(簡稱D2C)工具是其中一種廣受歡迎的選擇。
在本文中,我們將分享D2C工具的核心演算法方案設計和實現過程,以及一系列的解決方案。無論你是開發人員,還是設計師,本文都將為你提供有價值的資訊。我們希望,透過閱讀本文,能幫助你更好地瞭解D2C工具,並在實際工作中發揮出最大的價值。
二、前置知識
2.1 基本概念
D2C是一種透過使用智慧化技術將設計稿轉化為程式碼的工具,旨在提升開發效率,減少人力成本,並縮短設計到開發的流程。透過將設計稿原始檔(如:PSD、Sketch、Figma)轉化為React、Vue、小程式等平臺的前端程式碼,再使用領域特定語言(DSL)將其轉化為各端程式碼,D2C通常透過人工智慧訓練的模型或演算法實現。
2.2 哪些特性
高效協作:使用智慧化技術,提升前端工程師和設計師之間的協作效率。
高還原度:降低設計師檢查頁面還原度的人力成本。
高相容性:減少多端適配的開發成本。
快速上線:自動生成檢視層程式碼,減少手工工作量。
三、業界現狀
我們對業內比較出色的D2C產品進行調研,包括阿里 imgcook、京東 Deco、CodeFun、微軟 AI Lab 和 Locofy。我們在調研過程中,對各家公司的產品進行了對比,但這裡不再贅述。透過調研,我們得出初步結論:
預裝Sketch外掛或上傳檔案解析,匯出DSL資料。
透過 AI 自動處理並生成前端程式碼,支援使用Web編輯器對程式碼進行人工干預和編輯。
需要將設計稿資料儲存在對方伺服器。
程式碼未開源,解決方案也只是簡略描述。
部分公司進階功能需付費使用。
四、效果展示
D2C系統轉換流程介紹:
1. 上傳Sketch原始檔入口 → 2. 對資料進行處理並返回結果 → 3.展示轉換結果。
透過“檢視程式碼”功能獲取多端程式碼。
我們對APP、H5 、Online和小程式設計稿進行了還原比對,還原精度達到80%,且在不斷提升中。
下圖展示了系統轉換效果:
五、解決方案
5.1 方案分析
根據上述調研結果以及業務場景,我們的目標是將設計稿轉換為程式碼。主要解決三個問題:
(1)提取圖層資訊:需要提取設計圖中的圖層資訊,以獲取所有圖層元素的位置、大小、形狀和顏色等資訊。這些資訊將為後續的頁面佈局提供基礎。
(2)資訊預處理:在將圖層資訊轉換為程式碼之前,需要對資訊進行一些預處理。例如,篩選和過濾無用資訊和圖層,處理圖層style欄位與css的對映關係,解決設計稿中資料夾order如何轉換為佈局order的問題,以及處理圖片資源的匯出等。預處理有助於提高後續程式碼生成過程中的程式碼質量和佈局準確性。
(3)構建佈局關係:利用所提取的圖層資訊,可以進行精確的頁面佈局。使頁面儘可能地還原設計稿。
5.2 方案思考
為了更好的理解問題,將從簡單到複雜依次講解上述三個問題。
(1)問題1:“提取圖層資訊”,使用 sketch2json 開源工具可以從 Sketch 和 Figma 設計稿中提取圖層資訊,將向量資料轉換為 JSON 格式。資料結構中的 'layers' 對應著 HTML 的結構層,而 'style' 對應著 CSS 的表現層。下圖展示了從 Sketch 中獲取的資料結構。
(2)問題2:“資訊預處理”,需要對基於“提取圖層資訊”的資料進行一系列處理。這一步的流程較為複雜,涉及到多個技術難點。我們曾經在這一步踩過許多坑,並對技術方案進行了多次調整。其中,有幾個技術要點值得著重講述,例如:
篩選過濾無用資訊和圖層:對於 sketch2json 獲取的 JSON 資料中,有因 Sketch 的對映關係存在的大量對於影像還原無效的資料欄位和因為設計師對於影像繪製不規範產生的無用圖層資訊,所以需要對其中無效資料欄位和無用圖層資訊做一層資料過濾,減輕 JSON 的量級方便後續計算。
欄位型別對映:瘦身處理後的資料還需要再精細化處理,其中 Sketch 的樣式欄位等與傳統的 CSS 不一致,需要透過轉換進行關係對映。對於 Sketch 的圖層具體定義為文字還是圖片等也需要做相關欄位對映。
圖層結構重組:sketch2json 轉化後的圖層巢狀結構嚴格依賴視覺稿規範程度,可用性較低,需要對其進行一次結構重組,將所有圖層打平,後續利用圖層位置資訊計算出準確的包含關係。
Order 層級深度推算:圖層打平重組後,如何計算每個圖層在DOM Tree中的層疊關係。我們可以根據初始JSON資料中的原始巢狀關係進行推算,為重組後的圖層賦予新的層級深度值。
Symbol 元素處理:在 Sketch 中,Symbol 作為一種特殊元素,建立後可以被重複引用,類似前端中的元件。Symbol 元素在 Sketch 轉化後的 JSON 資料中,只包含了其引用ID,它的真實圖層資料被儲存在了其它位置,需要透過引用ID檢索到真實資料後替換 JSON資料中的 Symbol 元素。
進行系列處理之後,我們得到了前端可用的圖層資訊,即最終的 DSL 樹形資料。
下圖展示了預處理後的 DSL 資料結構:
(3)問題3:“構建佈局關係”是所有步驟中最複雜的一步,因為它涉及到許多技術難點,且幾乎沒有可供借鑑的開源資料。我們可能需要透過不斷的嘗試來解決問題。實際上,構建佈局關係是基於之前提到的 JSON 資料進行 absolute 和 flex 關係的規整,然後對 DSL 進行遞迴渲染。具體實現過程可以參閱下文的佈局核心演算法設計。
5.3 方案實現
5.3.1 架構設計
在進行系統架構設計時,我們綜合了上述問題分析和思考後基本確定了技術的可行性和方向。為了滿足系統的目標和功能,我們把系統拆分成了三個核心應用,分別負責執行核心任務。這張架構圖展示了我們設計的架構,其中包括:檢視渲染應用、佈局演算法服務和切圖演算法服務三個應用。在下文中,我們將對這些應用進行詳細的闡述。
檢視渲染應用:負責渲染轉換結果介面。
透過上傳的Sketch檔案,我們可以提取出設計稿資訊並將其轉換為JSON格式。這些資訊將被傳遞給佈局演算法服務進行處理。演算法服務將返回包含圖層資訊和樣式資訊的DSL,以樹形結構形式呈現。我們將使用DSL來渲染各端頁面程式碼。
佈局演算法服務:負責計算元素的位置和佈局,以確保介面還原精準。
具體來說,它會將設計稿的向量資料轉化為前端可用的結構化資料。這個過程包括打平和再加工等主要步驟。打平的目的是將圖層之間的關係(父子和兄弟關係)重新組織,再加工的目的是過濾一些干擾圖層。最終,演算法服務將返回中間層的DSL資料,該資料將用於檢視渲染應用的前端程式碼轉換。
完整流程圖:
切圖演算法服務:負責將影像切割成合適的尺寸顯示在介面上。
為此,我們使用一臺預裝了Sketch軟體的Mac機器,並使用Sketchtool-cli處理設計稿中的影像、圖示和路徑。透過接收前端傳遞的圖層symbolID,然後根據symbolID將設計稿中的圖片匯出並儲存在本地磁碟中。接下來,前端會讀取本地磁碟中的對應資料夾的圖片,並透過介面呼叫的方式將圖片上傳到靜態資源伺服器。最後,伺服器會返回可生產訪問的CDN URL給前端,前端會將所有URL同步到DSL中。
另外如何正確合理的對圖片進行切割,我們做了如下分類處理:對於sketch裡的樣式屬性利用css不易畫出時將這個圖層定義為圖片背景、對於多種形狀結合、蒙層合併的情況,首先判斷其當前圖層型別、再根據特定演算法判斷其子圖層裡的元素是否滿足條件進行圖層之間的合併,將多個單一圖片合併為一整張合理的大圖、對於已經採用了三角形、橢圓等特殊形狀的圖層確立為圖片。
完整流程圖:
5.3.2 核心演算法設計
(1)Sketch層級規律:
對於Sketch設計稿初始JSON資料中的樹狀圖層結構,每兩個圖層的層級大小判斷存在以下規則:
若圖層節點A是圖層節點B的子孫節點,那麼,圖層A層級 大於 圖層B層級;
若兩個圖層節點非子孫/祖父節點,那麼,這兩個節點所在的最小公共子樹中,若存在圖層A的祖父節點為圖層B的祖父節點的右兄弟節點,則表示圖層A層級 大於 圖層B層級。
經過分析,圖層層級大小和樹的先序遍歷訪問先後順序一致,即根節點 < 左子樹節點 < 右子樹節點。
(2)投影演算法:
佈局關係之兄弟關係,利用光影投射的原理,透過從X軸和Y軸的方向對其中的元素進行對映,投影后所在同一個陰影塊內的元素,則構成了兄弟關係。兄弟關係演算法的示意圖:
(3)交叉演算法:
佈局關係之父子關係:透過座標計算,對於有相交關係的或包含關係的元素之間,則構成了父子關係。父子關係演算法示意圖:
另外在父子關係中,還需要考慮元素是否有定位。如果兩個元素相交,則需要再次判斷元素的大小,以決定父子關係中的父與子。為了方便後續處理佈局關係,我們可以為子元素打上絕對定位的標籤。
透過兩個元素對角數學關係進行判斷:
(4)flex佈局關係推斷:
處理完父子關係和兄弟關係後,為了更好地滿足佈局的合理性,我們需要透過演算法來推測元素中的flex佈局方向。
透過判斷子layer,當他們的大小接近,並且Y值相差在固定閾值內且X值相差過大時,可以推斷出該層layer的佈局使用flex,且direction為row。
透過判斷子layer,當他們的大小接近,並且X值相差在固定閾值內且Y值相差過大時,可以推斷出該層layer的佈局使用flex,且direction為column。
六、視覺約束
為了更高效、準確地還原設計稿,建議輸出的 Sketch 原始檔做一些規範約束:
建議將元件保持在獨立的畫板中,這樣可以避免轉換無效的元素,方便工程師後續的程式碼邏輯開發。
保留有意義的圖層,刪除無效的空圖層,並且儘量避免過深的圖層巢狀。這樣可以避免渲染樹過深,影響頁面載入效能。
圖層分組(即 Sketch 中的資料夾)應該合理巢狀,避免交錯放置。合理擺放元素資料夾可以有利於還原元素的 DOM 樹關係。
除設計上有必要以外,應儘量避免將同級元素放在容器中交錯排列,因為這會導致這些元素在渲染樹中被視為父子關係。
對於相同型別的多行文字,建議使用一個文字圖層,這樣可以避免因為設計稿中的兩個圖層而將相同型別的文字轉換為兩個 HTML 段,從而提高程式碼複用率,減少程式碼重複。對於濾鏡等特殊效果,建議使用圖片來實現,以提高還原精度。
七、後續規劃
(1)提高佈局合理性:
提高flex彈性佈局的推算準確度
提升dom tree 分割準確度
減少dom tree 深度
(2)提高UI還原度:
列表迴圈識別能力
提升長頁面還原度能力
(3)其它:
減少視覺稿人工干預頻次
適配不同團隊設計規範
八、總結
D2C技術是一種旨在提高企業產品研發效率,最佳化設計到開發流程,加速研發進度,以及輔助前端開發人員探索前端智慧化道路的技術。主要優勢包括:
探索前端智慧化:透過將設計稿轉化為前端程式碼的方式,實現前端智慧化。可以提高前端開發的效率,保證設計的精確實現。
最佳化產品研發流程:可以提高產品研發的效率,減少人力成本,提升團隊的協作效率。更高效地進行產品的迭代和最佳化。
簡化設計到開發流程:可以最佳化設計到開發的流程,減少溝通成本,提升工作效率。設計人員可以直接使用設計工具製作設計圖,並將其轉化為程式碼,減少設計到開發的翻譯過程。
加速研發進度:可以幫助團隊加速研發進度,更快地將產品推向市場,並可以更快速地完成設計和開發工作。同時,也可以更快地進行產品的測試和驗證。
來自 “ 攜程技術 ”, 原文作者:by & Jialu;原文連結:http://server.it168.com/a2023/0303/6792/000006792268.shtml,如有侵權,請聯絡管理員刪除。
相關文章
- 前端工程化最佳實踐前端
- Hadoop叢集從180到1500,攜程大資料實踐之路Hadoop大資料
- 淺談攜程大住宿研發效能提升實踐
- 前端 Git-Hooks 工程化實踐前端GitHook
- 【溫故】前端工程化思考與實踐前端
- 開源實踐 | 攜程在OceanBase的探索與實踐
- 開源實踐 | 攜程在 OceanBase 的探索與實踐
- Babel 在提升前端效率的實踐Babel前端
- 實踐指南-前端效能提升 270%前端
- 攜程DBA負責人俞榕剛:OceanBase在攜程的落地和實踐
- ScaleFlux CSD 2000 在攜程的應用實踐UX
- 從Storm到Flink,有贊五年實時計算效率提升實踐ORM
- 攜程小程式內嵌webview實踐指南WebView
- 攜程MySQL遷移OceanBase最佳實踐|分享MySql
- 從前後端分離到GraphQL,攜程如何用Node實現?\n後端
- 【Go 程式設計實踐】從零到一:建立、測試併發布自己的 Go 庫Go程式設計
- 張翼:Spark SQL在攜程的實踐經驗分享!SparkSQL
- Vue 工程化最佳實踐Vue
- Vue工程化最佳實踐Vue
- GraphQL java工程化實踐Java
- 從設計到程式碼:探索高效的前端開發工具與實踐前端
- 乾貨分享:螞蟻金服前端框架和工程化實踐前端框架
- 從零到一,元件庫的進化元件
- 從零到一:實現通用一鏡到底H5H5
- 貝葉斯分類器詳解 從零開始 從理論到實踐
- 從零到一編寫MVVMMVVM
- 攜程後臺低程式碼平臺的探究與實踐
- 從零搭建一個前端cli腳手架併發布到npm前端NPM
- 從業務元件庫看前端工程化元件前端
- 從零到有模擬實現一個Set類
- 攜程 Redis On Rocks 實踐,節省 2/3 Redis成本Redis
- GraphQL 從入門到實踐
- React + Typescript 工程化治理實踐ReactTypeScript
- 前端工程化:圍繞Jenkins打造工作流的過程前端Jenkins
- 自動化介面用例從 1 到 1000 過程中的實踐和思考
- 從零到一實現類vue2.*的簡單MVVM框架VueMVVM框架
- 攜程對AIOps場景和演算法的探索與實踐AI演算法
- 基於 qiankun 的微前端最佳實踐(萬字長文) - 從 0 到 1 篇前端