iconfont字体图标

  1. 当前几种图标使用方式

:图像嵌入元素

用法

html 复制代码
<img src={'/com/huawei/static/images/grapefruit-slice-332-332.jpg'} className="App-logo" alt="logo" />

// 或
import logo from '/com/huawei/static/images/logo.svg';
<img src={logo} className="App-logo" alt="logo" />

// 支持响应式图片
<picture>
  <source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg" />
  <source media="(min-width: 800px)" srcset="elva-800w.jpg" />
  <img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva" />
</picture>
  • 学习成本:简单的标签即可。

  • 支持图像格式:APNG(动态可移植网络图形)------无损动画序列的不错选择(GIF 性能较差)。AVIF(AV1 图像文件格式)------静态图像或动画的不错选择,其性能较好。GIF(图像互换格式)------简单图像和动画的不错选择。JPEG(联合图像专家组)------有损压缩静态图像的不错选择(目前最流行的格式)。PNG(便携式网络图形)------对于无损压缩静态图像而言是不错的选择(质量略好于 JPEG)。SVG(可缩放矢量图形)------矢量图像格式。用于必须以不同尺寸准确描绘的图像。WebP(网络图片格式)------图像和动画的绝佳选择。Base64。

  • 是否矢量图: 不是,除非源文件本身就是SVG。

  • 如何修改图标样式:width和height,或者通过css修改宽高。

  • 体积大小:

  • 性能: 大量图标可以使用精灵图减少http请求;支持Base64。

  • 懒加载:

html 复制代码
 <img src={logo} className={"App-logo"} alt={"logo"} loading={'lazy'} />
jsx 复制代码
import React, { useRef, useEffect, useState } from 'react';
 
const LazyLoadImage = ({ src, alt }) => {
  const [imageSrc, setImageSrc] = useState('');
  const imgRef = useRef(null);
 
  useEffect(() => {
    let observer;
    if (imgRef.current) {
      observer = new IntersectionObserver(
        ([entry]) => {
          // 当图片进入可视区域时,设置图片地址进行加载
          if (entry.isIntersecting) {
            setImageSrc(src);
            observer.unobserve(imgRef.current);
          }
        },
        {
          rootMargin: '0px 0px 200px 0px', // 可视区域的边距设置为200px
        }
      );
      observer.observe(imgRef.current);
    }
    return () => {
      if (observer && observer.unobserve) {
        observer.unobserve(imgRef.current);
      }
    };
  }, [src]);
 
  return <img ref={imgRef} src={imageSrc} alt={alt} />;
};
 
export default LazyLoadImage;
  • 缓存: 可以被浏览器缓存。
  • 加载失败处理:
  • 适用场景: 适合于单个较大的图像或非矢量图标。

CSS背景图像 用法: 通过CSS background-image属性设置背景图像。

css 复制代码
background:<attachment> <bg-image> <position> <bg-size> <repeat-style>

学习成本:只需要了解css的background属性 支持图片格式:同img。 是否矢量图: 不是,除非源文件本身就是SVG。 体积大小: 性能: 支持Base64。 缓存: 可以被浏览器缓存。 加载失败处理: 适用场景: 适合于不需要频繁更新背景图的情况。

Base64编码 Base64 是一组相似的二进制到文本(binary-to-text)的编码规则,让二进制数据在解释成 64 进制的表现形式后能够用 ASCII 字符串的格式表示出来。

用法: 直接在CSS或HTML中嵌入Base64编码的字符串。

jsx 复制代码
<img src={"data:image/jpeg;base64,/9j/..."} alt={"Example Image"}>

学习成本: 低,只需知道如何使用Base64编码。 是否矢量图: 取决于源文件类型。 体积大小: 比原始文件大33%,但可以避免额外HTTP请求。 性能: 对于小图标较好,对于大图标可能增加页面加载时间。 缓存: 无法缓存,因为是内联数据;如果 base64 是被编码到 css/js 中,是可以缓存的,因为 css/js 文件可以缓存。 适用场景: 适合于小图标,可以减少HTTP请求次数。

HTML5 Canvas 用法: 使用JavaScript动态绘制。

js 复制代码
// html
<canvas width="120" height="120">
  An alternative text describing what your canvas displays.
