搜尋
首頁web前端css教學構建互動無花果小部件

Building Interactive Figma Widgets

Figma一直鼓勵開發者和設計師之間的協作,並憑藉其豐富的社區插件庫而蓬勃發展。需要3D元素?有插件!需要抽象的SVG?也有插件!

然而,Figma的設計部分一直相對靜態——始終使用不可移動的矩形,通過預定義的用戶交互連接在一起。但如果我說你的設計可以突然栩栩如生——可以動畫化、交互式,甚至是有狀態的,你會怎麼想?那麼,概念與實現之間還有什麼區別呢?

Figma在6月份宣布將推出基於JavaScript的小部件。現在,設計師可以直接在Figma中瀏覽和實現邏輯驅動的組件!

讓我們一起了解一下Widgets API!想知道它是什麼以及如何使用它嗎?這正是我們將在本文中一起探討的內容。

Figma小部件開啟無限可能

想像一下,你和你的合作夥伴日夜合作設計一個大型餐廳應用程序。你們都在同一個Figma畫板上協作;你們共享完全相同的文檔,更改實時發生。

當然,你已經知道協作不僅僅包括設計過程:

  • 項目管理,
  • 舉辦投票,
  • 導入和可視化模擬數據,
  • 也許甚至玩一個多人遊戲來放鬆一下長時間的工作。

只需要一個人管理所有內容並向小組的其他成員發送鏈接。但是,這效率不高,對吧?

這就是小部件發揮作用的地方。我們可以想像做到所有這些——是的,所有這些——無需離開Figma。

以下是一些你可能希望在Figma中使用小部件的方式:

  • 為Jira和Asana創建任務
  • 在GitHub中創建問題
  • 顯示動態數據
  • 錄製語音備忘錄
  • 創建任務列表
  • 浪費時間玩井字遊戲
  • 追踪活動
  • 創建計時器

等等等等。正如你所看到的,已經有大量的小部件可以自由地用於你的文檔中。事實上,你可以直接從“小部件”菜單(Shift I)將小部件添加到你的畫板中。

但我們不是來學習如何使用小部件的,因為這很容易。讓我們做我們最擅長的事情:我們將創建我們自己的Figma小部件!這個小部件將以Chris Coyier的設計報價網站為靈感。我們將獲取API,將其饋送到小部件,然後直接在Figma中顯示隨機的設計報價。

我們需要什麼

我不喜歡當壞消息的傳播者,但是為了開發小部件,你必須在Windows或Mac上。 Linux用戶,對不起,你運氣不好。 (如果你想繼續學習,你仍然可以使用虛擬機。)

我們將下載Figma桌面應用程序。最簡單的入門方法是從應用程序中直接生成小部件模板。

讓我們通過打開小部件菜單(Shift I)、切換到開發選項卡並創建一個新項目來創建一個新的畫板。

之後,Figma會提示你命名新的小部件,並決定它是否更適合設計畫板或FigJam畫板。對於本文的目的,前一個選項就足夠了。

定制並沒有就此結束;Figma還會讓你選擇從預製計數器小部件或啟用iFrame的替代方案開始,該方案還允許你訪問Canvas和Fetch API(以及所有其他瀏覽器API)。我們將選擇簡單的“空”選項,但我們最終會自己修改它以使用Fetch API。

然後,系統會提示你將新的Widget項目保存到系統中的特殊目錄。完成後,啟動你的終端並將其定向到該文件夾。現在還不要運行任何命令——我們稍後會這樣做,並故意出現錯誤,目的是學習更多關於Widgets API的知識。

設計小部件

我們直接從Chris Coyier的設計報價網站獲取設計。所以,讓我們去那裡,通過啟動DevTools來深入研究。

我在這裡使用的兩個關鍵快捷鍵是Ctrl Shift C(或Cmd Shift C)來切換“拾取元素”工具,以及Shift 單擊來將顏色格式更改為HEX代碼。我們這樣做是為了了解Chris網站中使用的顏色、字體、字體粗細和字體大小。所有這些信息對於在Figma中構建一個非常相似的Widget至關重要,這將是我們的下一步!你可以抓取設計好的組件並將其用於你自己的畫布。

我在這裡不會詳細介紹,因為本文的主題是通過編寫代碼來構建小部件。但我必須強調,精心設計小部件的樣式非常重要……CSS-Tricks已經有大量面向設計的Figma教程;你不會後悔將它們添加到你的閱讀列表中。

為我們的Widget創建佈局

