从零开发设计稿转代码插件(一)

从今天开始开个新的专栏,从零开始开发一个 figma design to code 插件。

阅读并且实操完本系列文章,你会

  • 对 figma 设计工具有深入的理解,甚至可能会比你们公司 ui 同学理解的还要深刻
  • 熟悉代码生成原理,自己也能够写出一个效果不错的插件
  • 对页面布局有了新的认知(比如不用 margin),大大提升你写 html 的速度和还原度

开发 figma 插件需要使用 figma 客户端。我们打开 figma 客户端,新建设计文件,然后点击顶部栏的 Plugins -> Development -> New Plugin

然后选择 Figma design,输入插件名字,点击确定

选择 Custom UI

将代码保存到本地,用你的编辑器打开,然后跟随readme 的指引运行项目

css 复制代码
npm install -g typescript
npm install --save-dev @figma/plugin-typings
npm run watch

这样项目就跑起来了

之后打开 figma 客户端运行你的插件

点击 create 之后会生成五个黄色的矩形

看下代码目录结构,我就说几个重要

manifest.json是插件描述文件,里面包含插件的 name,id,ui和 mian,ui 就是弹窗里面展示的 ui。main 是运行在沙盒环境的代码,里面应该是你主要的业务逻辑。他们通过 postMessage 通信

json 复制代码
{
  "name": "my-first-plugin",
  "id": "1482330158480649678",
  "api": "1.0.0",
  "main": "code.js",
  "capabilities": [],
  "enableProposedApi": false,
  "documentAccess": "dynamic-page",
  "editorType": [
    "figma"
  ],
  "ui": "ui.html",
  "networkAccess": {
    "allowedDomains": [
      "none"
    ]
  }
}

ui.html

html 复制代码
<h2>Rectangle Creator</h2>
<p>Count: <input id="count" type="number" value="5"></p>
<button id="create">Create</button>
<button id="cancel">Cancel</button>
<script>

document.getElementById('create').onclick = () => {
  const textbox = document.getElementById('count');
  const count = parseInt(textbox.value, 10);
  parent.postMessage({ pluginMessage: { type: 'create-shapes', count } }, '*')
}

document.getElementById('cancel').onclick = () => {
  parent.postMessage({ pluginMessage: { type: 'cancel' } }, '*')
}

</script>

code.ts

ts 复制代码
figma.showUI(__html__);
figma.ui.onmessage =  (msg: {type: string, count: number}) => {
  if (msg.type === 'create-shapes') {
    const numberOfRectangles = msg.count;

    const nodes: SceneNode[] = [];
    for (let i = 0; i < numberOfRectangles; i++) {
      const rect = figma.createRectangle();
      rect.x = i * 150;
      rect.fills = [{ type: 'SOLID', color: { r: 1, g: 0.5, b: 0 } }];
      figma.currentPage.appendChild(rect);
      nodes.push(rect);
    }
    figma.currentPage.selection = nodes;
    figma.viewport.scrollAndZoomIntoView(nodes);
  }
  figma.closePlugin();
};

看完代码现在就产生了一个问题,就是他们提供的代码实在是太古老了,过于刀耕火种了🔪⛏️🔥🌱,所以我来基于 react、vite 、ts 改造一下。

大概分享一下我的改造过程

  1. 在根目录直接npm create vite@latest

  2. 再给文件移出来🐶

  3. 创建 vite.ui.config.ts,用于build react 代码,使用viteSingleFile插件把代码都打包到 html 中

  4. 创建 vite.plugin.config.ts 用于 build 核心代码

  5. 修改 watch 命令

    json 复制代码
    "watch": "run-p watch:*",
    "watch:ui": "npm run build:ui -- --watch",
    "watch:plugin": "npm run build:plugin -- --watch",
    "build:ui": "vite build --config vite.ui.config.ts",
    "build:plugin": "vite build --config vite.plugin.config.ts"Ï

然后这个模板就完成了🎉

我给放到了 github 上,懒得自己折腾的小伙伴可以直接 clone 到本地直接跑 github.com/alpacachen/...

(readme 全是 ai 写的)

bash 复制代码
figma-react-template/
├── dist/                   # 构建输出
├── src/
│   ├── plugin/             # 插件代码(在 Figma 中运行)
│   │   └── index.ts        # 主插件代码
│   └── ui/                 # UI 代码(在 WebView 中运行)
│       ├── app/
│       │   ├── app.tsx     # 主 React 组件
│       │   ├── app.css     # 样式
│       │   └── main.tsx    # React 入口点
│       ├── index.html      # HTML 模板
│       └── vite-env.d.ts   # Vite 环境类型
├── .gitignore
├── eslint.config.js        # ESLint 配置
├── manifest.json           # Figma 插件清单
├── package.json            # 项目依赖和脚本
├── tsconfig.json           # TypeScript 配置
├── tsconfig.app.json       # 应用的 TypeScript 配置
├── tsconfig.node.json      # Node 的 TypeScript 配置
├── vite.plugin.config.ts   # 插件的 Vite 配置
└── vite.ui.config.ts       # UI 的 Vite 配置

现在前期准备弄完了,接下来真正开始

首先监听选中事件,可以让 ui.html知道选中了哪个图层,这样后面才好获取信息

ts 复制代码
// plugin.ts
figma.showUI(__html__);

figma.on('selectionchange', () => {
  const selection = figma.currentPage.selection;
  if (selection.length == 1) {
    const selectedNode = selection[0];
    // 将选中图层的坐标大小和类型全部发送给 ui
    const { x, y, width, height, type } = selectedNode;
    figma.ui.postMessage({
      x,
      y,
      width,
      height,
      type
    });
  }
});
ts 复制代码
// 在 app.ts中监听 message,然后打印出来
useEffect(() => {
    window.addEventListener('message', (event) => {
        console.log(event.data.pluginMessage);
   });
}, []);

然后测试一下

这样代码生成第一大步就完成了,因为代码生成说白了就是规则转化,把 figma 的字段转成 css 的属性。

本文到此结束,后面的章节会重点在 ui 界面的制作上,欢迎关注

相关推荐
老前端的功夫7 小时前
Vue 3 性能深度解析:从架构革新到运行时的全面优化
javascript·vue.js·架构
天天扭码7 小时前
如何实现流式输出?一篇文章手把手教你!
前端·aigc·ai编程
前端 贾公子7 小时前
vue移动端适配方案 === postcss-px-to-viewport
前端·javascript·html
GISer_Jing8 小时前
AI营销增长:4大核心能力+前端落地指南
前端·javascript·人工智能
明远湖之鱼9 小时前
一种基于 Service Worker 的渐进式渲染方案的基本原理
前端
前端小端长9 小时前
Vue 中 keep-alive 组件的原理与实践详解
前端·vue.js·spring
FeelTouch Labs9 小时前
Nginx核心架构设计
运维·前端·nginx
雪球工程师团队10 小时前
别再“苦力”写后台,Spec Coding “跑” 起来
前端·ai编程
m0_4711996310 小时前
【场景】前端怎么解决离线收银、数据同步异常等场景问题
前端·javascript