从零开发一款VS Code插件:图片取色工具教程 🎨

本文将带你从零开始,一步步开发一个实用的VS Code插件——图片取色工具,让你在VS Code中轻松提取图片的主色调!

🚀 项目概述

起因:之前想基于凡人动漫制作一款主题,于是截了很多动漫的图片想提取这些图片的主色调色号,在网上找了很多小工具,基本都是只能一张一张上传图片生成结果,实在太费事了,于是就想着把这个功能做成一个VSCode插件。

这个插件应该具备以下功能:

  • 📸 在资源管理器中右键图片文件
  • 🎨 自动提取图片主色调生成色卡
  • 📋 支持一键复制色号(HEX/RGB格式)
  • ⚙️ 可配置色卡数量(6/8/10个颜色)

📋 开发环境准备

必备工具

# 安装Node.js和npm
# 安装VS Code
# 安装Yeoman和VS Code扩展生成器
npm install -g yo generator-code

创建项目

# 使用脚手架创建项目
yo code

# 选择配置:
# ? What type of extension do you want to create? New Extension (TypeScript)
# ? What's the name of your extension? Image Color Palette
# ? What's the identifier of your extension? image-color-palette
# ? What's the description of your extension? 从图片中提取主色调并生成色卡
# ? Initialize a git repository? Yes
# ? Bundle the source code with webpack? Yes
# ? Package manager to use? npm

🏗️ 项目结构设计

生成的项目结构:

image-color-palette/
├── src/
│   ├── extension.ts          # 主扩展逻辑
│   └── test/
├── media/                    # 静态资源
│   ├── paletteView.js       # Webview前端脚本
│   └── palette.css          # 样式文件
├── resources/               # 图标资源
│   └── icon.png
├── package.json             # 扩展配置
├── webpack.config.js        # 打包配置
└── tsconfig.json           # TypeScript配置

📝 第一步:配置package.json

这是插件的"身份证",定义插件的基本信息和功能:

⚠️注意:publisher字段的值要和你注册Visual Studio Code MarketplacePublisher ID保持一致,不然会发布失败

{
  "name": "image-color-palette",
  "displayName": "Image Color Palette|图片取色",
  "description": "从图片中提取主色调并生成色卡,支持复制色号",
  "version": "0.0.1",
  "publisher": "CarrieXin",
  "engines": {
    "vscode": "^1.74.0"
  },
  "categories": ["Other"],
  "main": "./dist/extension.js",
  "icon": "./resources/icon.png",
  "contributes": {
    "commands": [
      {
        "command": "image-color-palette.generatePalette",
        "title": "生成图片色卡"
      }
    ],
    "menus": {
      "explorer/context": [
        {
          "command": "image-color-palette.generatePalette",
          "group": "navigation@100",
          "when": "resourceExtname == .png || resourceExtname == .jpg || resourceExtname == .jpeg || resourceExtname == .gif || resourceExtname == .webp || resourceExtname == .bmp || resourceExtname == .svg"
        }
      ]
    }
  }
}

🔑 关键配置说明:

  • contributes.commands: 定义插件提供的命令
  • contributes.menus: 配置右键菜单显示位置
  • when条件: 只在图片文件上显示菜单项

🎯 第二步:实现核心扩展逻辑

src/extension.ts中实现主要功能:

import * as vscode from "vscode";

