中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么使用Vue3開發Fimga插件

發布時間:2022-04-11 13:38:31 來源:億速云 閱讀:274 作者:iii 欄目:編程語言

本篇內容介紹了“怎么使用Vue3開發Fimga插件”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

怎么使用Vue3開發Fimga插件

用 Vue 3 開發 Figma 插件

Figma 是一款當下流行的設計工具,越來越多的設計團隊開始從 Sketch 轉向 Figma。Figma 最大的特點是使用Web技術開發,實現了完全的跨平臺。 Figma 插件也是使用 Web 技術開發,只要會  htmljscss 就能動手寫一個 Figma 插件。

Figma 插件原理

Figma 架構簡介

介紹 Fimga 插件之前,我們先來了解一下 Fimga 的技術架構。

Figma 整體是用 React 開發的,核心的畫布區是一塊 canvas ,使用WebGL來渲染。并且畫布引擎部分使用的是WebAssembly,這就是 Figma 能夠如此流暢的原因。桌面端的Figma App 使用了 Electron——一個使用Web技術開發桌面應用的框架。Electron 類似于一個瀏覽器,內部運行的其實還是一個Web應用。

Figma 插件原理

在Web端開發一套安全、可靠的插件系統, iframe 無疑是最直接的方案。 iframe 是標準的W3C規范,在瀏覽器上已經經過多年應用,它的特點是:

  • 安全,天然沙箱隔離環境,iframe內頁面無法操作主框架;

  • 可靠,兼容性非常好,且經過了多年市場的檢驗;

但是它也有明顯的缺點:與主框架通信只能通過 postMessage(STRING) 的方式,通信效率非常低。如果要在插件里操作一個畫布元素,首先要將元素的節點信息從主框架拷貝到 iframe 中,然后在  iframe 中操作完再更新節點信息給主框架。這涉及到大量通信,而且對于復雜的設計稿節點信息是非常巨大的,可能超過通信的限制。

為了保證操作畫布的能力,必須回到主線程。插件在主線程運行的問題主要在于安全性上,于是Figma的開發人員在主線程實現了一個 js 沙箱環境,使用了Realm API。沙箱中只能運行純粹的 js 代碼和Figma提供的API,無法訪問瀏覽器API(例如網絡、存儲等),這樣就保證了安全性。

怎么使用Vue3開發Fimga插件

感興趣的同學推薦閱讀官方團隊寫的《How to build a plugin system on the web and also sleep well at night》,詳細介紹了 Figma 插件方案的選擇過程,讀來獲益良多。

經過綜合考慮,Figma 將插件分成兩個部分:插件UI運行在 iframe 中,操作畫布的代碼運行在主線程的隔離沙箱中。UI線程和主線程通過  postMessage 通信。

插件配置文件 manifest.json 中分別配置 main 字段指向加載到主線程的 js 文件, ui 字段配置加載到 iframe 中的 html 文件。打開插件時,主線程調用 figma.showUI() 方法加載 iframe

寫一個最簡單的 Figma 插件

為了了解插件的運行過程,我們先寫一個最簡單的 Figma 插件。功能很簡單:可以加減正方形色塊。

安裝Figma桌面端

首先要下載并安裝好 Figma 桌面端。

編寫插件的啟動文件 manifest.json

新建一個代碼工程,在根目錄中新建 manifest.json 文件,內容如下:

{
  "name": "simple-demo",
  "api": "1.0.0",
  "main": "main.js",
  "ui": "index.html",
  "editorType": [
    "figjam",
    "figma"
  ]
}
編寫UI代碼

根目錄新建 index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Demo</title>
  <style>

    h2 {
      text-align: center;
    }
    p {
      color: red;
    }

    .buttons {
      margin-top: 20px;
      text-align: center;
    }

    .buttons button {
      width: 40px;
    }

    #block-num {
      font-size: 20px;
    }

  </style>
 
</head>
<body>
  <h2>Figma 插件 Demo</h2>
  <p>當前色塊數量:<span id="block-num">0</span></p>
  <div>
    <button id="btn-add" onclick="addBlock()">+</button>
    <button id="btn-sub" onclick="subBlock()">-</button>
  </div>

  <script>
    console.log('ui code runs!');
    var blockNumEle = document.getElementById('block-num');
    function addBlock() {
      console.log('add');
      var num = +blockNumEle.innerText;
      num += 1;
      blockNumEle.innerText = num;
    }

    function subBlock() {
      console.log('substract');
      var num = +blockNumEle.innerText;
      if (num === 0) return;
      num -= 1;
      blockNumEle.innerText = num;
    }
  </script>
