天天看點

svg入門 第一節

目錄

什麼是SVG?

viewport和viewBox

preserveAspectRatio

Mid,Min,Max

meet,slice

demo案例

什麼是SVG?

  • SVG 指可伸縮矢量圖形 (Scalable Vector Graphics)
  • SVG 用來定義用于網絡的基于矢量的圖形
  • SVG 使用 XML 格式定義圖形
  • SVG 圖像在放大或改變尺寸的情況下其圖形品質不會有所損失
  • SVG 是網際網路聯盟的标準
  • SVG 與諸如 DOM 和 XSL 之類的 W3C 标準是一個整體

viewport和viewBox

學好svg需要先了解svg中的viewport和viewBox這兩個概念。

  • viewpart是整個svg的可見區域即svg标簽的寬高。
  • viewBox是svg在繪圖過程中使用的坐标系,viewBox存在于viewPort中。可以通過viewBox屬性設定viewBox的大小和在viewPort中的相對位置。如:下面的标簽表是svg畫布的大小為200px*200px,view Box位于viewpart坐标中的(0, 0)位置并且大小為100*100。
<svg width='200px' height='200px' viewBox='0 0 100 100'></svg>
           
svg入門 第一節

preserveAspectRatio

svg除了viewport和viewBox外還有一個比較重要的參數preserveAspectRatio主要是用在viewport和viewBox寬高比不一緻的情況,寬高比會影響svg的渲染。

預設情況下preserveAspectRatio="xMidYMid meet"表示viewBox位于viewport的中心位置,并且采用viewport和viewBox最小的寬高比。

Mid,Min,Max

對于x軸Mid表示viewBox位于viewport橫向位置的中間,Min表示位于viewport的最左邊,Max表示位于viewport的最右邊

對于y軸Mid表示viewBox位于viewport橫向位置的中間,Min表示位于viewport的最上邊,Max表示位于viewport的最下邊

meet,slice

meet代表選擇viewport和viewBox寬高比例較小的一個圖形可以按照比例縮小顯示。

slice代表選擇viewport和viewBox寬高比例較大的一個這可能會造成svg圖形過大最終超出viewport圖形被裁切。

demo案例

在了解完preserveAspectRatio和viewBox、viewport後基本上對svg的布局就可以大緻了解svg的布局原理了,下面是幾個demo

svg.vue

<template>
  <div>
    <svg
      width="100"
      height="100"
      style="display: none"
      viewBox="0 0 100 100"
      preserveAspectRatio="xMidYMid meet"
    >
      <defs>
        <g id='more'>
          <line x1='40' y1='25' x2='90' y2='25' stroke-width='8' stroke='currentColor'></line>
          <line x1='40' y1='50' x2='80' y2='50' stroke-width='8' stroke='currentColor'></line>
          <line x1='40' y1='75' x2='90' y2='75' stroke-width='8' stroke='currentColor'></line>
          <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='75' fill='currentColor'></circle>
        </g>
        <symbol id='more1' viewBox='0 0 100 100'>
          <line x1='40' y1='25' x2='90' y2='25' stroke-width='8' stroke='currentColor'></line>
          <line x1='40' y1='50' x2='80' y2='50' stroke-width='8' stroke='currentColor'></line>
          <line x1='40' y1='75' x2='90' y2='75' stroke-width='8' stroke='currentColor'></line>
          <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='75' fill='currentColor'></circle>
        </symbol>
        <symbol id='filledArrowRight' viewBox='0 0 100 100'>
          <polyline points='20 10, 80 50, 20 90' fill='currentColor'></polyline>
        </symbol>
        <symbol id='arrowRight' viewBox='0 0 100 100'>
          <polyline points='20 10, 60 50, 20 90' fill='transparent' stroke-width='8' stroke='currentColor'></polyline>
        </symbol>
        <linearGradient id='linearGradient'>
            <stop offset='0' stopColor='red'></stop>
            <stop offset='50%' stopColor='green' stopOpacity='0.5'></stop>
            <stop offset='100%' stopColor='blue'></stop>
        </linearGradient>
        <radialGradient r='50%' cx='50%' cy='50%' fx='50%' fy='50%' id='radialGradient'>
            <stop offset='0' stopColor='red'></stop>
            <stop offset='50%' stopColor='green' stopOpacity='0.5'></stop>
            <stop offset='100%' stopColor='blue'></stop>
        </radialGradient>
        <symbol id='linearGradientBox' viewBox='0 0 100 100'>
            <rect x='0' y='0' height='100' width='100' fill='url(#radialGradient)'></rect>
        </symbol>
      </defs>
    </svg>
    <span :style="{color: 'green'}">
      <svg width='100' height='100' viewBox='0 0 100 100'>
        <use href='#more'></use>
      </svg>
      <Icon :style="{width: 100, height: 100, color: 'red'}" :svgId="'more1'" />
      <Icon :style="{width: 100, height: 100, color: 'blue'}" :svgId="'arrowRight'" />
      <Icon :style="{width: 100, height: 100, color: 'yellow'}" :svgId="'filledArrowRight'" />
      <Icon style={{width: 100, height: 100}} svgId='linearGradientBox' />
    </span>
  </div>