</canvas>

//js
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
ctx.fillStyle = "green";
// Add a rectangle at (10, 10) with size 100x100 pixels
ctx.fillRect(10, 10, 100, 100);

语法便利程度: 复杂,需要编程知识。 学习成本: 较高,需要熟悉Canvas API。 是否矢量图: 可以视为矢量图,但实际上是像素渲染,绘制完成后会导出为 PNG 或 JPEG。 体积大小: 动态生成,取决于实际绘制的内容。 性能: 较好,适合动态效果和动画。 缓存: 无法缓存,每次都需要重新绘制。 适用场景: 适合于复杂的图形处理和动画效果。

Web Components Web Component - Web API | MDN (mozilla.org) 用法: 定义自定义元素,并在其中放置图标。 语法便利程度: 中等到高,需要编写组件。 学习成本: 较高,需要了解Web Components。 是否矢量图: 取决于使用的图标类型。 体积大小: 取决于图标本身。 性能: 较好,封装性好。 缓存: 可以被浏览器缓存。 适用场景: 适合于复杂的Web应用,便于组件化管理。

Server-Side Rendering (SSR) 用法: 在服务器端生成图标HTML。 语法便利程度: 中等到高,需要服务器端脚本。 学习成本: 较高,需要了解服务器端渲染技术。 是否矢量图: 取决于生成的图标类型。 体积大小: 取决于图标本身。 性能: 较好,可以提高首屏加载速度。 缓存: 可以被浏览器缓存。 适用场景: 适合于需要服务器端渲染的应用程序。

SVG 用法:

html 复制代码
<svg version="1.1"
     baseProfile="full"
     width="300" height="200"
     xmlns="http://www.w3.org/2000/svg">

  <rect width="100%" height="100%" fill="red" />

  <circle cx="150" cy="100" r="80" fill="green" />

  <text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>

</svg>

<object data="image.svg" type="image/svg+xml"></object>
<iframe src="image.svg"></iframe>
// SVG 可以通过 JavaScript 动态创建并注入到 HTML DOM 中

学习成本: 需要了解SVG语法。 是否矢量图: 是。 体积大小: 较小,特别是当图标简单时。 性能: 较好,因为是矢量图且体积较小。 缓存: 直接嵌入 SVG 代码时,整个 HTML 文档会被缓存;而通过 <img> 标签引入时,SVG 文件会被作为一个独立的资源缓存。 适用场景: 适合于需要缩放而不失真的情况。

优点:矢量图,随时可改变形状大小颜色,SVG 支持渐变、旋转、复杂的曲线动画、滤镜效果、与 JavaScript 交互。

  1. 通过 ID 和 Class 选择 SVG 元素 用法:给 SVG 元素分配 ID 或 class,然后使用 JavaScript 通过这些选择器来访问和操作这些元素。
html 复制代码
<svg id="mySVG" width="100" height="100">
  <circle id="myCircle" cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>

<script>
  const circle = document.getElementById('myCircle');
  circle.setAttribute('fill', 'blue');
</script>
  1. 添加事件监听器 用法:使用 addEventListener 方法来为 SVG 元素添加事件监听器。
js 复制代码
<svg width="100" height="100">
  <rect x="10" y="10" width="80" height="80" fill="green" id="myRect" />
</svg>

<script>
  const rect = document.getElementById('myRect');
  rect.addEventListener('click', function(event) {
    event.target.setAttribute('fill', 'yellow');
  });
</script>
  1. 动画和定时器 用法:使用 JavaScript 的 setTimeout 和 setInterval 来创建动画效果。
js 复制代码
<svg width="200" height="200">
  <circle cx="100" cy="100" r="50" fill="blue" id="myCircle" />
</svg>

<script>
  const circle = document.getElementById('myCircle');
  let angle = 0;

  setInterval(function() {
    angle += 5; // 每次旋转 5 度
    const rad = angle * Math.PI / 180;
    const cx = 100 + 50 * Math.cos(rad);
    const cy = 100 + 50 * Math.sin(rad);

    circle.setAttribute('cx', cx);
    circle.setAttribute('cy', cy);
  }, 100); // 每 100 毫秒更新一次位置
