引言

因为在使用 SVG 图标的是否发现 Base64 代码真的很不直观,想预览一个打开一个浏览器标签,于是就想着将这些都在一个页面预览不就好了?所以,通过 Trae 的助力,开发了这个 SVG 图标库。

预览地址:

让图标管理变得简单

有以下特点😂:

  • ✅ 显示SVG图标并支持点击复制base64编码
  • ✅ 支持提交新的SVG图标
  • ✅ 响应式设计,适配不同设备
  • ✅ 现代化的液态玻璃UI效果
  • ✅ 支持批量上传SVG图标
  • ✅ 自动检测重复图标
  • ✅ 支持多种输入格式(SVG代码、纯Base64编码、带data URL前缀的Base64编码)
  • ✅ 完善的表单验证和错误处理
  • ✅ CSRF防护确保安全

1. 直观的图标展示

SVG 图标库采用网格布局展示所有图标,每个图标都以卡片形式呈现,悬停时会有微妙的动画效果。用户可以一目了然地看到所有可用的图标,无需在无数个文件夹中翻找。

界面展示

SVG图标库主界面

2. 便捷的复制功能

用户只需点击图标,在弹出的模态框中点击相应按钮,就能:

  • 一键复制SVG代码,直接用于HTML
  • 一键复制Base64编码,带data URL前缀,可直接粘贴到CSS中
  • 复制成功后会显示通知提示,确保操作成功

界面展示

图标预览和复制界面

3. 图标添加功能

支持多种格式的输入:

  • 直接上传SVG代码
  • 上传Base64编码(带或不带data URL前缀)
  • 批量上传多个Base64编码(一次粘贴多个,系统自动处理)
  • 智能验证,确保SVG内容有效
  • 自动去重,防止重复图标

界面展示

SVG图标添加界面

4. 现代美观的界面

采用流行的液态玻璃 UI 设计风格,使用 backdrop-filter 和 box-shadow 实现现代化的模糊效果。界面简洁大方,动画流畅自然,响应式设计确保在手机、平板和桌面设备上都能完美展示。

界面展示

移动端适配界面

技术实现

前端技术

  • HTML5:语义化标签,良好的结构
  • CSS3:现代CSS特性,包括变量、动画、响应式设计
  • JavaScript (ES6+) :模块化代码组织,事件处理
  • 液态玻璃UI:使用backdrop-filter和box-shadow实现

后端技术

  • PHP 8.0+ :服务器端逻辑处理
  • 文件系统:存储SVG图标数据
  • 会话管理:实现PRG模式,防止表单重复提交

代码结构

svg/
├── index.php          # 主入口文件
├── icons.txt          # 存储SVG图标数据
├── includes/
│   ├── config.php     # 配置文件
│   ├── security.php   # 安全相关功能
│   └── svg_manager.php # SVG图标管理功能
└── assets/
    ├── css/
    │   └── style.css  # 样式文件
    └── js/
        └── script.js  # JavaScript文件

问题与解决方案

1. Cloudflare兼容性问题

问题表现:部署到使用 Cloudflare 加速的服务器后,点击图标或按钮没有反应,浏览器控制台显示 JavaScript 错误。

具体影响: 核心功能完全无法使用,用户无法预览或复制图标,也无法添加新图标等问题

技术原因:Cloudflare 的 Rocket Loader 功能会异步加载和执行 JavaScript 代码,干扰了事件监听器的绑定,导致事件处理函数无法正常触发。

解决思路

解决思路

  • 使用捕获阶段的事件监听器,避免事件冒泡被干扰
  • 实现双重初始化机制,确保代码在各种情况下都能正确初始化
  • 增强DOM元素检查,添加元素存在性检查和重试机制

代码示例

// 使用捕获阶段的事件监听器
this.DOM.iconGrid.addEventListener('click', (event) => {
    const card = event.target.closest('.icon-card');
    if (card) {
        event.stopPropagation();
        this.openPreviewModal(card);
    }
}, true); // 使用捕获阶段
// 初始化 - 使用更可靠的方式,避免Cloudflare干扰
(function() {
    // 等待DOM加载完成
    function initWhenReady() {
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', function() {
                SvgIconLibrary.init();
            });
        } else {
            SvgIconLibrary.init();
        }
    }    // 立即执行初始化
    initWhenReady();    // 额外的保险措施:延迟初始化,确保所有资源都已加载
    setTimeout(function() {
        if (!window.SvgIconLibrary || !window.SvgIconLibrary.DOM || Object.keys(window.SvgIconLibrary.DOM).length === 0) {
            console.log('Secondary initialization attempt');
            SvgIconLibrary.init();
        }
    }, 1000);
})();

2. ARIA可访问性问题

问题表现:浏览器控制台报 ARIA 可访问性错误,提示 "Blocked aria-hidden on an element because its descendant retained focus",影响网站的可访问性评分。

技术原因:当关闭模态框时,模态框中的按钮仍然保持焦点,而模态框被设置为 aria-hidden="true",违反了 WAI-ARIA 规范,因为辅助技术不应该将焦点隐藏在用户看不到的元素上。

解决思路

解决思路

  • 在关闭模态框之前,检查当前获得焦点的元素是否在模态框内
  • 如果焦点在模态框内,将焦点移到页面主体
  • 先处理焦点,再设置aria-hidden="true"

代码示例

closePreviewModal: function() {
    // 确保焦点不留在隐藏的元素中
    const focusedElement = document.activeElement;
    if (this.DOM.previewModal.contains(focusedElement)) {
        // 将焦点移到页面主体
        document.body.focus();
    }
  
    this.DOM.previewModal.classList.remove('show');
    this.DOM.previewModal.setAttribute('aria-hidden', 'true');
    // 等待动画完成后隐藏
    setTimeout(() => {
        this.DOM.previewModal.style.display = 'none';
        // 清除当前图标数据
        this.currentIconData = null;
    }, 300);
},

3. 字体加载问题

问题表现:网站加载时,浏览器控制台显示字体加载失败的错误,提示 "Failed to load resource: net::ERR_CONNECTION_CLOSED"。

技术原因:使用的国内一些字体库连接不稳定,导致字体无法正常加载,影响网站的视觉效果。

解决思路

解决思路

  • 尝试使用其他国内字体源,如百度字体库、360字体库、字节跳动
  • 最终选择使用Google Fonts官方CDN,虽然在国内可能有一些延迟,但稳定性更高

代码示例

<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@400;500;600;700&display=swap">

4. 表单重复提交问题

问题表现:用户提交表单后刷新页面,会导致表单重复提交,可能造成重复数据或其他意外行为。

技术原因:传统的表单提交方式会在页面刷新时重新发送请求,导致重复提交。

解决思路

解决思路

  • 实现PRG(Post-Redirect-Get)模式
  • 使用会话存储消息,重定向后显示
  • 确保表单提交后不会因为刷新而重复提交

代码示例

if ($successCount > 0) {
    $_SESSION['message'] = '成功添加 ' . $successCount . ' 个SVG图标!';
    // 重定向到同一个页面,防止重复提交
    header('Location: ' . $_SERVER['PHP_SELF']);
    exit;
}

结语

SVG 图标库是一个简洁、高效的工具,解决了前端开发中图标管理的实际问题。通过模块化的代码结构、现代化的 UI 设计、完善的功能实现以及与 Cloudflare 的兼容性优化,它为用户提供了一个高效、可靠的 SVG 图标管理解决方案。

git:[@github/NoEggEgg/svg-icon-library]