概要:因为数据大屏项目的一些动画效果都是通过svg来做的,所以有必要将svg封装成组件使用。另外对svg的基础知识做一个系统的学习。
svg优势
- 源代码是使用的是xml,容量小。
- svg比较灵活,可以自己修改样式。可以修改颜色,大小,缩放等
- SVG 与 PNG、JPEG 和 GIF 图片相比,拥有很小的尺寸;
- SVG 是矢量图,可以伸缩,适用各种分辨率;
- SVG 采用开放标准,本质是 XML,可以被各种工具读取(浏览器、图片管理器、markdown 等);
- SVG 图像中的文本是可选的,同时也是可搜索的;
- SVG 可以与 CSS 结合,获得更强的扩展性
svg 应用场景
绘制 icon、绘制动画
svg的viewport 和viewbox的概念
- viewport 是 svg 图像的可见区域
- viewBox 是用于在画布上绘制 svg 图形的坐标系统
viewport中的宽/viewBox中的宽 viewport中的高/viewBox中的高,这个比例就是svg中元素的宽高的放大缩小的比例,通过viewBox可以实现svg的一个缩放自适应。
// svg上的width height表示viewPort中的宽高
// 这个宽的比例是 500/50=10 高的比例是200/20=10 所以在网页上呈现的效果是一个10*10(rect的宽10)=100 10*5(rect的高5)=50 大小的一个rect
<svg width="500" height="200" viewBox="0 0 50 20" style="border: 1px solid #000000">
<rect x="20" y="10" width="10" height="5" style="stroke: #000000; fill:none;"/>
</svg>
svg中一个重要的属性preserveAspectRatio
preserveAspectRatio默认的值是 xMidYMid meet preserveAspectRatio 用于当 viewport 和 viewBox 宽高比不相同时(比如宽的比是10,高的比是15)会影响当前svg图形在viewBox中的位置。preserveAspectRatio决定svg在视口绘制的位置,决定viewBox在viewPort中绘制的位置。
- 第一个参数:表示viewBox在viewPort中x轴y轴存在的位置。
- 第二个参数:表示是否等比缩放,是的话取最大的缩放比还是最小的缩放比,不是的话就直接按照原来的缩放比进行缩放。 参数一有如下的设置情况
- x/y Mid 位置在viewBox的x/y轴的中间
- x/y Min 位置在viewBox的x/y轴的开头
- x/y Max 位置在viewBox的x/y轴的结尾 参数二如下设置情况
- meet: 保持宽高比并将viewBox缩放为适合viewport的大小。meet 模式下,svg 将优先采纳压缩比较小的作为最终压缩比,meet 是默认参数
- slice: 保持宽高比并将所有不在viewport中的viewBox剪裁掉。slice 模式下,svg 将优先采纳压缩比较大的作为最终压缩比
- none: 不保存宽高比。缩放图像适合整个viewbox,可能会发生图像变形。none 模式下,svg 将分别计算 x 和 y 轴的压缩比
<!--当viewBox和viewPort的宽高比不一致 宽的比 和高的比不一致的时候 -->
<!-- 此时宽的比是 2.5 高的比是1 preserveAspectRatio:xMidYMid meet
meet表示取最小的比例即1,
-->
<svg width="500" height="200" viewBox="0 0 200 200" style="border: 1px solid #000000" preserveAspectRatio="xMidYMid meet">
<rect x="100" y="100" width="100" height="50" stroke-width="10" style="stroke: #000000; fill:none;"/>
</svg>
<!--宽比是2.5 高的比是1 xMaxYMax 表示viewBox在viewPort的上方开始,slice取最大值2.5,所以rect的宽高分别是 250 125,viewBox的大小就边成了 500 500,rect是画在viewBox上的所以出现的情况如下图 -->
<svg width="500" height="200" viewBox="0 0 200 200" style="border: 1px solid #000000" preserveAspectRatio="xMaxYMax slice">
<rect x="100" y="100" width="100" height="50" stroke-width="10" style="stroke: #000000; fill:none;"/>
</svg>
svg组件库的封装方法
svg组件库在封装的时候,官方提供了defs标签, g标签, use 标签, symbol标签,用来封装svg库的一个方法。
第一步将svg放入到 def标签中
第二步在当前的组件svg前套一层g标签
g标签的作用是把当前的svg标签打包成一个固定的组件,并且在g标签上加上id,这个id就是用来调用svg组件的时候再use标签中使用的。
<svg width="0" height="0" viewBox="0 0 100 100">
<def>
<g id="moreTag">
<circle r="5" cx="20" cy="25" fill="currentColor"></circle>
<circle r="5" cx="20" cy="50" fill="currentColor"></circle>
<circle r="5" cx="20" cy="70" fill="currentColor"></circle>
<line x1="40" y1="25" x2="90" y2="25" stroke-width="8" stroke="currentColor"></line>
<line x1="40" y1="50" x2="70" y2="50" stroke-width="8" stroke="currentColor"></line>
<line x1="40" y1="75" x2="90" y2="75" stroke-width="8" stroke="currentColor"></line>
</g>
</def>
</svg>
第三步:引用的时候使用use进行引用
<svg width="XX" height="XX" viewBox="XXX">
<use href="#moreTag" />
</svg>
当使用g标签的时候,再使用use引用的时候,不仅需要设置当前svg图标组件的大小,还需要设置viewBox的大小。为此专门出现了symbol标签。
symbol 与 g 标签用法相同也是包在def下方,但 symbol 可以拥有一个独立的 viewBox, 将组件中的g替换成symbol,并且组件svg上不需要设置viewBox在symbol上设置即可,引用的时候用use引用不需要设置viewBox。这样用户就可以封装更通用的svg组件了。
<svg width="0" height="0" >
<def>
<symbol id="moreTag" viewBox="0 0 100 100">
<!-- <g id="moreTag"> -->
<circle r="5" cx="20" cy="25" fill="currentColor"></circle>
<circle r="5" cx="20" cy="50" fill="currentColor"></circle>
<circle r="5" cx="20" cy="70" fill="currentColor"></circle>
<line x1="40" y1="25" x2="90" y2="25" stroke-width="8" stroke="currentColor"></line>
<line x1="40" y1="50" x2="70" y2="50" stroke-width="8" stroke="currentColor"></line>
<line x1="40" y1="75" x2="90" y2="75" stroke-width="8" stroke="currentColor"></line>
<!-- </g> -->
</symbol>
<symbol id="cross" viewBox="0 0 100 100">
<line x1="50" y1="10" x2="50" y2="90" stroke-width="8" stroke="currentColor"></line>
<line x1="10" y1="50" x2="90" y2="50" stroke-width="8" stroke="currentColor"></line>
</symbol>
</def>
</svg>
引用的时候
<svg width="XX" height="XX">
<use href="#moreTag" />
</svg>
编写通用组件库Icon
icon/Icon.vue
<template>
<div class="iconWrapData" :style="{...style}">
<svg class="icon">
<use :href="iconClassName" />
</svg>
</div>
</template>
<script>
export default {
name: "Icon",
props: {
name: String,
style: Object,
},
setup(ctx) {
const iconClassName = `#${ctx.name}`
return {
iconClassName
}
},
}
</script>
<style lang="scss" scoped>
.icon {
width: 100%;
height: 100%;
/* vertical-align: -0.15em; */
fill: currentColor;
overflow: hidden;
}
.iconWrapData {
display: inline-block;
}
</style>
icon/indexd.js
import Icon from './Icon.vue'
export default function(Vue) {
Vue.component(Icon.name, Icon);
}
并且需要在index.js中注册一下src\index.js
import Icon from './component/Icon/index';
export default function(Vue){
Vue.use(Icon);
}
使用 iconfont 的正确姿势
- 方法一:集成 svg 图标 在iconfont官网中找到合适的 svg 图标,下载图标,复制图标的svg代码,并且将svg 代码集成到我们自己的组件库中,然后如果要用户随心的更改组件的颜色,需要在代码中增加或者修改组件的fill属性fill="currtetColor"。
- 方法二:创建 iconfont 项目 在 vue 项目中使用组件,但是对于大量图标的复杂项目对于这种方式一个个的集成图标是很低效的,实际项目中我们会通过创建 iconfont 项目进行操作。
打开Iconfont创建一个自己的项目,然后在iconfont官网上选择自己项目需要的图片下载svg图标。打开我的项目,选择上传到项目中。选择去除颜色并且上传。点击查看在线连接,选择symbol方式生成一个外部引用链接。然后在public的index.html文件中引入即可在项目中使用。