</template>

<script >
import { defineComponent } from "vue";
import Icon from '@src/components/icon.vue'

export default defineComponent({
  name: "SVG",
  components: {
    Icon
  },
  setup: () => {
    return {};
  },
});
</script>

<style scoped>
</style>
           

icon.vue

<template>
  <svg :style="style">
    <use :href="`#${svgId}`" target="_blank" rel="external nofollow" ></use>
  </svg>
</template>

<script >
import { defineComponent } from "vue";

export default defineComponent({
  name: "icon",
  props: {
    svgId: {
      type: String,
      required: true,
    },
    style: {
      type: CSSStyleDeclaration, // CSSStyleDeclaration
      require: false
    }
  }
});
</script>
           
svg入門 第一節
svg入門 第一節

demo中用到了幾個比較常用的svg基本圖形

  line線

  rect矩形

  circle圓型

  defs可以将寫好的svg元件隐藏起來

    g可以設定id屬性即這是一個svg組合可以直接顯示symbol不能直接顯示

    symbol和g類似但是可以傳遞viewBox屬性這樣在使用的時候就不用再寫viewbox去适應圖示(實作的原理就是在套一層svg标簽)

  use可以使用定義好的svg組合(通過href='#id'使用)

  polyline多邊形

path

    d屬性

      M為開始Z為結束,沒有Z的話路徑就不回閉合。L10 10表示點坐标(10, 10)

mask蒙版類似ps的蒙版可以混合顔色 

linearGradient漸變色

  通過fill='url(#linearGradient)'的方式設定

  stop

    需要連續多個stop标簽,有offset='50%'位置、stop-color='red'對應的顔色、stop-opacity='0.5'透明度

radialGradient

  放射性漸變屬性同linearGradient

   r='50%'輻射半徑 cx='50%'外圈輻射 cy='50%'外圈輻射 fx='50%'内圈輻射 fy='50%'内圈輻射,預設都是50%

幾個值的注意的地方

  1.對線來說填充顔色不能用fill來填充需要用stroke來填充顔色,并且如果将顔色設定成currentColor即為繼承父元素的顔色(css中的color屬性)

  2.當我們自己想要寫svg樣式庫的時候可以使用defs将svg庫隐藏起來但是這裡仍然會占用文檔流的位置,可以将display:none将其隐藏掉

  3.封裝svg圖形的時候盡量使用symbol代替g(這也是iconfont建議的),因為為了在使用編輯好的svg圖示時g标簽還要額外去寫viewBox去适應圖示的縮放大小而symbol可以直接設定viewBox,這樣我們使用封裝好的svg組合時就可以直接通過組合的id使用圖示并且保證圖示的正常顯示。

  4.viewport是可以繼承父元素的寬高的隻要将svg标簽的width和height設定成100%即可

svg