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

从今天开始开个新的专栏,从零开始开发一个 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 界面的制作上,欢迎关注

相关推荐
百万蹄蹄向前冲10 分钟前
组建百万前端梦之队-计算机大学生竞赛发展蓝图
前端·vue.js·掘金社区
云隙阳光i23 分钟前
实现手机手势签字功能
前端·javascript·vue.js
imkaifan43 分钟前
vue2升级Vue3--native、对inheritAttrs作用做以解释、声明的prop属性和未声明prop的属性
前端·vue.js·native修饰符·inheritattrs作用·声明的prop属性·未声明prop的属性
觉醒法师1 小时前
HarmonyOS NEXT - 电商App实例三( 网络请求axios)
前端·华为·typescript·axios·harmonyos·ark-ts
Danta1 小时前
HTTP协议版本演进:从HTTP/0.9到HTTP/3的高分面试回答
前端·网络协议·面试
柠檬树^-^2 小时前
app.config.globalProperties
前端·javascript·vue.js
太阳花ˉ2 小时前
react(一):特点-基本使用-JSX语法
前端·react.js
赵大仁2 小时前
深入解析 React Diff 算法:原理、优化与实践
前端·react.js·前端框架
1024小神2 小时前
vue/react/vite前端项目打包的时候加上时间最简单版本,防止后端扯皮
前端·vue.js·react.js
起来改bug2 小时前
【pptx-preview】react+pptx预览
javascript·react.js·pptx