Write the Code. Change the World.

9月 04

https://github.com/vbenjs/vite-plugin-svg-icons/

创建一个空的 vue 项目

pnpm create vue

┌  Vue.js - The Progressive JavaScript Framework
◇  请输入项目名称:
│  vueSvg
│
◇  请输入包名称:
│  vuesvg
│
◇  请选择要包含的功能: (↑/↓ 切换,空格选择,a 全选,回车确认)
│  TypeScript, ESLint(错误预防), Prettier(代码格式化)
│
◇  选择要包含的试验特性: (↑/↓ 切换,空格选择,a 全选,回车确认)
│  none
│

正在初始化项目 C:\Users\Windows\Desktop\study\vue\primevue\vueSvg...
│
└  项目初始化完成,可执行以下命令:

   cd vueSvg
   pnpm install
   pnpm format
   pnpm dev

| 可选:使用以下命令在项目目录中初始化 Git:

   git init && git add -A && git commit -m "initial commit"

空的 vue 项目创建好后,开始安装 vite-plugin-svg-icons

安装配置 vite-plugin-svg-icons

安装

pnpm add -D vite-plugin-svg-icons

在 vite.config.ts 中配置。

import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'

plugins: [
    ……
    createSvgIconsPlugin({
    iconDirs: [fileURLToPath(new URL('./src/icons', import.meta.url))],
    symbolId: 'icon-[dir]-[name]',
    }),
]

在 ./src/main.ts 中添加。

import 'virtual:svg-icons-register'

新建组件 ./src/components/SvgIcon/SvgIcon.vue

<template>
  <svg :width="width" :height="height" aria-hidden="true">
    <use :href="symbolId" :fill="color" />
  </svg>
</template>

<script lang="ts" setup>
import { computed } from 'vue'

interface Props {
  prefix?: string
  name: string
  color?: string
  width?: string
  height?: string
}

const props = withDefaults(defineProps<Props>(), {
  prefix: 'icon',
  name: '',
  color: '#333',
  width: '20px',
  height: '20px',
})

const symbolId = computed(() => {
  return `#${props.prefix}-${props.name}`
})
</script>

再安装一个自动导入组件的插件(非必须)

pnpm add -D unplugin-vue-components

# 配置 vite.config.ts
import Components from 'unplugin-vue-components/vite'
plugins: [
    ……,
    Components({
      dirs: ['src/components'],
      extensions: ['vue'],
      deep: true,
      dts: true
    }),
]

https://www.iconfont.cn/ 上下载几个 svg 试试。具体点就从 https://www.iconfont.cn/illustrations/detail?spm=a313x.home_2025.i1.68.260f3a81Iah7ae&cid=52616 下载几只舔狗试试。

这里就下载了两个,分别叫 dog-1.svg,dog-2.svg,将这两个文件放到 ./src/icons/ 目录下。

在 App.vue 中添加测试代码。

  <div>
    <SvgIcon name="dog-1" width="120px" height="120px" />
    <SvgIcon name="dog-2" width="120px" height="120px" />
  </div>

运行 pnpm dev 看看效果。

搞个假的 loading

https://www.npmjs.com/package/vite-plugin-app-loading

<template>
  <h1>You did it!</h1>
  <p>
    Visit <a href="https://vuejs.org/" target="_blank" rel="noopener">vuejs.org</a> to read the
    documentation
  </p>

  <div>
    <SvgIcon name="dog-1" color="#000" width="120px" height="120px" />
    <SvgIcon name="dog-2" color="#000" width="120px" height="120px" />
  </div>

  <div class="loading" id="__app-loading__">
    <div class="loader"></div>
    <div class="title">Loading …</div>
  </div>
</template>

<script setup lang="ts">
import { onMounted } from 'vue'

onMounted(() => {
  setTimeout(() => {
    document.getElementById('__app-loading__')?.remove()
  }, 1000)
})
</script>

<style scoped>
html {
  line-height: 1.15;
}

.loading {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: #f4f7f9;
  transition: all 0.8s ease-out;
}

.loading.hidden {
  pointer-events: none;
  visibility: hidden;
  opacity: 0;
  transition: all 0.8s ease-out;
}

.dark .loading {
  background: #0d0d10;
}

.title {
  margin-top: 66px;
  font-size: 28px;
  font-weight: 600;
  color: rgb(0 0 0 / 85%);
}

.dark .title {
  color: #fff;
}

.loader {
  position: relative;
  width: 48px;
  height: 48px;
}

.loader::before {
  position: absolute;
  top: 60px;
  left: 0;
  width: 48px;
  height: 5px;
  content: '';
  background: hsl(var(--primary, 85 100% 50%) / 50%);
  border-radius: 50%;
  animation: shadow-ani 0.5s linear infinite;
}

.loader::after {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  content: '';
  background: hsl(var(--primary, 98 100% 50%));
  border-radius: 4px;
  animation: jump-ani 0.5s linear infinite;
}

@keyframes jump-ani {
  15% {
    border-bottom-right-radius: 3px;
  }

  25% {
    transform: translateY(9px) rotate(22.5deg);
  }

  50% {
    border-bottom-right-radius: 40px;
    transform: translateY(18px) scale(1, 0.9) rotate(45deg);
  }

  75% {
    transform: translateY(9px) rotate(67.5deg);
  }

  100% {
    transform: translateY(0) rotate(90deg);
  }
}

@keyframes shadow-ani {
  0%,
  100% {
    transform: scale(1, 1);
  }

  50% {
    transform: scale(1.2, 1);
  }
}
</style>

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注