
vue의 template부분에 직접적으로 svg파일을 사용하는 방식으로 크게 아래 두가지가 있다.
vue의 template안에 직접 <svg> 태그 작성
<img>태그의 src에 svg파일의 위치 연결
장점
어려움 없이 사용 가능
svg 코드 값을 직접 수정, 변수를 전달 가능
단점
vue에서 직접적으로 svg를 load 할 수 있도록 도와주는 vue-svg-loader 라이브러리가 있다.
<template>
<div>
<plus-svg>
</div>
</template>
<script lang="ts">
import PlusSvg from '@/icons/svg/Plus.svg';
export default defineComponent({
components: { PlusSvg, CheckBox },
props: {
},
})
</script>
장점
직관적이다.
가독성이 좋다.
단점
초기 설정해줘야 하는 부분들이 존재한다. 어렵진 않지만, 귀찮을 수 있다.
Vue컴포넌트 내의 변수를 Svg파일에 전달할 수가 없다. (e.g. 사이즈 변수 등)
Best Practice
Svg파일만을 위한 VueComponent를 만들고 이를 import해서 사용한다.
아래코드는 히어로즈아이콘에서 다운받은 Plus Svg 파일을 Vue 컴포넌트화한 예시이다.
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
:width="size"
:height="size"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2.5"
stroke-linecap="round"
stroke-linejoin="round"
class="feather feather-plus"
>
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'plusSvg',
props: {
size: { type: String, required: true },
},
setup() {
return {};
},
});
</script>
<style lang="scss"></style>
장점
props를 이용할 수 있다.
가독성이 좋다.
import가 직관적이다.
단점
<template>
<svg
:style="{ position: 'absolute', left: 0, top: 0, width: '100%', height: '100%', pointerEvents: 'none', zIndex: 200 }"
>
<defs>
<linearGradient
:id="gradientId"
x1="0"
y1="0"
x2="1"
y2="0"
>
<stop offset="0%" :stop-color="color" stop-opacity="0.6"/>
<stop offset="80%" :stop-color="color" stop-opacity="1"/>
<stop offset="100%" stop-color="#fff" stop-opacity="0.4"/>
</linearGradient>
<marker
id="arrowhead"
markerWidth="5"
markerHeight="5"
refX="2.5"
refY="1.5"
orient="auto"
markerUnits="strokeWidth"
>
<polygon points="0 0, 5 1.5, 0 3" :fill="color" />
</marker>
</defs>
<g>
<path
:d="path"
:stroke="'url(#' + gradientId + ')'"
stroke-width="3"
fill="none"
:style="animatedStroke"
marker-end="url(#arrowhead)"
/>
</g>
</svg>
</template>
<script>
export default {
props: {
path: {type: String, required: true},
color: {type: String, default: '#ff3333'},
isReverse: {type: Boolean, default: false}
},
data() {
return {
dashoffset: 0,
gradientId: 'flow-grad-' + Math.random().toString(36).substr(2,6)
}
},
computed: {
animatedStroke() {
return {
strokeDasharray: '11,9',
strokeDashoffset: `${this.isReverse ? -this.dashoffset : this.dashoffset}`,
transition: 'stroke-dashoffset 0.18s linear'
}
}
},
mounted() {
setInterval(() => {
this.dashoffset = (this.dashoffset + 3) % 20;
}, 45);
}
}
</script>
<AnimatedFlowArrow
path="M10,20 C30,10 60,10 80,20"
color="#00aaff"
/>