</body>
</html>
編輯main js 代碼

根目錄新建 main.js ,內容如下:

console.log('from code 2');
figma.showUI(__html__, {
  width: 400,
  height: 400,
});
啟動插件

Figma桌面APP,畫布任意地方右鍵打開菜單, Plugins -> Development -> Import plugin from manifest... ,選擇前面創建的 manifest.json 文件路徑,即可成功導入插件。 然后通過右鍵, Plugins -> Development -> simple-demo (插件名),就可以打開插件。

怎么使用Vue3開發Fimga插件

測試點擊按鈕,功能正常。只不過頁面上還未出現色塊(別著急)。 通過 Plugins -> Development -> Open console  可以打開調試控制臺。可以看到我們打印的日志。

操作畫布

前面講了,畫布代碼是運行在主線程的,為了執行效率,插件要操作畫布內容也只能在主線程執行,即在 main.js 中。 main.js 中暴露了頂級對象 figma ,封裝了用來操作畫布的一系列API,具體可以去看官網文檔。我們用 figma.createRectangle() 來創建一個矩形。主線程需要通過 figma.ui.onmessage 監聽來自UI線程的事件,從而做出響應。修改后的 main.js 代碼如下:

console.log('figma plugin code runs!')

figma.showUI(__html__, {
  width: 400,
  height: 400,
});

const nodes = [];

figma.ui.onmessage = (msg) => {=
  if (msg.type === "add-block") {
    const rect = figma.createRectangle();
    rect.x = nodes.length * 150;
    rect.fills = [{ type: "SOLID", color: { r: 1, g: 0.5, b: 0 } }];
    figma.currentPage.appendChild(rect);
    nodes.push(rect);
  } else if (msg.type === "sub-block") {
    const rect = nodes.pop();
    if (rect) {
      rect.remove();
    }
  }
  figma.viewport.scrollAndZoomIntoView(nodes);
};

同時要修改  index.html 中的部分代碼,通過 parent.postMessage 給主線程發送事件:

function addBlock() {
  console.log('add');
  var num = +blockNumEle.innerText;
  num += 1;
  blockNumEle.innerText = num;
  parent.postMessage({ pluginMessage: { type: 'add-block' } }, '*')
}

function subBlock() {
  console.log('substract');
  var num = +blockNumEle.innerText;
  if (num === 0) return;
  num -= 1;
  blockNumEle.innerText = num;
  parent.postMessage({ pluginMessage: { type: 'sub-block' } }, '*')
}

重新啟動插件,再試驗一下,發現已經可以成功加減色塊了。

怎么使用Vue3開發Fimga插件

使用 Vue 3 開發 Figma 插件

通過前面的例子,我們已經清楚 Figma 插件的運行原理。但是用這種“原生”的 jshtml 來編寫代碼非常低效的。我們完全可以用最新的Web技術來編寫代碼,只要打包產物包括一個運行在主框架的 js 文件和一個給 iframe 運行的 html 文件即可。我決定嘗試使用  Vue 3 來開發插件。(學習視頻分享:vuejs教程)

關于 Vue 3 就不多做介紹了,懂的都懂,不懂的看到這里可以先去學習一下再來。這里的重點不在于用什么框架(改成用vue 2、react過程也差不多),而在于構建工具。

Vite 啟動一個新項目

Vite 是Vue的作者開發的新一代構建工具,也是 Vue 3推薦的構建工具。 我們先建一個 Vue  +  TypeScript 的模板項目。

npm init vite@latest figma-plugin-vue3 --template vue-ts
cd figma-plugin-vue3
npm install
npm run dev

然后通過瀏覽器打開 http://localhost:3000 就能看到頁面。

移植上述demo代碼

我們把前面的插件demo移植到 Vue 3 中。 src/App.vue 代碼修改如下:

<script setup>
import { ref } from 'vue';

const num = ref(0);

console.log('ui code runs!');