設計完成後,是時候拿出我們的編程手指,開始構建我們小部件的齒輪了。

Figma如何將其設計構建塊轉換為類似React的組件非常有趣。例如,具有自動佈局功能的框架元素在代碼中表示為<autolayout></autolayout>組件。除此之外,我們還將使用另外兩個組件:<text></text><svg></svg>

看看我的Figma畫板……我正是要求你關注對象樹。這是我們需要能夠將我們的Widget設計轉換為JSX代碼的關鍵。

如你所見,我們的設計報價小部件需要導入三個組件。考慮到完整的API只包含八個基於圖層的節點,這是一個相當數量的組件。但正如你很快就會看到的,這些模塊足以製作各種佈局。

 <code>// code.tsx const { widget } = figma; const { AutoLayout, Text, SVG } = widget;</code>

有了這個,我們就可以像在React中一樣構建我們小部件的骨架了:

 <code>function QuotesWidget() { const quote = `...`; const author = `...`; return (<autolayout></autolayout></code><svg></svg><autolayout><text> {quote}</text><text> — {author}</text></autolayout><svg></svg>
  );
}

widget.register(QuotesWidget);

這段代碼至少可以說是非常混亂的。現在,我們無法區分設計圖層。幸運的是,我們可以通過使用name屬性輕鬆解決這個問題。

<code><autolayout name="{" quote></autolayout></code> <svg name="{" leftquotationmark></svg><autolayout name="{" quotecontent><text name="{" quotetext> {quote}</text><text name="{" quoteauthor> — {author}</text></autolayout><svg name="{" rightquotationmark></svg> ;

當然,我們仍然看不到我們的引號SVG,所以讓我們著手解決這個問題。<svg></svg>組件接受一個src屬性,該屬性採用SVG元素的源代碼。對此沒有太多可說的,所以讓我們保持簡單,直接跳回代碼:

 <code>const leftQuotationSvgSrc = `</code>
  // 為簡潔起見,已縮短`;
const rightQuotationSvgSrc = ` <svg fill="none" height="103" viewbox="0 0 118 103" width="118" xmlns="<http://www.w3.org/2000/svg>">
// 為簡潔起見,已縮短</svg>`;

function QuotesWidget() {
  return (
    <svg name="{" leftquotationmark src="%7BleftQuotationSvgSrc%7D"></svg><svg name="{" rightquotationmark src="%7BrightQuotationSvgSrc%7D"></svg>
  );
}

我認為我們都可以同意現在一切都清楚多了!當我們命名事物時,它們的目的突然變得對我們代碼的讀者更加明顯。

實時預覽我們的Widget

Figma在構建小部件時提供了良好的開發體驗,包括(但不限於)熱重載。使用此功能,我們可以實時編碼和預覽對小部件的更改。

首先打開小部件菜單(Shift I),切換到開發選項卡,然後單擊或拖動你的新小部件到畫板。找不到你的小部件?別擔心,只需單擊三點菜單並導入你的小部件的manifest.json文件即可。是的,這就是讓它恢復存在的全部步驟!

等等,你的屏幕底部是否出現錯誤消息?

如果是這樣,讓我們調查一下。單擊“打開控制台”並閱讀它的內容。如果“打開控制台”按鈕消失了,則有一種替代方法可以打開調試控制台。單擊Figma徽標,跳轉到“小部件”類別並顯示開髮菜單。

該錯誤可能是因為我們尚未將TypeScript編譯為JavaScript。我們可以通過運行npm installnpm run watch (或yarnyarn watch )在命令行中執行此操作。這次沒有錯誤!

你可能會遇到的另一個障礙是,每次代碼更改時,小部件都無法重新渲染。我們可以使用以下上下文菜單命令輕鬆強制小部件更新:小部件重新渲染小部件

樣式設置小部件

就目前而言,我們小部件的外觀仍然與我們的最終目標相差甚遠。

那麼我們如何從代碼中設置Figma組件的樣式呢?也許像在React項目中那樣使用CSS?錯誤。對於Figma小部件,所有樣式都是通過一套完善的屬性來實現的。幸運的是,這些項目的名稱與Figma中的對應項目幾乎完全相同

我們將首先配置我們的兩個<autolayout></autolayout>組件。如上圖所示,屬性名稱對它們的目的進行了非常清晰的描述。這使我們能夠直接跳轉到代碼並開始進行一些更改。我不會再次顯示整個代碼,所以請依靠組件名稱來指導你代碼片段的位置。

 <code><autolayout direction="{" horizontal horizontal:="" horizontalalignitems="{" center name="{" quote padding="{{" spacing="{54}" vertical:="" verticalalignitems="{" start> <autolayout direction="{" vertical horizontal:="" horizontalalignitems="{" start name="{" quotecontent padding="{{" spacing="{10}" vertical:="" verticalalignitems="{" end></autolayout></autolayout> ;</code>

