Greasy Fork is available in English.

Design Tokens

从 Figma 设计稿提取所用到的库颜色

// ==UserScript==
// @name         Design Tokens
// @namespace    http://tampermonkey.net/
// @description  从 Figma 设计稿提取所用到的库颜色
// @version      2024-11-15
// @author       You
// @match        https://*.figma.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=figma.com
// @grant        none
// @license      MIT
// ==/UserScript==


(function() {
    'use strict';

    // 将 Figma 的颜色格式转换为 RGBA 格式
    function colorToRGBA(color, opacity) {
        const r = Math.round(color.r * 255);
        const g = Math.round(color.g * 255);
        const b = Math.round(color.b * 255);
        return `rgba(${r}, ${g}, ${b}, ${opacity})`; // 使用 paint.opacity 作为 alpha 值
    }

    // 迭代函数用于遍历节点并提取具有 fillStyleId 的填充样式
    function extractPaintStyles(rootNode) {
        const styles = [];
        const uniqueStyles = {}; // 用于去重的对象
        const stack = [rootNode]; // 使用栈来存储待处理的节点

        function processNodes() {
            let count = 0; // 计数处理的节点数量

            while (stack.length > 0 && count < 10) {
                const node = stack.pop(); // 从栈中取出一个节点

                // 仅处理具有填充样式的节点
                if ("fills" in node && node.fills.length > 0) {
                    // 检查节点是否有 fillStyleId
                    if (node.fillStyleId) {
                        const style = figma.getStyleById(node.fillStyleId);
                        if (style) {
                            // 检查样式类型是否为 PAINT
                            if (style.type === 'PAINT') {
                                // 提取颜色信息
                                const paint = style.paints[0]; // 假设样式只包含一个填充
                                if (paint && paint.type === 'SOLID') {
                                    const rgbaColor = colorToRGBA(paint.color, paint.opacity); // 使用 paint.opacity
                                    const styleKey = style.name; // 使用样式名称作为唯一标识

                                    // 去重逻辑
                                    if (!uniqueStyles[styleKey]) {
                                        uniqueStyles[styleKey] = {
                                            name: style.name,
                                            description: style.description || 'No description',
                                            rgba: rgbaColor
                                        };
                                    }
                                }
                            } else {
                                console.error(`Node has a fillStyleId that is not a paint style: ${style.type}`);
                            }
                        }
                    }
                }

                // 如果节点有子节点,则将子节点添加到栈中
                if ("children" in node) {
                    for (const child of node.children) {
                        stack.push(child); // 将子节点推入栈中
                    }
                }

                count++; // 增加计数
            }

            // 如果还有节点未处理,设置延迟后继续处理
            if (stack.length > 0) {
                setTimeout(processNodes, 1); // 每 1 毫秒继续处理
            } else {
                // 所有节点处理完成,输出结果
                const result = Object.values(uniqueStyles); // 将对象转换为数组
                result.sort((a, b) => a.name.localeCompare(b.name)); // 按名称排序
                console.log('Extracted Paint Styles:', result);
                alert('提取完成,请查看控制台输出');
            }
        }

        // 启动节点处理
        processNodes();
    }

    // 添加一个按钮到页面
    const button = document.createElement('button');
    button.innerText = '提取填充样式';
    button.style.position = 'fixed';
    button.style.top = '10px';
    button.style.right = '10px';
    button.style.zIndex = 1000;
    button.style.padding = '10px';
    button.style.backgroundColor = '#007bff';
    button.style.color = 'white';
    button.style.border = 'none';
    button.style.borderRadius = '5px';
    button.style.cursor = 'pointer';

    // 点击按钮时提取样式
    button.onclick = () => {
        const rootNode = figma.currentPage; // 使用 Figma 的 API 获取当前页面

        try {
            extractPaintStyles(rootNode);
        } catch (error) {
            console.error(error.message);
            alert('提取过程中发生错误,请查看控制台');
        }
    };

    // 将按钮添加到页面
    document.body.appendChild(button);
})();