function addBlock() {
  console.log('add');
  num.value += 1;
  parent.postMessage({ pluginMessage: { type: 'add-block' } }, '*')
}

function subBlock() {
  console.log('substract');
  if (num .value=== 0) return;
  num.value -= 1;
  parent.postMessage({ pluginMessage: { type: 'sub-block' } }, '*')
}
</script>

<template>
  <h2>Figma 插件 Demo</h2>
  <p>當前色塊數量:<span id="block-num">{{ num }}</span></p>
  <div>
    <button id="btn-add" @click="addBlock">+</button>
    <button id="btn-sub" @click="subBlock">-</button>
  </div>
</template>

<style scoped>
h2 {
  text-align: center;
}
p {
  color: red;
}

.buttons {
  margin-top: 20px;
  text-align: center;
}

.buttons button {
  width: 40px;
}

#block-num {
  font-size: 20px;
}
</style>

我們在 src/worker 目錄存放運行在主線程沙箱中的js代碼。新建 src/worker/code.ts ,內容如下:

console.log('figma plugin code runs!')

figma.showUI(__html__, {
  width: 400,
  height: 400,
});

const nodes: RectangleNode[] = [];

figma.ui.onmessage = (msg) => {
  
  if (msg.type === "add-block") {
    const rect = figma.createRectangle();
    rect.x = nodes.length * 150;
    rect.fills = [{ type: "SOLID", color: { r: 1, g: 0.5, b: 0 } }];
    figma.currentPage.appendChild(rect);
    nodes.push(rect);
  } else if (msg.type === "sub-block") {
    const rect = nodes.pop();
    if (rect) {
      rect.remove();
    }
  }

  figma.viewport.scrollAndZoomIntoView(nodes);

};

上述代碼中缺少 figma 的 ts 類型聲明,所以我們需要安裝一下。

npm i -D @figma/plugin-typings

修改 tsconfig.json ,添加 typeRoots ,這樣 ts 代碼就不會報錯了。同時也要加上 "skipLibCheck": true ,解決類型聲明沖突問題。

{
  "compilerOptions": {
    // ...
"skipLibCheck": true,
    "typeRoots": [
      "./node_modules/@types",
      "./node_modules/@figma"
    ]
  },
}

修改構建配置

Figma 插件需要的構建產物有:

  • manifest.json  文件作為插件配置

  • index.html 作為UI代碼

  • code.js 作為主線程js代碼

在 public 目錄中添加 manifest.json 文件

public 目錄中的文件都會負責到構建產物 dist 目錄下。

{
  "name": "figma-plugin-vue3",
  "api": "1.0.0",
  "main": "code.js",
  "ui": "index.html",
  "editorType": [
    "figjam",
    "figma"
  ]
}
vite.config.ts  中增加構建入口

默認情況下 vite 會用 index.html 作為構建入口,里面用到的資源會被打包構建。我們還需要一個入口,用來構建主線程 js 代碼。

執行  npm i -D @types/node ,安裝  Node.js  的類型聲明,以便在 ts 中使用  Node.js  API。 vite.config.ts  的  build.rollupOptions  中增加  input 。默認情況下輸出產物會帶上文件 hash ,所以也要修改 output 配置:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  build: {
    sourcemap: 'inline',
    rollupOptions: {
      input:{
            main: resolve(__dirname, 'index.html'),
            code: resolve(__dirname, 'src/worker/code.ts'),
          },
      output: {
        entryFileNames: '[name].js',
      },
    },
  },
})
運行構建

執行 npm run builddist 目錄會有構建產物。然后我們按照前面的步驟,將  dist  目錄添加為 Figma 插件。 Plugins -> Development -> Import plugin from manifest... ,選擇 dist/manifest.json 文件路徑。

啟動插件......怎么插件里一片空白?好在 Figma 里面有 devtools 調試工具,我們打開瞧一瞧。

怎么使用Vue3開發Fimga插件

可以看到,我們的 index.html 已經成功加載,但是 js 代碼沒加載所以頁面空白。js、css 等資源是通過相對路徑引用的,而我們的 iframe 中的 src 是一個 base64 格式內容,在尋找 js 資源的時候因為沒有域名,所以找不到資源。