我們取得了很大的進展!讓我們保存並跳回到Figma以查看我們的Widget的外觀。還記得新更改後Figma如何自動重新加載Widget嗎?

但它還不夠。我們還必須向根組件添加背景顏色:

<code><autolayout fill="{" name="{" quote></autolayout></code>

同樣,查看你的Figma畫板,注意更改如何幾乎立即反映到Widget中。

讓我們繼續本指南並設置<text></text>組件的樣式。

查看Widgets API文檔後,再次清楚地看到屬性名稱與其在Figma應用程序中的對應項幾乎相同,如上圖所示。我們還將使用上一節中檢查Chris網站的值。

 <code><text fill="{'#545454'}" fontfamily="{'Lora'}" fontsize="{36}" fontweight="{'normal'}" name="{'QuoteText'}" width="{700}"> {quote}</text> <text fill="{'#16B6DF'}" fontfamily="{'Raleway'}" fontsize="{26}" fontweight="{'bold'}" name="{'QuoteAuthor'}" textcase="{'upper'}" width="{700}"> — {author}</text></code>

向Widget添加狀態

我們的小部件目前顯示相同的報價,但我們希望隨機從整個報價池中提取。我們必須向我們的Widget添加狀態,所有React開發人員都知道這是一個變量,它的更改會觸發我們組件的重新渲染。

在Figma中,狀態是使用useSyncedState鉤子創建的;它幾乎就是React的useState ,但它要求程序員指定一個唯一的key 。此要求源於這樣一個事實,即Figma必須同步我們Widget的狀態,這些狀態跨越可能正在查看同一設計畫板的所有客戶端,但通過不同的計算機。

 <code>const { useSyncedState } = widget; function QuotesWidget() { const [quote, setQuote] = useSyncedState("quote-text", ""); const [author, setAuthor] = useSyncedState("quote-author", ""); }</code>

目前,這就是我們需要做的全部更改。在下一節中,我們將弄清楚如何從互聯網獲取數據。劇透警告:這並不像看起來那麼簡單。

從網絡獲取數據

回想一下Figma讓我們選擇從啟用iFrame的小部件開始。雖然我們沒有選擇該選項,但我們仍然必須實現其一些功能。讓我解釋一下為什麼我們不能簡單地在小部件代碼中調用fetch()

當你使用小部件時,你正在你的計算機上運行由其他人編寫的JavaScript代碼。雖然所有小部件都經過Figma員工的徹底審查,但這仍然是一個巨大的安全漏洞,因為我們都知道即使是一行JavaScript也會造成多大的損害。

因此,Figma不能簡單地eval()匿名程序員編寫的任何小部件代碼。長話短說,團隊決定最佳解決方案是在嚴密保護的沙箱環境中運行第三方代碼。正如你可能猜到的那樣,瀏覽器API在這種環境中是不可用的。

