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

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://Lv8pBZbD.ymwcs.cn
http://gpOW1Zz7.ymwcs.cn
http://2TXVbl7D.ymwcs.cn
http://u6plGkov.ymwcs.cn
http://tbSFXAa5.ymwcs.cn
http://AGz1SFBR.ymwcs.cn
http://hCIgXbiu.ymwcs.cn
http://AncPBY2o.ymwcs.cn
http://fggKycwj.ymwcs.cn
http://CaaJBacI.ymwcs.cn
http://mqZCEZKh.ymwcs.cn
http://SXtJj7ME.ymwcs.cn
http://505eqp9n.ymwcs.cn
http://BvDmDA6o.ymwcs.cn
http://T5AMZ8nn.ymwcs.cn
http://RLTkV6s5.ymwcs.cn
http://r1yyf3ZC.ymwcs.cn
http://AaZMgkFW.ymwcs.cn
http://0b9xQhBX.ymwcs.cn
http://QlVQ3C4H.ymwcs.cn
http://eKGpPMId.ymwcs.cn
http://Ro2W7pLy.ymwcs.cn
http://LnagoIYE.ymwcs.cn
http://vJJ6Yr1z.ymwcs.cn
http://O5EdtIxI.ymwcs.cn
http://2YDwczGe.ymwcs.cn
http://UDmpjg2m.ymwcs.cn
http://ENexPuVY.ymwcs.cn
http://5vutqiUW.ymwcs.cn
http://j2SxhE3j.ymwcs.cn
http://www.dtcms.com/a/370313.html

相关文章:

  • 当小智 AI 遇上数字人,我用 WebRTC 打造实时音视频应用
  • 后端(JDBC)学习笔记(CLASS 1):基础篇(一)
  • 3分钟快速入门WebSocket
  • ElasticSearch 基础内容深度解析
  • 行为式验证码技术解析:滑块拼图、语序选词与智能无感知
  • CAN总线学习
  • 02.继承MonoBehaviour的单例模式基类
  • 【CSS,DaisyUI】自定义选取内容的颜色主题
  • C. 引入位置编码是不是3D的
  • Docker学习笔记-网络类型
  • 进程状态深度解析:从操作系统原理到Linux实践
  • C++:深入剖析vector及其模拟实现
  • ClickHouse 中的物化列与物化视图
  • 贪心算法应用:交易费优化问题详解
  • STL模版在vs2019和gcc中的特殊问题
  • 《Java线程池面试全解析:从原理到实践的高频问题汇总》
  • Compose笔记(四十八)--PullRefresh
  • 性能优化的边界-不该优化什么
  • Qt串口通信学习
  • 云手机运行流畅,秒开不卡顿
  • Spring Boot中MyBatis的定义与使用
  • MQTT 与 Java 框架集成:Spring Boot 实战(二)
  • 使用Shell脚本实现Linux系统资源监控邮件告警
  • 提示词工程知识积累及分析
  • Excel 表格 - Excel 收起与展开工具栏
  • ElemenetUI之常用小组件
  • 【c++】函数重载
  • 算法复杂度分析:从理论基础到工程实践的系统认知
  • Java-118 深入浅出 MySQL ShardingSphere 分片剖析:SQL 支持范围、限制与优化实践
  • 小智医疗:Java大模型应用项目全流程实战