所有分类
  • 所有分类
  • 后端开发

如何在Vue种使用类似于Font的SVG图标系统

如何在Vue中使用类似Font的SVG图标系统?让我们今天了解一下!!!

做过VUE项目的童鞋可能已经经历过了,有时在VUE应用程序中很难管理图标的自定义集合。图标字体很容易使用,但你必须依靠第三方字体生成器进行自定义,并且可能很难解决合并冲突,因为字体是一个二进制文件。

相反,使用SVG文件可以消除这些痛点,但我们如何确保它们同样容易使用,并且可以轻松地添加或删除图标呢?

这是我理想图标系统的外观:

  • 添加图标,只需将其放入指定的图标中icons文件夹中。如果不再需要图标,只需删除即可。

  • 在模板中使用robott.SVG图标,语法很简单<svg-icon icon="rocket" />

  • 可使用CSS font-sizecolor属性(像图标字体一样)缩放和着色图标。

  • 如果同一图标的多个例子出现在页面上,SVG代码不会每次都重复。

  • 无需编辑Webpack配置。

这是我们通过编写两个小的单文件组件来构建的。虽然我相信您的许多导游可以重新设计其他框架和构建工具:

  • webpack:假如你使用Vue CLI构建应用程序意味着您已经在使用webpack。

  • svg-inline-loader:这样我们就可以加载所有的SVG代码,清理不必要的部分。继续并继续npm install svg-inline-loader --save-dev从终端运行开始。

SVG Sprite组件

为了满足我们对页面上每个图标实例不重复SVG代码的要求,我们需要建立一个SVG“精灵”。如果您以前从未听说过SVG子图片,请将其视为包含其他SVG的隐藏SVG。我们可以引用任何需要显示图标的地方<use>将标签中的图标ID复制到sprite以外,如下所示:

<svg><use xlink:href="#rocket" /></svg>

这个代码本质上是我们的<SvgIcon>组件的工作模式,但让我们继续先创建它<SvgSprite>组件。这是整个SvgSprite.vue文件;起初,它似乎有点令人生畏,但我把它分解了。

<!-- SvgSprite.vue -->

<template>
  <svg width="0" height="0" style="display: none;" v-html="$options.svgSprite" />
</template>

<script>
const svgContext = require.context(
  '!svg-inline-loader?'   
  'removeTags=true'   // remove title tags, etc.
  '&removeSVGTagAttrs=true'   // enable removing attributes
  '&removingTagAttrs=fill'   // remove fill attributes
  '!@/assets/icons', // search this directory
  true, // search subdirectories
  /\w \.svg$/i // only include SVG files
)
const symbols = svgContext.keys().map(path => {
  // get SVG file content
  const content = svgContext(path)
   // extract icon id from filename
  const id = path.replace(/^\.\/(.*)\.\w $/, '$1')
  // replace svg tags with symbol tags and id attribute
  return content.replace('<svg', `<symbol id="${id}"`).replace('svg>', 'symbol>')
})
export default {
  name: 'SvgSprite',
  svgSprite: symbols.join('\n'), // concatenate all symbols into $options.svgSprite
}
</script>

在模板中,我们的lone <svg>元素的内容绑定到$options.svgSprite。假如你不熟悉$options它包含直接附加到我们的Vue组件中的属性。我们可以添加它svgSprite到组件的data,但我们真的不需要Vue来设置响应性,因为我们的SVG加载器只在构建应用程序时运行。

我们在脚本中使用它require.context在使用时检索所有SVG文件并清理它们。svg-inline-loader使用与查询字符串参数非常相似的语法来调用和传递几个参数。我把它们分成多行,让它们更容易理解。

const svgContext = require.context(
  '!svg-inline-loader?'   
  'removeTags=true'   // remove title tags, etc.
  '&removeSVGTagAttrs=true'   // enable removing attributes
  '&removingTagAttrs=fill'   // remove fill attributes
  '!@/assets/icons', // search this directory
  true, // search subdirectories
  /\w \.svg$/i // only include SVG files
)