解決辦法也很簡單,我們給資源加上域名,然后本地起一個靜態資源服務器就行了。修改  vite.config.ts ,加上 base: 'http://127.0.0.1:3000'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  base: 'http://127.0.0.1:3000',
  build: {
    sourcemap: 'inline',
    rollupOptions: {
      input: {
        main: resolve(__dirname, 'index.html'),
        code: resolve(__dirname, 'src/worker/code.ts'),
      },
      output: {
        entryFileNames: '[name].js',
      },
    },
  },
  preview: {
    port: 3000,
  },
})

重新構建代碼 npm run build 。然后啟動靜態資源服務器 npm run preview 。通過瀏覽器訪問 http://localhost:3000/ 可以看到內容。

然后重新打開 Figma 插件看看。果然,插件已經正常了!

怎么使用Vue3開發Fimga插件

Figma 加載插件只需要  index.html  和  code.js ,其他資源都可以通過網絡加載。這意味著我們可以將 js、css 資源放在服務端,實現插件的熱更?不知道發布插件的時候會不會有限制,這個我還沒試過。

開發模式

我們已經能成功通過 Vue 3 來構建 Figma 插件了,但是我不想每次修改代碼都要構建一遍,我們需要能夠自動構建代碼的開發模式。

vite 自動的 dev 模式是啟動了一個服務,沒有構建產物(而且沒有類似webpack里面的  writeToDisk 配置),所以無法使用。

watch 模式

vite 的 build 命令有watch模式,可以監聽文件改動然后自動執行  build 。我們只需要修改 package.jsonscripts  里新增  "watch": "vite build --watch"

npm run watch

# 同時要在另一個終端里啟動靜態文件服務
npm run preview

這種方式雖然修改代碼后會自動編譯,但是每次還是要關閉插件并重新打開才能看到更新。這樣寫UI還是太低效了,能不能在插件里實現  HMR  (模塊熱重載)功能呢?

dev 模式

vite dev 的問題在于沒有構建產物。 code.js  是運行在 Fimga 主線程沙箱中的,這部分是無法熱重載的,所以可以利用 vite build --watch 實現來編譯。需要熱重載的是 index.html  以及相應的 js 、css 資源。 先來看一下 npm run dev 模式下的 html 資源有什么內容:

怎么使用Vue3開發Fimga插件

