本文首发于本人博客:可可托海没有海,你能去那看我我高兴,不想点链接在这看也行,横竖内容彻底相同。


之前一向想开发个Figma插件练练手,但畏于开发文档,也不知道做什么,就没动手。

或许是由于最近一向在用Tailwind CSS,在前两周冒出个主意:

Figma中Frame现已支撑了很多类似CSS布局的设置,能否将这些设置转化成Tailwind输出呢?

在Figma上搜索了一下,有类似插件,但还没有专门用于导出Tailwind的插件。这便是个空白,能够搞。

翻了下Figma的开发文档,规划文档中元素的款式很容易拿到,只要把最根本结构搭起来,随便把什么款式获取到,转化成Tailwind到插件界面上,剩余的作业便是针对支撑的特点一个个调整输出就行了。

现在的问题便是,怎么把这个最根本的结构搭起来。

Introducing GPT-4

首要我测试了ChatGPT的作用,发现给出的回答并不可靠。

GPT-4会不会靠谱一点?

可我无法运用GPT-4,由于平常主要运用付费API,现已不想再买一个plus了。

还好有Poe,每天有一次时机运用GPT-4。这就意味着我必须谨慎构思prompt,不能糟蹋每天一次的时机。

然后我问出了给GPT-4的第一个问题:

我想写一个Figma plugin,功用是将选定的元素生成的CSS款式,转化成tailwind类名并显现在插件面板上。插件面板默许没有元素,只有一句提示语“请挑选元素”,在挑选元素后,其款式对应的tailwind类名将会显现在插件面板上。下方会有一个仿制按钮。假如再点击其他元素 ,持续生成新的tailwind类名。这个插件暂时只需求考虑宽、高和布景色彩,其他款式能够不必管。你需求告诉我code.ts里要怎么完成这个功用,给出完好代码,不能有typescript类型错误。

AI的回答

以下是它的回答:

首要,你需求有一个根本的Figma插件项目结构。你能够参考 Figma 插件开发文档 来了解怎么创建一个新的插件。 以下是一个简略的示例,演示了如安在 code.ts 中完成你所描述的功用。请留意,这个示例仅适用于处理宽度、高度和布景色彩,并将它们转化为 Tailwind CSS 类名。你或许需求依据你的需求进行调整。

// code.ts
const figmaUIApi = `
  <html>
  <style>
    body {
      font-family: -apple-system, [BlinkMacSystemFont](poe://www.poe.com/_api/key_phrase?phrase=BlinkMacSystemFont&prompt=Tell%20me%20more%20about%20BlinkMacSystemFont.), "Segoe UI", [Roboto](poe://www.poe.com/_api/key_phrase?phrase=Roboto&prompt=Tell%20me%20more%20about%20Roboto.), [Helvetica](poe://www.poe.com/_api/key_phrase?phrase=Helvetica&prompt=Tell%20me%20more%20about%20Helvetica.), [Arial](poe://www.poe.com/_api/key_phrase?phrase=Arial&prompt=Tell%20me%20more%20about%20Arial.), sans-serif;
      margin: 0;
      padding: 24px;
    }
    #info {
      margin-bottom: 16px;
    }
    button {
      background-color: #1669ef;
      border: none;
      border-radius: 4px;
      color: white;
      cursor: pointer;
      font-size: 14px;
      padding: 8px 16px;
    }
    button:hover {
      background-color: #0d4edb;
    }
  </style>
  <body>
    <div id="info">请挑选元素</div>
    <button id="copy">仿制</button>
    <script>
      [const info](poe://www.poe.com/_api/key_phrase?phrase=const%20info&prompt=Tell%20me%20more%20about%20const%20info.) = document.querySelector('#info');
      const copyButton = document.querySelector('#copy');
      copyButton.addEventListener('click', () => {
        const tailwindClasses = info.textContent;
        if (tailwindClasses) {
          navigator.clipboard.writeText(tailwindClasses);
        }
      });
      onmessage = (event) => {
        const tailwindClasses = event.data.pluginMessage;
        if (tailwindClasses) {
          info.textContent = tailwindClasses;
        } else {
          info.textContent = '请挑选元素';
        }
      };
    </script>
  </body>
  </html>
`;
figma.showUI(figmaUIApi, { width: 300, height: 150 });
function convertToTailwind(width: number, height: number, color: string): string {
  // 宽度和高度转化
  const widthClass = `w-${Math.round(width / 4)}`;
  const heightClass = `h-${Math.round(height / 4)}`;
  // 色彩转化
  const colorClass = `bg-${color.replace('#', '')}`;
  return `${widthClass} ${heightClass} ${colorClass}`;
}
figma.on("selectionchange", () => {
  const node = figma.currentPage.selection[0];
  if (node && node.type === "RECTANGLE") {
    const width = node.width;
    const height = node.height;
    const color = node.fills[0].color;
    const hexColor = `#${Math.round(color.r * 255).toString(16)}${Math.round(color.g * 255).toString(16)}${Math.round(color.b * 255).toString(16)}`;
    const tailwindClasses = convertToTailwind(width, height, hexColor);
    figma.ui.postMessage(tailwindClasses);
  } else {
    figma.ui.postMessage(null);
  }
});

留意,这个示例中的 figmaUIApi 代码是一个简略的 HTML 和 JavaScript 代码,用于创建插件的 UI。它接收从 code.ts 发送的音讯,并在接收到音讯时更新显现的 Tailwind 类名。

这个示例中的 convertToTailwind 函数将宽度、高度和色彩转化为相应的 Tailwind 类名。你能够依据需求扩展此函数以支撑更多的 CSS 特点。

请留意,这个示例仅适用于处理矩形节点。假如你需求支撑其他类型的节点,你能够依据需求调整代码。


