当前位置: 首页 > web >正文

vue3图标终极方案【npm包推荐】vue3-icon-sui(含源码详解)

简介

为彻底实现 vue3 项目图标自由,特开发此 npm包 vue3-icon-sui,全品类图标,通通支持!

  • iconify 图标
  • svg 图标
  • font-class 图标

安装

npm i vue3-icon-sui -S

使用

按需导入

任意页面中

import myIcon from "vue3-icon-sui";

myIcon 可为任意自定义的组件名称

全局注册

src/main.ts

import myIcon from "vue3-icon-sui";const app = createApp(App);
app.component("myIcon", myIcon);

iconify 图标

  • 必要传参 icon – iconify 官网图标的名称,支持翻转 flip
    • 水平翻转 “horizontal”
    • 垂直翻转 “vertical”
    • 水平垂直翻转 “horizontal vertical”
  1. 在 iconify 官网搜索想要的图标
    https://icon-sets.iconify.design/?query=home

在这里插入图片描述
2. 页面中使用
传给属性 icon

<myIcon icon="ic:baseline-home" color="red" size="36" />

在这里插入图片描述

svg 图标(支持多彩)

  • 必要传参 name – 项目的 src/assets/icons/svg 目录中svg 图标的名称
  1. 从https://www.iconfont.cn/ 中找到喜欢的图标
    在这里插入图片描述
    鼠标悬浮其上时,点击下载

    在这里插入图片描述
    在这里插入图片描述

    可直接下载svg,将其放入项目的 src/assets/icons/svg 目录中,改名为 nice.svg

    也可以复制 svg 代码,新建 src/assets/icons/svg/nice.svg 文件,再将 svg 代码粘贴到 nice.svg 中

  2. 页面中使用
    将 svg 图标的名称传给属性 name

    <myIcon name="nice" size="36" />
    

    效果如下
    在这里插入图片描述
    传入 color 可自定义颜色,但会丧失多彩

    <myIcon name="nice" size="36" color="red" />
    

    在这里插入图片描述

font-class 图标

  1. 从https://www.iconfont.cn/ 中找到喜欢的图标
    在这里插入图片描述

鼠标悬浮其上时,点击添加入库
在这里插入图片描述

在这里插入图片描述

加入已有项目,或新建项目

在这里插入图片描述
在这里插入图片描述
得到 url

//at.alicdn.com/t/c/font_2261937_vumtsyzbq7d.css

鼠标悬浮在项目的图标上,可一键复制代码,得到 type

icon-nice

在这里插入图片描述

  1. 页面中使用
    必传参数 url 和 type

      <myIconurl="//at.alicdn.com/t/c/font_2261937_vumtsyzbq7d.css"type="icon-nice"size="36"color="red"/>
    

    在这里插入图片描述

属性

属性名属性值说明
iconiconify 官网图标的名称,如 “ic:baseline-home”iconify图标必传
flip水平翻转 “horizontal”
垂直翻转 “vertical”
水平垂直翻转 “horizontal vertical”
仅iconify图标支持
name项目的 src/assets/icons/svg 目录中svg 图标的名称svg图标必传
rotate旋转度数,数值即可,如 90 即顺时针旋转90度所有图标都支持
color颜色,如 red所有图标都支持,但svg的多彩图标会变为纯色
size大小,数值,如 36 即 36px所有图标都支持
urlfont-class图标的css地址,详见使用范例font-class图标必传
typefont-class图标的代码,详见使用范例font-class图标必传
fontFamilyfont-class图标的前缀除非在项目设置中进行了修改,否则使用默认的 icon-font 即可

font-class 图标自定义fontFamily

在这里插入图片描述

在这里插入图片描述
通常不建议修改!

假设修改为 myfont ,则页面使用时,fontFamily属性需传入 myfont

  <myIconurl="//at.alicdn.com/t/c/font_2261937_vumtsyzbq7d.css"type="icon-nice"fontFamily="myfont"/>

源码

详解见源码注释