理論上來說,我們只需要把這個 html 手動寫入到  dist  目錄就行,熱重載的時候 html 文件不需要修改。直接寫入的話會遇到資源是相對路徑的問題,所以要么把資源路徑都加上域名( http://localhost:3000 ),或者使用 <base>標簽。

手動生成 html 文件

對比上面的 html 代碼和根目錄的 index.html  文件,發現只是增加了一個 <script type="module" src="/@vite/client"></script> 。所以我們可以自己解析  index.html ,然后插入相應這個標簽,以及一個  <base> 標簽。解析 HTML 我們用  jsdom  。

const JSDOM = require('jsdom');
const fs = require('fs');

// 生成 html 文件
function genIndexHtml(sourceHTMLPath, targetHTMLPath) {
  const htmlContent = fs.readFileSync(sourceHTMLPath, 'utf-8');
  const dom = new JSDOM(htmlContent);
  const { document } = dom.window;
  
  const script = document.createElement('script');
  script.setAttribute('type', 'module');
  script.setAttribute('src', '/@vite/client');
  dom.window.document.head.insertBefore(script, document.head.firstChild);
  
  const base = document.createElement('base');
  base.setAttribute('href', 'http://127.0.0.1:3000/');
  dom.window.document.head.insertBefore(base, document.head.firstChild);

  const result = dom.serialize();
  fs.writeFileSync(targetHTMLPath, result);
}

同時 vite 提供了 JavaScript API,所以我們可以代碼組織起來,寫一個 js 腳本來啟動開發模式。新建文件 scripts/dev.js ,完整內容如下:

const { JSDOM } = require('jsdom');
const fs = require('fs');
const path = require('path');
const vite = require('vite');

const rootDir = path.resolve(__dirname, '../');

function dev() {
  const htmlPath = path.resolve(rootDir, 'index.html');
  const targetHTMLPath = path.resolve(rootDir, 'dist/index.html');
  genIndexHtml(htmlPath, targetHTMLPath);

  buildMainCode();

  startDevServer();
}

// 生成 html 文件
function genIndexHtml(sourceHTMLPath, targetHTMLPath) {
  const htmlContent = fs.readFileSync(sourceHTMLPath, 'utf-8');
  const dom = new JSDOM(htmlContent);
  const {
    document
  } = dom.window;

  const script = document.createElement('script');
  script.setAttribute('type', 'module');
  script.setAttribute('src', '/@vite/client');
  dom.window.document.head.insertBefore(script, document.head.firstChild);

  const base = document.createElement('base');
  base.setAttribute('href', 'http://127.0.0.1:3000/');
  dom.window.document.head.insertBefore(base, document.head.firstChild);

  const result = dom.serialize();
  fs.writeFileSync(targetHTMLPath, result);
}

// 構建 code.js 入口
async function buildMainCode() {
  const config = vite.defineConfig({
    configFile: false, // 關閉默認使用的配置文件
    build: {
      emptyOutDir: false, // 不要清空 dist 目錄
      lib: { // 使用庫模式構建
        entry: path.resolve(rootDir, 'src/worker/code.ts'),
        name: 'code',
        formats: ['es'],
        fileName: (format) => `code.js`,
      },
      sourcemap: 'inline',
      watch: {},
    },
  });
  return vite.build(config);
}

// 開啟 devServer
async function startDevServer() {
  const config = vite.defineConfig({
    configFile: path.resolve(rootDir, 'vite.config.ts'),
    root: rootDir,
    server: {
      hmr: {
        host: '127.0.0.1', // 必須加上這個,否則 HMR 會報錯
      },
      port: 3000,
    },
    build: {
      emptyOutDir: false, // 不要清空 dist 目錄
      watch: {}, // 使用 watch 模式
    }
  });
  const server = await vite.createServer(config);
  await server.listen()

  server.printUrls()
}

dev();

執行  node scripts/dev.js ,然后在 Figma 中重啟插件。試試修改一下 Vue 代碼,發現插件內容自動更新了!

怎么使用Vue3開發Fimga插件

最后在  package.json  中新建一個修改一下dev的內容為 "dev": "node scripts/dev.js" 就可以了。

通過請求來獲取 HTML

前面通過自己生產  index.html  的方式有很大的弊端:萬一后續 vite 更新后修改了默認 html 的內容,那我們的腳本也要跟著修改。有沒有更健壯的方式呢?我想到可以通過請求 devServer 來獲取 html 內容,然后寫入本地。話不多說,修改后代碼如下:

const { JSDOM } = require('jsdom');
const fs = require('fs');
const path = require('path');
const vite = require('vite');
const axios = require('axios');

const rootDir = path.resolve(__dirname, '../');

async function dev() {
  // const htmlPath = path.resolve(rootDir, 'index.html');
  const targetHTMLPath = path.resolve(rootDir, 'dist/index.html');

  await buildMainCode();

  await startDevServer();
  
  // 必須放到 startDevServer 后面執行
  await genIndexHtml(targetHTMLPath);
}

// 生成 html 文件
async function genIndexHtml(/* sourceHTMLPath,*/ targetHTMLPath) {
  const htmlContent = await getHTMLfromDevServer();
  const dom = new JSDOM(htmlContent);
  
  // ...

  const result = dom.serialize();
  fs.writeFileSync(targetHTMLPath, result);
}

// ...

// 通過請求 devServer 獲取HTML
async function getHTMLfromDevServer () {
  const rsp = await axios.get('http://localhost:3000/index.html');
  return rsp.data;
}

dev();

“怎么使用Vue3開發Fimga插件”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

vue
AI

菏泽市| 墨竹工卡县| 江都市| 龙泉市| 高密市| 陇川县| 上饶市| 台中市| 临沂市| 泽库县| 响水县| 达州市| 石楼县| 云南省| 东乌| 安义县| 达孜县| 彰武县| 宁阳县| 隆子县| 贺兰县| 和顺县| 佛学| 延边| 会宁县| 白银市| 青海省| 英吉沙县| 搜索| 贵州省| 泌阳县| 鄱阳县| 双辽市| 民和| 南投县| 洛南县| 孝感市| 东光县| 高州市| 盱眙县| 通江县|