目錄
Figma小部件開啟無限可能
我們需要什麼
設計小部件
為我們的Widget創建佈局
實時預覽我們的Widget
樣式設置小部件
向Widget添加狀態
從網絡獲取數據
向我們的Widget添加屬性菜單
將我們的Widget發佈到公共
結論
更多資源
構建更多小部件:
更深入地學習小部件:
小部件與插件
首頁 web前端 css教學 構建互動無花果小部件

構建互動無花果小部件

Mar 11, 2025 am 09:37 AM

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

熱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

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1656
14
CakePHP 教程
1415
52
Laravel 教程
1309
25
PHP教程
1257
29
C# 教程
1229
24
Google字體可變字體 Google字體可變字體 Apr 09, 2025 am 10:42 AM

我看到Google字體推出了新設計(Tweet)。與上一次大型重新設計相比,這感覺更加迭代。我幾乎無法分辨出區別

如何使用HTML,CSS和JavaScript創建動畫倒計時計時器 如何使用HTML,CSS和JavaScript創建動畫倒計時計時器 Apr 11, 2025 am 11:29 AM

您是否曾經在項目上需要一個倒計時計時器?對於這樣的東西,可以自然訪問插件,但實際上更多

HTML數據屬性指南 HTML數據屬性指南 Apr 11, 2025 am 11:50 AM

您想了解的有關HTML,CSS和JavaScript中數據屬性的所有信息。

如何通過CSS選擇第一個類名為item的子元素? 如何通過CSS選擇第一個類名為item的子元素? Apr 05, 2025 pm 11:24 PM

在元素個數不固定的情況下如何通過CSS選擇第一個指定類名的子元素在處理HTML結構時,常常會遇到元素個數不�...

為什麼Flex佈局中的紫色斜線區域會被誤認為是'溢出空間”? 為什麼Flex佈局中的紫色斜線區域會被誤認為是'溢出空間”? Apr 05, 2025 pm 05:51 PM

關於Flex佈局中紫色斜線區域的疑問在使用Flex佈局時,你可能會遇到一些令人困惑的現象,比如在開發者工具(d...

使Sass更快的概念證明 使Sass更快的概念證明 Apr 16, 2025 am 10:38 AM

在一個新項目開始時,Sass彙編發生在眼睛的眨眼中。感覺很棒,尤其是當它與browsersync配對時,它重新加載

我們如何創建一個在SVG中生成格子呢模式的靜態站點 我們如何創建一個在SVG中生成格子呢模式的靜態站點 Apr 09, 2025 am 11:29 AM

格子呢是一塊圖案布,通常與蘇格蘭有關,尤其是他們時尚的蘇格蘭語。在Tar​​tanify.com上,我們收集了5,000多個格子呢

在前端開發中,如何使用CSS和JavaScript實現類似Windows 10設置界面的探照燈效果? 在前端開發中,如何使用CSS和JavaScript實現類似Windows 10設置界面的探照燈效果? Apr 05, 2025 pm 10:21 PM

在前端開發中如何實現類似Windows...

See all articles