解锁SVG新姿势:ChatGPT绘制图标+SVG Symbol自动导入

lxf2023-04-06 20:34:01

解锁SVG新姿势:ChatGPT绘制图标+SVG Symbol自动导入

1 前言

大家好,我是心锁,一枚23届准毕业生。

近期ChatGPT很火,作为前端er,我思考与尝试了让它帮忙写代码、帮助我解析与研究某些国内资料较少的技术、优化代码、解释代码、优化简历——都非常棒,就是很可惜GPT的图片能力还一般,如果什么时候它可以解析图片了,或许图片生成代码就不远了。

解锁SVG新姿势:ChatGPT绘制图标+SVG Symbol自动导入

等一下,SVG好像也是图片,就在某个时刻我灵光一闪,于是本文章就出来了。

2 目标

不知道诸位读者们有没有自己找icon的经历:

  1. 先找到对应图片并下载
  2. 将文件移动到项目并改名
  3. 在需要使用的地方导入并通过img标签使用

私以为,第一步,第二步,第三步我都不喜欢。有没有一种合适的方式,让我可以直接通过IDE新建文件,不再需要下载,同时使用的时候不再需要导入?

解锁SVG新姿势:ChatGPT绘制图标+SVG Symbol自动导入

这或许是有的,本文旨在完成该目标。

3 演示ChatGPT生成SVG

本步骤也可以理解成正常流程中的寻找图标与自行绘制图片

众所周知,SVG是一种矢量图形格式,可以通过代码描述出图形,而不是像普通图片一样储存像素点。这使得SVG图标具有可缩放性,适合在不同分辨率的设备上使用。同时,SVG图标可以用作网站的某些元素,例如logo、导航菜单等。

解锁SVG新姿势:ChatGPT绘制图标+SVG Symbol自动导入

再众所周知,ChatGPT具有生成代码的能力。我们可以利用ChatGPT生成SVG代码,这样就可以省去自己绘制图标或者自己找图标的步骤。

我试着用下边的文案生成了一些icon,大家可以参考:

3.1 一款网络助手的logo

生成一个扁平风格的图标,该图标用途是作为一款网络助手程序的logo。背景色是“#7FA1F7”,圆角22.5%。注意要求图像大小为64*64,图像内容需在viewBox居中。

解锁SVG新姿势:ChatGPT绘制图标+SVG Symbol自动导入

解锁SVG新姿势:ChatGPT绘制图标+SVG Symbol自动导入

3.2 绘制一个用于AdminJS的拟物化“矿石”图标

绘制一个64*64的“矿石”图标,以svg格式输出。该图标用于表示社区中的金币,图标风格应偏向拟物化风格,整体需符合AdminJS社区的气质,并确保图像内容需在viewBox居中。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
  <circle cx="32" cy="32" r="30" fill="#e8ca6f" stroke="#c3a150" stroke-width="2"/>
  <path d="M 32 5 L 60 23 L 60 41 L 32 59 L 4 41 L 4 23 Z" fill="#e0b757" stroke="#c3a150" stroke-width="2"/>
  <path d="M 32 17 L 52 33 L 32 49 L 12 33 Z" fill="#d4a84a"/>
  <path d="M 32 23 L 45 33 L 32 43 L 19 33 Z" fill="#e8ca6f"/>
  <path d="M 32 27 L 41 33 L 32 39 L 23 33 Z" fill="#f2e1a9"/>
</svg>

解锁SVG新姿势:ChatGPT绘制图标+SVG Symbol自动导入

3.3 绘制一个用于AdminJS的拟态化“收藏”图标(它好像把AdminJS社区误会成真的AdminJS了)

绘制一个64*64的“收藏”图标,以svg格式输出。图标风格应偏向拟态化风格,整体需符合AdminJS社区的气质,并确保图像内容需在viewBox居中。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
  <circle cx="32" cy="32" r="30" fill="#e8ca6f" stroke="#c3a150" stroke-width="2"/>
  <path d="M 32 17 L 44 33 L 32 49 L 20 33 Z" fill="#e0b757" stroke="#c3a150" stroke-width="2"/>
  <path d="M 32 21 L 40 33 L 32 45 L 24 33 Z" fill="#d4a84a"/>
  <path d="M 32 27 L 36 33 L 32 39 L 28 33 Z" fill="#e8ca6f"/>
  <rect x="25" y="26" width="14" height="12" fill="#f2e1a9"/>
  <path d="M 26 27 L 32 22 L 38 27 L 38 33 L 26 33 Z" fill="#c3a150"/>
  <path d="M 38 27 L 32 32 L 26 27 L 26 33 L 38 33 Z" fill="#d4a84a"/>
  <circle cx="32" cy="32" r="9" fill="#f2e1a9"/>
</svg>

解锁SVG新姿势:ChatGPT绘制图标+SVG Symbol自动导入

4 Svg Symbol自动导入

4.1 什么是Symbol

为了实现不需要下载和导入文件,我们可以使用SVG Symbol。使用SVG Symbol,我们可以将所有的图标放在一个单独的SVG文件中,并通过引用该文件中的Symbol元素来使用它们。

以下是一个示例SVG文件,其中定义了两个Symbol元素:

<svg xmlns="<http://www.w3.org/2000/svg>" style="display:none">
  <symbol id="icon-search" viewBox="0 0 24 24">
    <path fill="none" d="M0 0h24v24H0V0z"/>
    <path d="M9.5 15h-.79l-.28-.27C8.01 13.54 7.5 12.8 7.5 12c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5c0 .8-.5 1.54-1.21 1.73l-.28.27v.5l5 4.99L20.49 19l-4.95-5zm-1-3a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z"/>
  </symbol>
  <symbol id="icon-heart" viewBox="0 0 24 24">
    <path fill="none" d="M0 0h24v24H0V0z"/>
    <path d="M12 21.35l-1.45-1.32C5.4 14.35 2 11.43 2 7.77 2 5.82 3.16 4.02 5 3.14 6.38 2.5 8.35 2.5 10 3.44 11.65 2.5 13.62 2.5 15 3.14c1.84.88 3 2.68 3 4.63 0 3.66-3.4 6.58-8.55 11.26L12 21.35z"/>
  </symbol>
</svg>

以下是一个使用SVG Symbol的示例代码:

<svg>
  <use xlink:href="#icon-search"></use>
  <use xlink:href="#icon-heart"></use>
</svg>

在上面的代码中,我们通过<use>元素引用了SVG文件中的两个Symbol元素,并将它们放在了<svg>元素内。

4.2 自动化导入

为了进一步简化该流程,我们可以使用Webpack和svg-sprite-loader自动导入SVG Symbol。

4.2.1 添加svg-sprite-loader

以下是一个Webpack配置文件中添加的svg-sprite-loader规则:

module: {
  rules: [
    {
        test: /\.svg$/i,
        oneOf: [
          {
            resourceQuery: /asset/,
            type: "asset/resource",
          },
          {
            loader: "svg-sprite-loader",
            include: path.resolve(__dirname, "../src/images/svg"),
            options: {
              symbolId: "icon-[name]",
            },
          },
        ],
      },
  ]
}

该规则将处理所有以.svg结尾的文件,并使用svg-sprite-loader将它们转换为SVG Symbol元素。其中,symbolId选项用于生成Symbol元素的ID。这样既保留了导入svg为url的能力,又拥有了symbol导入能力。

4.2.2 自动导入所有svg图标

我们可以在images文件夹下新建一个svg文件夹,在其中存放所有的SVG图标文件。然后,我们创建一个svg-sprite.ts文件,使用require.context函数自动导入所有的SVG文件并将它们添加到页面中。

解锁SVG新姿势:ChatGPT绘制图标+SVG Symbol自动导入

// svg-sprite.ts
const importAll = (requireContext: __WebpackModuleApi.RequireContext) => 
	requireContext.keys().forEach(requireContext);

importAll(require.context('./svg', true, /\.svg$/));
export {};

在上面的代码中,我们使用require.context函数导入了所有以.svg结尾的文件,并将它们添加到页面中。

在该步骤,需要注意两个点。

  • 需要导入svg-sprite.ts文件

务必在主文件中导入该文件:

// App.tsx
import "./images/svg-sprite";
  • 若出现和WebpackModuleApi相关错误,强烈建议使用any代替

解锁SVG新姿势:ChatGPT绘制图标+SVG Symbol自动导入

4.2.3 在React中使用

为方便使用,我们封装一个SvgIcon组件

import React from "react";
import "./index.less";

export interface SvgIconProps extends React.HTMLAttributes<HTMLElement> {
  name: string;
  className?: string;
  color?: string;
}

const SvgIcon: React.FC<SvgIconProps> = ({
  name = "",
  className = "",
  color = "currentColor",
  ...rest
}) => {
  return (
    <i className={`${className}`} aria-hidden {...rest}>
      <svg className={"svg-icon"}>
        <use xlinkHref={"#icon-" + name} fill={color} />
      </svg>
    </i>
  );
};

export default SvgIcon;

在上面的代码中,我们定义了一个SvgIcon组件,用于渲染SVG图标。该组件使用了<use>元素引用了SVG文件中的Symbol元素。其中,name属性用于指定Symbol元素的ID。

.svg-icon{
     width: 1em; height: 1em;
     vertical-align: -0.15em;
     fill: currentColor;
     overflow: hidden;
}

使用em作为icon的单位,是因为em是相对于当前对象内文本的字体尺寸的宽度单位,这样我们就可以通过设置fontSize的方式来调整icon的图标了。

解锁SVG新姿势:ChatGPT绘制图标+SVG Symbol自动导入

使用方式:

import SvgIcon from "@/components";

const MyComponent: React.FC = () => {
  return (
    <div>
      <SvgIcon name="search" className="text-[1rem]" />
      <SvgIcon name="heart" />
    </div>
  );
};

在上面的代码中,我们使用了SvgIcon组件来渲染SVG图标,其中,name属性用于指定需要渲染的图标的名称。

至此,我们已经完成了将SVG图标转换为SVG Symbol,并自动导入的流程。现在,我们可以直接在代码中使用SVG图标了,而不需要导入文件。

4.2.4 性能考虑

值得注意的是,该方法存在一定的问题。由于我们全量引用了图标,会导致在所有页面,都会导入所有icon,原因是我们在svg-sprite.ts文件中做了自动化导入,我们亦可通过单行导入的方式来避免全量引入,我目前在思考有没有什么更好的方案解决该问题。

import "@/images/svg/rough.svg";

5 总结

本文主要介绍了两个方法,分别是使用ChatGPT自动生成SVG代码和使用Webpack和svg-sprite-loader自动导入SVG Symbol。这些方法可以使得在代码中使用SVG图标更加方便和高效。

解锁SVG新姿势:ChatGPT绘制图标+SVG Symbol自动导入

综上所述,通过使用ChatGPT自动生成SVG代码和使用Webpack和svg-sprite-loader自动导入SVG Symbol,我们可以更加便捷地在代码中使用SVG图标,提高开发效率和代码质量。


本文正在参加「」