我们在这里基本上要做的就是清理位于特定目录中的SVG文件(/assets/icons在任何需要的地方使用它们都处于良好的状态。

removeTags我们不需要为我们的图标删除参数标签,如果没有titlestyle。我们特别想删除它title因为这些标签可能会导致不必要的工具提示。如果您想在图标中保留任何硬编码样式,请添加removingTags=title作为附加参数,只能使用title删除标记。

我们还告诉加载程序删除fill属性,以便fill以后可以使用CSS 设置自己的颜色。你可能想保留自己fill颜色。在这种情况下,只需删除即可removeSVGTagAttrsremovingTagAttrs参数。

SVG图标文件夹的路径是最后一个加载程序参数。然后require.context,为了搜索子目录,只加载SVG文件,我们提供了另外两个参数。

为了在SVG精灵中嵌入所有的SVG元素,我们必须将它们从<svg>将元素转换为SVG <symbol>元素。这就像改变标签并赋予每个标签独特性一样简单id,然后从文件名中提取唯一性。

const symbols = svgContext.keys().map(path => {
  // extract icon id from filename
  const id = path.replace(/^\.\/(.*)\.\w $/, '$1')
  // get SVG file content
  const content = svgContext(path)
  // replace svg tags with symbol tags and id attribute
  return content.replace('<svg', `<symbol id="${id}"`).replace('svg>', 'symbol>')
})

如何处理这个问题?<SvgSprite>组件?我们把它放在我们页面上所有依赖它的图标之前。我建议将其添加到App.vue文件的顶部。

<!-- App.vue -->
<template>
  <div id="app">
    <svg-sprite />
<!-- ... -->

图标组件

现在,让我们建造它SvgIcon.vue组件。

<!-- SvgIcon.vue -->

<template>
  <svg class="icon" :class="{ 'icon-spin': spin }">
    <use :xlink:href="`#${icon}`" />
  </svg>
</template>

<script>
export default {
  name: 'SvgIcon',
  props: {
    icon: {
      type: String,
      required: true,
    },
    spin: {
      type: Boolean,
      default: false,
    },
  },
}
</script>

<style>
svg.icon {
  fill: currentColor;
  height: 1em;
  margin-bottom: 0.125em;
  vertical-align: middle;
  width: 1em;
}
svg.icon-spin {
  animation: icon-spin 2s infinite linear;
}
@keyframes icon-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(359deg);
  }
}
</style>

这个组件要简单得多。如前所述,我们使用它<use>引用精灵中的ID进行标记。然后id来自我们的组件icon道具。

spin在那里加一个道具,可以根据需要切换.icon-spin类作为动画的可选位置。例如,这可能对加载微调图标非常有用。

<svg-icon v-if="isLoading" icon="spinner" spin />

根据您的需要,您可能需要添加其他道具,例如rotateflip。在不使用道具的情况下,可以根据需要直接将类添加到组件中。

我们组件的大部分内容是CSS。除了旋转动画,大多数动画都被用来使我们的SVG图标更像图标字体。为了使图标与文本基线对齐,我发现它可以在大多数情况下应用vertical-align: middle,底边0.125em为了。我们还会fill属性值设置为currentColor,这使我们能够像文本一样为图标着色。

<p style="font-size: 2em; color: red;">
  <svg-icon icon="exclamation-circle" /><!-- This icon will be 2em and red. -->
  Error!
</p>

只是!如果您想在应用程序中的任何位置使用图标组件,并且不需要将其导入需要它的每个组件,请确保在main.js该组件在文件中注册:

// main.js
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon.vue'
Vue.component('svg-icon', SvgIcon)
// ...

image-9.png

总结

这里有一些改进的想法,我故意遗漏了一些,使解决方案易于处理:

  • 具有非正方形尺寸的缩放图标以保持其比例

  • SVG无需其他组件即可使用 将Sprite注入页面。

  • 与vite一起使用vite,vite是vue创作者Evann You是一种新的、快速的(而且没有webpack)建筑工具。

  • 利用Vue 3 Composition API。

如果你想快速使用这些组件,我已经基于默认的vue-cli模板创建了一个演示应用程序。如果你对DEMO感兴趣,你可以添加一个小组来讨论源代码,我希望这能帮助你开发适合你的应用程序需求的实现!

原文链接:https://www.icz.com/technicalinformation/web/svg/2023/05/9355.html,转载请注明出处~~~
0
注意:请收藏好网址www.icz.com,防止失联!站内免费资源持续上传中…!赞助我们
显示验证码
没有账号?注册  忘记密码?