// 支持的图片扩展名
const IMAGE_EXTS = [".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".svg"];

/**
 * 激活扩展入口
 * @param {vscode.ExtensionContext} context 扩展上下文
 * @return {void} 无返回
 */
export function activate(context: vscode.ExtensionContext) {
  console.log('插件"image-color-palette"已激活!');

  // 注册生成图片色卡命令
  const genPalette = vscode.commands.registerCommand(
    "image-color-palette.generatePalette",
    async (resource: vscode.Uri) => {
      try {
        const target = await ensureTargetImage(resource);
        if (!target) {
          return;
        }
        openPaletteWebview(context, target);
      } catch (err: any) {
        vscode.window.showErrorMessage(
          `生成图片色卡失败: ${err?.message || String(err)}`
        );
      }
    }
  );
  context.subscriptions.push(genPalette);
}

🖼️ 第三步:创建Webview界面

/**
 * 打开色卡预览Webview
 * @param {vscode.ExtensionContext} context 扩展上下文
 * @param {vscode.Uri} imgUri 图片URI
 * @return {void} 无返回
 */
function openPaletteWebview(
  context: vscode.ExtensionContext,
  imgUri: vscode.Uri
): void {
  // 创建并显示webview面板
  const panel = vscode.window.createWebviewPanel(
    "imageColorPalette",
    "图片色卡",
    vscode.ViewColumn.Beside,
    {
      enableScripts: true,
      retainContextWhenHidden: true,
    }
  );

  // 处理webview消息
  panel.webview.onDidReceiveMessage(
    (message) => {
      switch (message.type) {
        case "copy":
          vscode.env.clipboard.writeText(message.hex);
          vscode.window.showInformationMessage(`已复制色号: ${message.hex}`);
          break;
        case "copyAll":
          vscode.env.clipboard.writeText(message.colors.join("\n"));
          vscode.window.showInformationMessage(
            `已复制${message.colors.length}个色号`
          );
          break;
      }
    },
    undefined,
    context.subscriptions
  );

🎨 第四步:实现前端色彩提取算法

media/paletteView.js中实现K-Means聚类算法提取主色调:

/**
 * 图片色卡生成器
 * 作者:CarrieXin
 * 功能:使用K-Means算法从图片中提取主色调
 */

class ColorPalette {
  constructor() {
    this.vscode = acquireVsCodeApi();
    this.init();
  }

  /**
   * 初始化色卡生成器
   */
  init() {
    const img = document.getElementById('sourceImage');
    img.onload = () => {
      this.extractColors(img);
    };
  }

  /**
   * 使用K-Means算法提取图片主色调
   * @param {HTMLImageElement} img 图片元素
   */
  extractColors(img) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    
    // 设置画布尺寸
    canvas.width = img.width;
    canvas.height = img.height;
    
    // 绘制图片到画布
    ctx.drawImage(img, 0, 0);
    
    // 获取图片像素数据
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const pixels = this.getPixels(imageData);
    
    // 使用K-Means聚类提取主色调
    const colorCount = parseInt(document.getElementById('colorCount').value);
    const dominantColors = this.kMeans(pixels, colorCount);
    
    // 渲染色卡
    this.renderPalette(dominantColors);
  }

  /**
   * RGB转HEX
   * @param {number} r 红色值
   * @param {number} g 绿色值
   * @param {number} b 蓝色值
   * @return {string} HEX颜色值
   */
  rgbToHex(r, g, b) {
    return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
  }
}

// 初始化色卡生成器
new ColorPalette();

🎭 第五步:美化界面样式

media/palette.css中添加样式:

/**
 * 图片色卡样式文件
 * 作者:CarrieXin
 */

body {
  font-family: var(--vscode-font-family);
  color: var(--vscode-foreground);
  background-color: var(--vscode-editor-background);
  margin: 0;
  padding: 20px;
}

.container {
  max-width: 800px;
  margin: 0 auto;
}

.controls {
  display: flex;
  gap: 15px;
  margin-bottom: 20px;
  align-items: center;
}

.control-group {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.color-item {
  height: 80px;
  border-radius: 8px;
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
  display: flex;
  align-items: flex-end;
  position: relative;
  overflow: hidden;
}
...

🔧 第六步:调试和测试

本地调试

  1. F5(mac fn + F5)启动调试模式
  2. 在新窗口中测试插件功能
  3. 在资源管理器中右键图片文件
  4. 选择"生成图片色卡"

常见问题解决

问题:版本兼容性

测试时发现报错

ERROR  @types/vscode ^1.103.0 greater than engines.vscode ^1.74.0.
Either upgrade engines.vscode or use an older @types/vscode version
确保`package.json`中的版本配置一致:

这是因为engines.vscode 版本为 ^1.74.0,@types/vscode 版本为 ^1.103.0
,两者版本不匹配导致打包失败,将版本号统一即可

{
  "engines": {
    "vscode": "^1.74.0"
  },
  "devDependencies": {
    "@types/vscode": "^1.74.0"
  }
}

📦 第七步:打包和发布

安装打包工具

npm install -g vsce

打包插件

# 编译项目
npm run compile

# 打包成.vsix文件
vsce package

本地安装测试

方式一:命令安装

# 安装打包好的插件
code --install-extension image-color-palette-0.0.1.vsix

方式二:上传 vsix 文件


image.png

发布插件

将生成的插件vsix文件上传到插件广场

image.png

image.png

至此一款 VSCode 插件就开发完成并上传到拓展商店,可以提供给其他人使用了🎉🎉🎉
插件效果如图


image.png

踩坑:注意版本兼容问题,确保依赖版本与引擎版本匹配

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容