<script setup lang="ts">
// 优先推荐【iconify图标】必要传参 icon ,支持翻转 flip
// 搜索图标 https://icon-sets.iconify.design/// 【svg图标-支持多彩图标】必要传参 name
// 需将svg图标放在 src/assets/icons/svg 目录中,// 【font图标-不支持多彩图标】必要传参 url 和 type
// 整个项目使用多个图标时,只需有一个图标传入 url 即可import { computed, onBeforeMount, ref, watch, onMounted } from "vue";
import { Icon } from "@iconify/vue";// 接收的属性
const props = defineProps({icon: {type: String,},// 水平翻转 "horizontal"// 垂直翻转 "vertical"// 水平垂直翻转 "horizontal vertical"flip: {type: String,},name: {type: String,},// 旋转角度rotate: {type: Number,},// 图标颜色color: {type: String,},// 图标大小size: {type: [Number, String],default: 16,},url: {type: String,default: "//at.alicdn.com/t/c/font_2261937_dg35xe8b86.css",},type: {type: String,},fontFamily: {type: String,default: "iconfont",},
});onBeforeMount(() => {if (props.url) {const existingLink = document.querySelector(`link[href="${props.url}"]`);if (!existingLink) {const link = document.createElement("link");link.href = props.url;link.rel = "stylesheet";document.head.appendChild(link);}}
});const className = computed(() => `${props.fontFamily} ${props.type}`);// 计算样式
const newStyle = computed(() => {const style: Record<string, string | number> = {};if (props.size) {style.width = `${props.size}px`;style.height = `${props.size}px`;}if (props.color) {style.color = props.color;}if (props.rotate) {style.transform = `rotate(${props.rotate}deg)`;}return style;
});// 状态管理
const svgContainer = ref<HTMLDivElement>();
const loading = ref(true);
const error = ref(null);// 加载并渲染SVG的函数
const loadAndRenderSvg = async () => {try {// 重置状态loading.value = true;error.value = null;// 使用动态import导入SVG文件,获取原始内容// 加上 ?raw 后,Vite 会直接将 SVG 文件的内容以纯文本字符串的形式返回const svgUrl = "/src/assets/icons/svg/" + props.name + ".svg";const module = await import(svgUrl + "?raw");const svgContent = module.default;// 清空容器if (svgContainer.value) {(svgContainer.value as any).innerHTML = "";}// 创建临时元素解析SVG内容const tempDiv = document.createElement("div");tempDiv.innerHTML = svgContent;// 获取SVG元素const svgElement = tempDiv.querySelector("svg");if (!svgElement) {throw new Error("导入的文件不是有效的SVG");}// 设置SVG属性svgElement.setAttribute("width", props.size + "px");svgElement.setAttribute("height", props.size + "px");if (props.color) {// 替换SVG颜色replaceSvgFillColor(svgElement, props.color);// svg 图片本身没有 fill 时,添加fillsvgElement.setAttribute("fill", props.color);}// 将SVG元素添加到容器if (svgContainer.value) {svgContainer.value.appendChild(svgElement);}} catch (err: any) {error.value = err.message || `无法加载图标: ${props.name}`;} finally {loading.value = false;}
};/*** 替换SVG元素的fill颜色值* @param svgElement 目标SVG元素* @param newColor 新的颜色值(可以是十六进制、rgb、rgba或颜色名称)* @returns 是否成功替换颜色*/
function replaceSvgFillColor(svgElement: SVGElement,newColor: string
): boolean {if (!svgElement) {return false;}try {// 查找所有带有fill属性的路径元素const pathElements = svgElement.querySelectorAll("path[fill]");if (pathElements.length === 0) {return false;}// 替换每个path元素的fill属性pathElements.forEach((path) => {path.setAttribute("fill", newColor);});return true;} catch (error) {return false;}
}// 监听props变化,重新加载图标
watch(() => [props.name, props.size, props.color],() => {loadAndRenderSvg();}
);// 组件挂载时加载图标
onMounted(() => {if (props.name) {loadAndRenderSvg();}
});
</script><template><Iconv-if="props.icon":icon="props.icon":style="newStyle":flip="props.flip"/><template v-else-if="props.name"><!-- 加载状态 --><div v-if="loading" class="loading">加载中...</div><!-- 错误状态 --><div v-if="error" class="error">图标加载失败: {{ error }}</div><!-- SVG容器 - 动态渲染的SVG将插入到这里 --><div ref="svgContainer" v-else></div></template><iv-else="props.type":class="className":style="{fontSize: props.size + 'px',color: props.color,...newStyle,}"style="display: inline-block"></i>
</template>
http://www.xdnf.cn/news/20474.html

相关文章:

  • STM32F4芯片RS485使用记录
  • 小迪自用web笔记29
  • 少儿配音教育:广州声与色在线科技有限公司打造趣味课程,助力青少年语言能力提升
  • 电脑外接显示屏字体和图标过大
  • 实体商业创新观察:AI 驱动的本地生活服务新模式解析
  • 计算机网络:物理层---物理层的基本概念
  • OpenSSL 1.0.1e 下载解压和运行方法(小白适用 附安装包)​
  • Nginx性能调优:参数详解与压测对比
  • 小孔成像原理
  • 吴恩达机器学习(九)
  • 正态分布 - 正态分布的标准化
  • 音视频技术全景:从采集到低延迟播放的完整链路解析
  • 【鸿蒙 NEXT】V1迁移V2状态管理
  • VMWare和centOS的安装
  • 集成学习 —— 梯度提升树GBDT、XGBoost
  • Javaweb 14.4 Vue3 视图渲染技术
  • 【MySQL | 高级篇 分片规则与管理监控】
  • 从Java全栈到前端框架的全面实战:一次真实面试的深度解析
  • c++ sqlite3库
  • CentOS下Bind服务的安装与故障排查
  • pyAutoGUI 模块主要功能介绍-(1)鼠标功能
  • 从 Excel 趋势线到机器学习:拆解 AI 背后的核心框架​
  • 数位DP -
  • 【明道云】[工作表控件11] 地理位置控件与地图定位应用
  • 用内存顺序实现 三种内存顺序模型
  • 安装es和kibana
  • Linux之Firewalld防火墙实战篇
  • [光学原理与应用-435]:晶体光学 - 晶体的结构-基元/原胞/晶胞/点阵
  • 多次base64编码过滤垃圾字符
  • 讲一下模版特化和偏特化的区别