</script>
  1. 与 CSS 结合使用 用法:结合使用 JavaScript 和 CSS 来控制 SVG 元素的样式。
js 复制代码
<svg width="200" height="200">
  <circle cx="100" cy="100" r="50" fill="blue" id="myCircle" />
</svg>

<style>
  #myCircle.active {
    fill: red;
  }
</style>

<script>
  const circle = document.getElementById('myCircle');

  circle.addEventListener('click', function() {
    circle.classList.toggle('active');
  });
</script>
  1. 使用 SVG.js 或 Snap.svg 用法:使用这些轻量级的 SVG 操作库来简化 SVG 元素的操作和动画。
js 复制代码
<svg width="200" height="200">
  <circle cx="100" cy="100" r="50" fill="blue" id="myCircle" />
</svg>

<script src="https://cdn.jsdelivr.net/npm/svg.js@3.1.1/dist/svg.min.js"></script>
<script>
  const circle = SVG('myCircle');

  circle.animate(2000).attr({ fill: 'red' }).repeat();
</script>

SVG 与 JavaScript 的交互可以让你创建动态的图形和动画效果。通过选择器、事件监听器、定时器、SVG DOM 方法、第三方库以及 CSS 的组合使用,你可以轻松地实现复杂的 SVG 动画和交互。选择合适的方法取决于你的具体需求和项目的复杂性。 缺点:加载慢。

为了完整地实现这个功能,你需要编写一个脚本来生成 SVG 组件,并更新 index.ts 文件。以下是完整的示例代码:

1. 安装依赖项

首先,确保安装了 @svgr/clichild_process 模块。在你的项目根目录中运行以下命令:

bash 复制代码
bash
深色版本
1npm install -D @svgr/cli child_process

2. 编写脚本文件

创建一个名为 generate-icons.js 的文件,并将以下代码复制进去:

javascript 复制代码
javascript
深色版本
1const path = require('path');
2const fs = require('fs');
3const execSync = require('child_process').execSync;
4
5function generateSvgComponent(item) {
6  if (item === 'index') return Promise.resolve();
7
8  return new Promise((resolve, reject) => {
9    try {
10      execSync(`npx @svgr/cli -- ${path.resolve(__dirname, `../src/components/ui/icon/svg/${item}.svg`)}`);
11      resolve();
12    } catch (error) {
13      reject(error);
14    }
15  });
16}
17
18function updateIndexFile() {
19  const indexPath = path.join(__dirname, '../src/components/ui/icon/index.ts');
20  const iconDirPath = path.resolve(__dirname, '../src/components/ui/icon/icons');
21
22  const files = fs.readdirSync(iconDirPath).filter(file => file.endsWith('.svg'));
23
24  let content = files
25    .map(file => `export * from './icons/${file.replace(/.svg$/, '')}'`)
26    .join('\n');
27
28  content += '\n';
29
30  fs.writeFileSync(indexPath, content);
31}
32
33async function main() {
34  await generateSvgComponent('index');
35  updateIndexFile();
36}
37
38main().catch(console.error);

3. 运行脚本

在终端中运行以下命令:

bash
深色版本
1node generate-icons.js

这个脚本会自动遍历 ./src/components/ui/icon/icons 目录下的所有 .svg 文件,并使用 @svgr/cli 将它们转换为 React 组件。同时,它还会更新 index.ts 文件,使你可以按需导入和使用这些组件。

4. 使用生成的组件

在你的 React 应用程序中,你可以像这样使用生成的组件:

ini 复制代码
jsx
深色版本
1import { UserIcon } from './components/ui/icon';
2
3function App() {
4  return (
5    <div className="App">
6      <UserIcon color="red" />
7    </div>
8  );
9}

在这个例子中,color 属性会被传递给 UserIcon 组件,使其能够更改图标颜色。这是由于 @svgr/cli 工具生成的组件通常具有这样的功能。

请注意,这个脚本仅适用于简单的场景。在实际项目中,你可能需要对它进行调整以满足特定需求,比如处理错误、添加日志记录等功能。