但不要擔心,Figma對此第二個問題的解決方案是<iframe></iframe>。我們在文件中編寫的任何HTML代碼(最好稱為ui.html )都可以訪問所有瀏覽器API。你可能想知道我們如何從Widget觸發此代碼,但我們稍後會研究這個問題。現在,讓我們回到代碼中:

 <code>// manifest.json { "ui": "ui.html" }</code>
 <code>window.onmessage = async (event) => { if (event.data.pluginMessage.type === 'networkRequest') { // TODO: 从服务器获取数据window.parent.postMessage({ pluginMessage: { // TODO: 返回获取的数据} }, '*') } }</code>

這是Widget到iFrame通信的通用模板。讓我們用它從服務器獲取數據:

 <code>window.onmessage = async (event) => { if (event.data.pluginMessage.type === 'networkRequest') { // 获取从0到100的随机数const randomPage = Math.round(Math.random() * 100) // 从Design Quotes API获取随机报价const res = await fetch(`https://quotesondesign.com/wp-json/wp/v2/posts/?orderby=rand&per_page=1&page=${randomPage}&_fields=title,yoast_head_json`) const data = await res.json() // 从响应中提取作者姓名和报价内容const authorName = data[0].title.rendered const quoteContent = data[0].yoast_head_json.og_description window.parent.postMessage({ pluginMessage: { authorName, quoteContent } }, '*') } }</code>

為了保持簡單明了,我們省略了錯誤處理。讓我們回到小部件代碼中,看看我們如何訪問<iframe></iframe>中定義的函數:

 <code>function fetchData() { return new Promise<void> (resolve => { figma.showUI(__html__, {visible: false}) figma.ui.postMessage({type: 'networkRequest'}) figma.ui.onmessage = async ({authorName, quoteContent}) => { setAuthor(authorName) setQuote(quoteContent) resolve() } }) }</void></code>

如你所見,我們首先告訴Figma公開訪問我們隱藏的<iframe></iframe>並觸發名為“networkRequest”的事件。我們通過檢查event.data.pluginMessage.type === 'networkRequest'來處理ui.html文件中的此事件,然後將數據發布回小部件。

但是現在還沒有發生任何事情……我們仍然沒有調用fetchData()函數。如果我們直接在組件函數中調用它,則控制台中會出現以下錯誤:

<code>在小部件渲染期间无法使用showUI。</code>

Figma告訴我們不要直接在函數體中調用showUI ……那麼我們應該把它放在哪裡呢?答案是一個新的鉤子和一個新的函數: useEffectwaitForTask 。如果你是一位React開發人員,你可能已經熟悉useEffect了,但我們將在這裡使用它來在小部件組件掛載時從服務器獲取數據。

 <code>const { useEffect, waitForTask } = widget; function QuotesWidget() { useEffect(() => { waitForTask(fetchData()); }); }</code>

但這會導致另一個“錯誤”,我們的Widget將永遠使用新的報價不斷重新渲染。發生這種情況是因為useEffect根據定義,每當Widget的狀態發生更改時,或者當我們調用fetchData時,它都會再次觸發。雖然有一種技術可以在React中只調用一次useEffect ,但它不適用於Figma的實現。來自Figma文檔:

由於小部件的運行方式,useEffect應該處理使用相同狀態多次被調用。

幸運的是,我們可以利用一個簡單的解決方法,只在組件第一次掛載時調用一次useEffect ,方法是檢查狀態的值是否仍然為空:

 <code>function QuotesWidget() { useEffect(() => { if (!author.length & !quote.length) { waitForTask(fetchData()); } }); }</code>

你可能會遇到一個可怕的“內存訪問越界”錯誤。這在插件和小部件開發中非常常見。只需重新啟動Figma,它就不會再出現了。

你可能已經註意到,有時報價文本包含奇怪的字符。

這些是Unicode字符,我們必須在代碼中正確格式化它們:

 <code>window.onmessage = async (event) => { // ... const quoteContent = decodeEntities(data[0].yoast_head_json.og_description); }; //<https:> var decodeEntities = (function () { // this prevents any overhead from creating the object each time var element = document.createElement("div"); function decodeHTMLEntities(str) { if (str && typeof str === "string") { // strip script/html tags str = str.replace(/]*>([\\\\S\\\\s]*?)/gim, ""); str = str.replace(/]|"[^"]*"|'[^']*')*>/gim, ""); element.innerHTML = str; str = element.textContent; element.textContent = ""; } return str; } return decodeHTMLEntities; })();</https:></code>

瞧,我們的Widget每次添加到設計畫板時都會獲取一個全新的設計報價。

向我們的Widget添加屬性菜單

雖然我們的Widget在實例化時會獲取新的報價,但如果我們能夠再次執行此過程而無需刪除它,則會更實用。本節將簡短介紹,因為解決方案非常出色。使用屬性菜單,我們可以通過一次調用usePropertyMenu鉤子來向我們的Widget添加交互性。

 <code>const { usePropertyMenu } = widget; function QuotesWidget() { usePropertyMenu( [ { itemType: "action", propertyName: "generate", tooltip: "Generate", icon: ` <svg fill="none" height="15" viewbox="0 0 22 15" width="22" xmlns="<http://www.w3.org/2000/svg>"></svg></code> `,
      },
    ],
    () => fetchData()
  );
}

使用一個簡單的鉤子,我們就可以創建一個按鈕,當選中我們的Widget時,該按鈕會出現在我們的Widget附近。這是我們需要添加的最後一個部分才能完成這個項目。

將我們的Widget發佈到公共

如果沒有人使用它,那麼構建Widget就沒有多大用處。雖然Figma允許組織啟動用於內部使用的私有Widget,但將這些小程序發佈到世界各地更為常見。

Figma有一個細緻的小部件審查流程,可能需要5到10個工作日。雖然我們一起構建的設計報價小部件已經位於小部件庫中,但我仍然會演示它是如何到達那裡的。請不要嘗試再次發布此小部件,因為這只會導致刪除。但是,如果你對其進行了一些重大更改,請繼續與社區分享你自己的小部件!

首先單擊小部件菜單(Shift I),然後切換到開發選項卡以查看我們的Widget。單擊三點菜單並按發布

Figma會提示你輸入有關你的Widget的一些詳細信息,例如標題、描述和一些標籤。我們還需要一個128×128的圖標圖像和一個1920×960的橫幅圖像。

導入所有這些資源後,我們仍然需要Widget的屏幕截圖。關閉發布模式(別擔心,你不會丟失數據),然後右鍵單擊Widget以顯示一個有趣的上下文菜單。找到複製/粘貼為類別並選擇複製為PNG

完成此操作後,讓我們回到發布模式並將Widget的屏幕截圖粘貼進去:

向下滾動並最終發布你的模式。慶祝! ?

Figma會在幾天后與你聯繫,告知你的模式審查狀態。如果被拒絕,你將有機會進行更改並再次提交。

結論

我們剛剛從頭開始構建了一個Figma小部件!這裡有很多內容沒有涵蓋,例如單擊事件、輸入表單等等。你可以在這個GitHub存儲庫中深入了解Widget的完整源代碼。

對於那些渴望將他們的Figma技能提升到更高水平的人,我建議探索Widgets社區,並使用你感興趣的內容作為靈感。繼續構建更多的小部件,繼續磨練你的React技能,在你意識到之前,你將教我如何做到這一切。

更多資源

在製作這個Widget時,我不得不參考大量的文檔。我認為我會分享我發現最有幫助的內容。

構建更多小部件:

  • 構建小部件的最佳實踐
  • 官方Figma小部件示例,包含代碼

更深入地學習小部件:

  • 所有小部件鉤子
  • 所有小部件組件
  • 小部件在幕後如何運行

小部件與插件

  • 小部件與插件
  • Figma插件簡介
  • 插件在幕後如何運行

以上是構建互動無花果小部件的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
什麼是CSS網格?什麼是CSS網格?Apr 30, 2025 pm 03:21 PM

CSS網格是創建複雜,響應式Web佈局的強大工具。它簡化了設計,提高可訪問性並提供了比舊方法更多的控制權。

什麼是CSS Flexbox?什麼是CSS Flexbox?Apr 30, 2025 pm 03:20 PM

文章討論了CSS FlexBox,這是一種佈局方法,用於有效地對齊和分佈響應設計中的空間。它說明了FlexBox用法,將其與CSS網格進行了比較,並詳細瀏覽了瀏覽器支持。

我們如何使用CSS使網站迅速響應?我們如何使用CSS使網站迅速響應?Apr 30, 2025 pm 03:19 PM

本文討論了使用CSS創建響應網站的技術,包括視口元標籤,靈活的網格,流體媒體,媒體查詢和相對單元。它還涵蓋了使用CSS網格和Flexbox一起使用,並推薦CSS框架

CSS盒裝屬性有什麼作用?CSS盒裝屬性有什麼作用?Apr 30, 2025 pm 03:18 PM

本文討論了CSS盒裝屬性,該屬性控制了元素維度的計算方式。它解釋了諸如Content-Box,Border-Box和Padding-Box之類的值,以及它們對佈局設計和形式對齊的影響。

我們如何使用CSS動畫?我們如何使用CSS動畫?Apr 30, 2025 pm 03:17 PM

文章討論使用CSS,關鍵屬性並與JavaScript結合創建動畫。主要問題是瀏覽器兼容性。

我們可以使用CSS向我們的項目添加3D轉換嗎?我們可以使用CSS向我們的項目添加3D轉換嗎?Apr 30, 2025 pm 03:16 PM

文章討論了Web項目的3D轉換,關鍵屬性,瀏覽器兼容性和性能注意事項的討論。 (角色計數:159)

我們如何在CSS中添加梯度?我們如何在CSS中添加梯度?Apr 30, 2025 pm 03:15 PM

文章討論了使用CSS梯度(線性,徑向,重複)來增強網站視覺效果,添加深度,焦點和現代美學。

CSS中的偽元素是什麼?CSS中的偽元素是什麼?Apr 30, 2025 pm 03:14 PM

文章討論了CSS中的偽元素,它們在增強HTML樣式方面的使用以及與偽級的差異。提供實用的例子。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。