这个代码其完成已能够运转起来了,仅仅会有一些bug。其实你更应该把AI当成Copilot,用它给你提供创意,就会是很好的东西。

那咱们就来分析一下这段代码。

界面

const figmaUIApi跟着的那一大坨便是插件的界面,<style>内的暂时不必管。

界面相关代码最重要的部分便是copyButton.addEventListeneronmessage

copyButton.addEventListener是给仿制按钮添加了一个监听函数,将info里的内容保存到tailwindClasses里,假如存在则向剪贴板写入;

onmessage的作用是判断是否有挑选元素,假如没有挑选,会显现一个提示案牍。

插件逻辑

figma.showUI是Figma的一个办法,用于召唤出插件的界面。

function convertToTailwind是AI为咱们生成的一个最简略的转化函数,比方下面这个:

const widthClass = `w-${Math.round(width / 4)}`;

它的作用是将元素的宽度获取到,除以4,四舍五入取整,在前面加一个前缀。

假如宽度是24,这儿就会输出w-6

当然Tailwind的宽度并不能这么简略的四舍五入,但咱们有了结构,细化就仅仅时间问题,并不存在什么难题。

剩余的色彩函数也是同理,并不能直接用,但你能够知道逻辑。

figma.on的作用是为指定事件注册一个回调函数,当这个事件发生的时分,执行该函数。

AI为咱们生成了一个在挑选元素发生变化时,针对矩形元素的一个处理:

figma.on("selectionchange", () => {
  const node = figma.currentPage.selection[0];
  if (node && node.type === "RECTANGLE") {
    const width = node.width;
    const height = node.height;
    const color = node.fills[0].color;
    const hexColor = `#${Math.round(color.r * 255).toString(16)}${Math.round(color.g * 255).toString(16)}${Math.round(color.b * 255).toString(16)}`;
    const tailwindClasses = convertToTailwind(width, height, hexColor);
    figma.ui.postMessage(tailwindClasses);
  } else {
    figma.ui.postMessage(null);
  }
});

当挑选了Figma元素时,该函数触发,假如节点类型为矩形,将特点提取出来,传入convertToTailwind处理函数,终究回来一串Tailwind类名字符串,然后将其显现到界面上。

其实中间还有一些小bug需求处理,我这儿就不说了。

增加功用

根本的结构现已打好,暂时也没有GPT-4的协助,剩余的只能靠自己和GPT-3.5了。

接下来的作业便是阅读Figma Plugin文档,找出支撑的特点,再考虑怎么转成对应的Tailwind类名。

比方关于文字类型:

export default function Text(node: SceneNode): string {
  const textNode = node as TextNode;
  let fontSize = 'text-base';
  let fontWeight = 'font-normal';
  let fontColor = 'text-black';
  const textAlign = ConvertTextAlign(textNode);
  if (textNode.fontSize !== figma.mixed) {
    fontSize = ConvertFontSize(textNode.fontSize);
  }
  if (textNode.fontWeight !== figma.mixed) {
    fontWeight = ConvertFontWeight(textNode.fontWeight);
  }
  const opacity = ConvertOpacity(textNode.opacity);
  if (textNode.fills !== figma.mixed) {
    if (textNode.fills[0].type === "SOLID") {
      fontColor = `text-${ConvertColors(textNode.fills[0].color)}`
    }
  }
  return `${textAlign} ${fontSize} ${fontWeight} ${opacity} ${fontColor}`;
}

先将文字的特点一个个提取出来,再分别传入对应的处理函数。

拿字号转化函数为例:

import getNumber from "./getNumber";
const Sizes = {
  'text-xs': 12,
  'text-sm': 14,
  'text-base': 16,
  'text-lg': 18,
  'text-xl': 20,
  'text-2xl': 24,
  'text-3xl': 30,
  'text-4xl': 36,
  'text-5xl': 48,
  'text-6xl': 60,
  'text-7xl': 72,
  'text-8xl': 96,
  'text-9xl': 128,
}
export default function ConvertFontSize(fontSize: number): string {
  const fontSizeClass = getNumber(fontSize, Sizes);
  return fontSizeClass;
}

这个函数收到字号后,会再调用一个函数,这个getNumber()的作用便是在第二个参数中寻觅与第一个参数最接近的名称。比方传入的字号是17,就会回来字符串text-base

剩余的处理逻辑也都类似,都是在一个预设的参数中找到与入参最接近的,回来类名。

当然也有单个比较费事的,比方色彩。如安在一堆预设色彩中找出与指定色彩最接近的那个呢?

关于色彩怎么进行对比仍是将来另起一篇介绍比较好。让咱们先持续。

竣工

接下来你需求持续增加宽度高度、圆角半径、透明度、padding甚至布局的转化,办法都差不多,额外提一下布局。

了解CSS的人肯定会发现,Autolayout的规划跟CSS中Flexbox布局很类似,align-itemsjustify-contentgap都能够找到对应。所以我也特地生成了布局相关的类名。

插件的终究作用便是这样,具体代码能够访问Github检查。

我用GPT-4指导我写了个Figma插件

体会插件

还能够搞些什么

整个进程体会下来,我以为AI还不能让零基础的人完成开发,但能够让略懂的人更快的完成自己的主意。

你或许现已看到不少说法,说GPT-4现已能够彻底帮你写代码了,但我仍是主张你不要越过基础的学习。刚开始或许你会欣喜于成功运转起demo,但随着完成的功用越来越复杂,你仍是需求亲身写一些逻辑。彻底不懂的话会无从下手,或许不知道怎么提问题。

关于我来说,有了AI加持,我终于敢开发一些之前仅停留在脑海里的主意了。下一步或许搞一个OnlyFans原图下载插件,存一些艺术照。