IconFont 用法: 使用字体图标字符,通过CSS设置。 语法便利程度: 方便,只需一个字符。 学习成本: 低,只需了解基本的CSS和字体图标集。 支持的格式: 字体图标,通常是 TTF, OTF, WOFF, WOFF2 等字体格式。 是否矢量图: 是,基于字体。 体积大小: 较小,尤其是当多个图标打包在一个字体文件中时。 性能: 好,因为字体文件可以被缓存。 缓存: 可以被浏览器缓存。 适用场景: 适合于需要大量图标并且希望保持字体一致性的项目。

各自优缺点

  1. Img (Image) 优点: 易于使用: 只需一个 标签即可显示图标。 跨浏览器兼容性: 几乎所有浏览器都支持 标签。 尺寸固定: 图标尺寸不会随文本缩放而改变,保持一致的视觉效果。 缺点: 不灵活: 需要为不同尺寸和状态准备多个图像文件。 加载时间: 每个图像都需要额外的HTTP请求,可能会增加页面加载时间。 样式限制: 无法使用CSS进行颜色或透明度调整。
  2. CSS 优点: 可定制性强: 可以通过CSS对图标进行颜色、阴影等样式的修改。 响应式: 图标可以随着容器尺寸变化而自动调整大小。 单个HTTP请求: 如果使用CSS Sprites或者CSS背景图,可以减少HTTP请求数量。 缺点: 复杂性: 需要额外的工作来创建复杂的图标。 维护成本: 更改图标可能需要修改CSS代码。 兼容性问题: 对于某些较老的浏览器,可能需要额外的polyfills。
  3. HTML5 Canvas 优点: 高性能: 特别适合动画和复杂的图形操作。 动态生成: 可以根据需要动态绘制图标。 可扩展性: 图标可以根据需要缩放而不失真。 缺点: JavaScript依赖: 需要编写JavaScript代码来绘制图标。 不便于维护: 修改图标通常需要更改代码。 SEO不友好: Canvas内容对搜索引擎不可见。
  4. SVG (Scalable Vector Graphics) 优点: 矢量图形: 图标可以无损缩放。 样式可定制: 可以使用CSS来改变颜色、填充等属性。 单个HTTP请求: 可以内联到HTML中,避免额外的HTTP请求。 响应式: 可以根据容器尺寸自动调整大小。 缺点: 复杂图标: 复杂图标可能需要较多的手工编码。 IE兼容性: IE9及以下版本不支持SVG。
  5. Icon Font 优点: 样式可定制: 使用CSS来改变颜色、大小等属性。 单个HTTP请求: 所有图标都可以打包在一个字体文件中。 易于使用: 只需像使用文字一样使用图标字符。 缺点: 图标质量: 字体图标可能不如SVG清晰。 兼容性问题: 较老的浏览器可能不支持某些字体。 多语言环境: 在多语言环境中可能与文字混排产生问题。
  6. Web Components 优点: 封装性: Web Components 提供了一种封装图标的方法,可以将图标及其行为封装在一个自定义元素中。 重用性: 可以轻松地在多个项目中重用相同的图标组件。 可扩展性: 可以在组件内部添加更多的逻辑和交互。 缺点: 浏览器兼容性: 虽然大多数现代浏览器都支持Web Components,但在一些旧版浏览器上可能需要polyfills。 学习曲线: 开发者需要学习如何创建和使用Web Components。 性能: 使用Web Components可能会带来一些额外的性能开销,尤其是在大量使用时。
相关推荐
彭世瑜22 分钟前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund40423 分钟前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish24 分钟前
Token刷新机制
前端·javascript·vue.js·typescript·vue
小五Five25 分钟前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序25 分钟前
vue3 封装request请求
java·前端·typescript·vue
临枫54126 分钟前
Nuxt3封装网络请求 useFetch & $fetch
前端·javascript·vue.js·typescript
酷酷的威朗普27 分钟前
医院绩效考核系统
javascript·css·vue.js·typescript·node.js·echarts·html5
前端每日三省27 分钟前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript
小刺猬_98527 分钟前
(超详细)数组方法 ——— splice( )
前端·javascript·typescript
渊兮兮29 分钟前
Vue3 + TypeScript +动画,实现动态登陆页面
前端·javascript·css·typescript·动画