H5 SVG 使用方式總結(jié)

實(shí)際工作中,SVG大多數(shù)是用<svg>+<defs></defs>(或者symbol)+<use></use>+</svg>的組合來使用的砌梆,defs 顧名思義就是「definitions」定義岗照,我們可以把許多重復(fù)性質(zhì)高的元素,放入defs 元素內(nèi)鲫懒,讓它變成一個(gè)可以重復(fù)利用的物件蚁堤。而symbol更多的只是包含單個(gè)圖標(biāo)醉者。

1、SVG使用方式

不論哪種方式披诗,svg都必須作為根標(biāo)簽

  • 外鏈方式
    這種方式是先定義好一個(gè)svg文件撬即,再在html或css中引入。
// test.svg
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
    <circle cx="100" cy="100" r="40" fill="red"></circle>
</svg>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>SVG</title>
</head>
<body>
         ![](test.svg)
</body>
</html>

外鏈的方式僅僅是將svg元素作為一個(gè)圖片呈队,無法利用JS對(duì)其做一些操作剥槐,如改變大小顏色等。

  • 內(nèi)聯(lián)方式
<div id="div1">
    <svg width="100%" height="100%" >
        <circle cx="100" cy="100" r="40" fill="red" id='circle'></circle>
    </svg>
</div>

內(nèi)聯(lián)方式可以向操作普通html元素一樣通過getElementById拿到dom掂咒,再通過setAttribute方法做屬性操作:

<script type="text/javascript">
      var c = document.getElementById('circle');
      c.setAttribute('fill','blue');
</script>

2、defs & use

  • 實(shí)例1:簡(jiǎn)單組合
<defs>
  <rect id="rect1" width="100" height="50" x="10" y="10" fill="#c00"/>
</defs>
<use xlink:href="#rect1"/>
<use xlink:href="#rect1" x="110"/>
基本組合
  • 實(shí)例2:復(fù)雜組合
<defs>
    <g id="g1">
          <rect id="rect1" width="100" height="50" x="10" y="10" fill="#c00"/>
          <circle id="circle1" cx="30" cy="30" r="10" fill="#00c"/>
    </g>
</defs>
<use xlink:href="#g1"/>
<use xlink:href="#rect1" x="110"/>
<use xlink:href="#circle1" x="210"/>
復(fù)雜組合
  • 實(shí)例3:漸變
<defs>
   <linearGradient id="a1">
     <stop offset="5%" stop-color="#F00" />
     <stop offset="95%" stop-color="#ff0" />
   </linearGradient>
</defs>
<rect x="50" y="250" width="100" height="100" stroke="#000" stroke-width="5" fill="url(#a1)"></rect>
<circle cx="220" cy="300" r="50" stroke="#000" stroke-width="5" fill="url(#a1)"></circle>
<rect x="290" y="250" width="100" height="100" stroke="url(#a1)" stroke-width="5" fill="none"></rect>
漸變
  • 實(shí)例4:路徑
<defs>
  <path id="a1" d="M0 50 C150 150 100 -50 300 50" stroke="#000" fill="none"/>
</defs>
<text>
   <textPath xlink:href="#a1">這是隨路徑跑的文字迈喉,很酷吧
  </textPath>
</text>
路徑
  • 實(shí)例5:裁切
<defs>  
  <clipPath id="a1">
  <rect x="0" y="0" width="200" height="100" />
</clipPath>
</defs>
<circle cx="100" cy="100" r="100" clip-path="url(#a1)" fill="#000" />
裁切
  • 實(shí)例6:遮罩
<defs>
  <mask id="mask1"> 
    <rect  x="50" y="50" width="100" height="100" fill="#ccc"/>
    <rect  x="150" y="150" width="50" height="50" fill="#fff"/>
  </mask> 
</defs>
  <rect id="box1" x="50" y="50" width="150" height="150" fill="#0f0"/>
  <rect id="box2" x="50" y="50" width="150" height="150" fill="#f00" mask="url(#mask1)"/>
遮罩
  • 實(shí)例7:標(biāo)志marker
<defs>
  <marker id="r" viewBox="-10 -10 70 70" refX="25" refY="25" markerWidth="15" markerHeight="15" orient="auto" >
      <circle fill="#fff" stroke="#000" stroke-width="10" cx="25" cy="25" r="25"/>
  </marker>
    <marker id="g" viewBox="0 0 50 50" refX="25" refY="25" markerWidth="10" markerHeight="10" orient="45" >
      <rect fill="#0a0" width="50" height="50"/>
  </marker>
  <marker id="b" viewBox="-10 -10 70 70" refX="25" refY="25" markerWidth="15" markerHeight="15" orient="auto" >
      <circle fill="#f99" stroke="#f00" stroke-width="10" cx="25" cy="25" r="25"/>
  </marker>
</defs>
<polyline points="20,100 50,100 80,20 110,80 140,30 170,100 200,100" fill="none" stroke="black" stroke-width="1" marker-end="url(#b)" marker-start="url(#r)" marker-mid="url(#g)"></polyline>
marker
  • 實(shí)例8:濾鏡
<defs>
<filter width="200" height="200" x="0" y="0" id="blur" filterUnits="userSpaceOnUse">
  <feGaussianBlur stdDeviation="5" />
</filter>
</defs>
<rect x="30" y="30" width="70" height="70" fill="#a00" filter=url("#blur") />
濾鏡

3绍刮、控制svg

  • CSS 方式
    svg元素和html元素一樣,都可以用class屬性添加類名來控制樣式挨摸,只是對(duì)于svg元素而言孩革,可控制的樣式較少,常見的有fill,stroke,stroke-width
    ,opacity以及transform得运,看一個(gè)例子:
    //定義區(qū)
    <svg>
      <symbol id="ic"> 
          <path fill="#000" d="..."/> 
      </symbol> 
    </svg>
    //使用區(qū)
    <svg class="icon" viewBox="0 0 100 125"> 
       <use class="ic-1" xlink:href="#ic" x="0" y="0" /> 
    </svg> 
    <svg class="icon" viewBox="0 0 100 125">
       <use class="ic-2" xlink:href="#ic" x="0" y="0" />
    </svg>
    //定義樣式
    .icon { width: 100px; height: 125px; }
    use.ic-1 { fill: skyblue; } 
    use.ic-2 { fill: #FDC646; }
    svg path { fill: inherit; }    //防止.ic-1,.ic-2設(shè)置的fill被path覆蓋
    

symbol元素和defs差不多膝蜈,都是用來組合元素的,但symbol更多的用于單個(gè)圖標(biāo)的組合

  • JS 方式
    要在SVG內(nèi)動(dòng)態(tài)新增<path>或<rect>等元素熔掺,要使用createElementNS饱搏,而不是createElement,因?yàn)閟vg和html不在同一個(gè)命名空間里置逻。
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    </head>
    <body>
        <svg id="s" xmlns="http://www.w3.org/2000/svg"/>
        <script type="text/javascript">
            function makeSVG(tag, attrs) {
                var el= document.createElementNS('http://www.w3.org/2000/svg', tag);
                for (var k in attrs)
                    el.setAttribute(k, attrs[k]);
                return el;
            }
            var circle= makeSVG('circle', {cx: 100, cy: 50, r:40, stroke: 'black', 'stroke-width': 2, fill: 'red'});
            document.getElementById('s').appendChild(circle);
        </script>
    </body>
    </html>
    

4推沸、svg最佳實(shí)踐

在工作中svg使用最多的場(chǎng)景還是當(dāng)小圖標(biāo)使用,替換諸如純圖片、iconfont圖標(biāo)等方案鬓催。使用內(nèi)聯(lián)svg的優(yōu)勢(shì)在于:1肺素、少發(fā)一次http請(qǐng)求;2宇驾、放大不會(huì)變形倍靡;3、易于用JS控制课舍,比iconfont更靈活塌西。

最佳做法(SVG sprite):

  • 1、將所有需要用到的小圖標(biāo)統(tǒng)一定義在svg下布卡,該svg要設(shè)置display:none雨让,每個(gè)小圖標(biāo)用symbol包圍,每個(gè)symbol取一個(gè)id忿等,方便后續(xù)調(diào)用栖忠;
  • 2、使用svg+use的方式調(diào)用贸街,use中用屬性xlink:href='#id'來引用相應(yīng)圖標(biāo)庵寞,可以給每個(gè)svg取一個(gè)類名,方便css和js動(dòng)態(tài)控制薛匪;
  • 3捐川、通過getElementById的方式獲取需要改變屬性的use元素,為其動(dòng)態(tài)添加或刪除相應(yīng)的類名逸尖;
  • 4古沥、添加的類名最終是運(yùn)用在symbol上,symbol中定義的圖標(biāo)(path)會(huì)覆蓋類名中對(duì)應(yīng)的屬性娇跟,所以不要忘了設(shè)置symbol中元素的屬性繼承自symbol岩齿,就像
    上例中:svg path { fill: inherit; };
  • 5苞俘、要想實(shí)現(xiàn)更為復(fù)雜的效果盹沈,如漸變等,可以使用defs吃谣;
  • 6乞封、要想做動(dòng)畫效果,可以在css類名中控制opacity岗憋、transform肃晚、stroke-dasharray和stroke-dashoffset屬性。

5仔戈、SVG動(dòng)畫

5.1 路徑動(dòng)畫

路徑動(dòng)畫基本是svg動(dòng)畫里最常用的了陷揪,其基本原理是動(dòng)態(tài)改變stroke-dasharray和stroke-dashoffset屬性的值:



實(shí)例:

<body>
    <svg>
        <symbol viewBox="0 0 24 20" id="ic" xmlns="http://www.w3.org/2000/svg">
            <title>點(diǎn)贊前</title>
            <path d="M22.825 6.727a6.236 6.236 0 0 0-1.8-3.818A5.275 5.275 0 0 0 17.36 1.44a5.275 5.275 0 0 0-3.667 1.47A11.134 11.134 0 0 0 12 5.09a11.134 11.134 0 0 0-1.692-2.18A5.275 5.275 0 0 0 6.64 1.44a5.275 5.275 0 0 0-3.667 1.47 6.236 6.236 0 0 0-1.8 3.817c-.044.546-.1 2.095 1.236 4.364 2.584 4.364 7.655 6.802 9.59 7.636 1.935-.834 7.006-3.272 9.59-7.636 1.337-2.27 1.28-3.83 1.235-4.364z" stroke="#454545" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" />
    </svg>
    <svg class="icon" viewBox="0 0 100 125">
        <use class="ic-1" xlink:href="#ic" x="0" y="0" />
    </svg>
</body>
    svg.icon {
        width: 120px;
        height: 135px;
    }
    use.ic-1 {
        stroke: gray;
        fill: gray;
        animation: move 3s linear forwards;
    }
    @keyframes move {
        0% {
            stroke-dasharray: 30px, 30px;
        }
        100% {
            stroke-dasharray: 30px, 0px;
        }
    }
    svg path {
        fill: inherit;
        stroke: inherit;
    }

效果就是stroke從30px長和30px空白逐漸變得沒有空白

5.2 SMIL動(dòng)畫(2018/1/1更新)

以上動(dòng)畫方式總是需要借助css來實(shí)現(xiàn)惋鸥,其實(shí)svg專門有做動(dòng)畫的元素
先看移動(dòng)端兼容性:


SVG SMIL animation
  • set
    在特定時(shí)間之后修改某個(gè)屬性值
    用法:
<svg width="320" height="320" xmlns="http://www.w3.org/2000/svg">
  <g> 
    <text font-family="microsoft yahei" font-size="120" y="160" x="160">
      馬
      <set attributeName="x" attributeType="XML" to="60" begin="3s" />
    </text>
  </g>
</svg>

這個(gè)「馬」會(huì)在3秒之后從橫坐標(biāo)160的位置移動(dòng)60這個(gè)位置(瞬移,無動(dòng)畫效果)

  • animate
    實(shí)現(xiàn)單屬性(不包含css的transform)的動(dòng)畫過渡效果
<svg width="320" height="320" xmlns="http://www.w3.org/2000/svg">
  <g> 
    <text font-family="microsoft yahei" font-size="120" y="160" x="160">
    馬
      <animate attributeName="x" from="160" to="60" begin="0s" dur="3s" repeatCount="indefinite" />
    </text>
  </g>
</svg>
  • animateTransform
    專用于transform動(dòng)畫
<svg width="320" height="320" xmlns="http://www.w3.org/2000/svg">
  <g> 
    <text font-family="microsoft yahei" font-size="80" y="100" x="100">馬</text>
    <animateTransform attributeName="transform" begin="0s" dur="3s"  type="scale" from="1" to="1.5" repeatCount="indefinite"/>
  </g>
</svg>
  • animateMotion
    專用于復(fù)雜的路徑動(dòng)畫
<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg">
  <text font-family="microsoft yahei" font-size="40" x="0" y="0" fill="#cd0000">馬
    <animateMotion path="M10,80 q100,120 120,20 q140,-50 160,0" begin="0s" dur="3s" repeatCount="indefinite"/>
  </text>
  <path d="M10,80 q100,120 120,20 q140,-50 160,0" stroke="#cd0000" stroke-width="2" fill="none" />
</svg>

5.3 小結(jié)

關(guān)于用svg做動(dòng)畫悍缠,更推薦用5.2的方式卦绣,并且5.2中animate的用法是最多的,animate元素還可以組合使用:

<svg width="320" height="200" xmlns="http://www.w3.org/2000/svg">
    <text font-family="microsoft yahei" font-size="120" y="160" x="160">馬
        <animate attributeName="x" from="160" to="60" begin="0s" dur="3s" repeatCount="indefinite" />
        <animate attributeName="opacity" from="1" to="0" begin="0s" dur="3s" repeatCount="indefinite" />
    </text>
</svg>

此外飞蚓,svg動(dòng)畫還可以手動(dòng)控制(JS)動(dòng)畫的開始和暫停

// svg指當(dāng)前svg DOM元素
// 暫停
svg.pauseAnimations();

// 重啟動(dòng)
svg.unpauseAnimations()

6滤港、參考:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末趴拧,一起剝皮案震驚了整個(gè)濱河市溅漾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌著榴,老刑警劉巖添履,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異脑又,居然都是意外死亡暮胧,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門问麸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來往衷,“玉大人,你說我怎么就攤上這事严卖∠幔” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵哮笆,是天一觀的道長来颤。 經(jīng)常有香客問我,道長稠肘,這世上最難降的妖魔是什么福铅? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮启具,結(jié)果婚禮上本讥,老公的妹妹穿的比我還像新娘珊泳。我一直安慰自己鲁冯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布色查。 她就那樣靜靜地躺著薯演,像睡著了一般。 火紅的嫁衣襯著肌膚如雪秧了。 梳的紋絲不亂的頭發(fā)上跨扮,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼衡创。 笑死帝嗡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的璃氢。 我是一名探鬼主播哟玷,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼一也!你這毒婦竟也來了巢寡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤椰苟,失蹤者是張志新(化名)和其女友劉穎抑月,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舆蝴,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谦絮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了须误。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挨稿。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖京痢,靈堂內(nèi)的尸體忽然破棺而出奶甘,到底是詐尸還是另有隱情,我是刑警寧澤祭椰,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布臭家,位于F島的核電站,受9級(jí)特大地震影響方淤,放射性物質(zhì)發(fā)生泄漏钉赁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一携茂、第九天 我趴在偏房一處隱蔽的房頂上張望你踩。 院中可真熱鬧,春花似錦讳苦、人聲如沸带膜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽膝藕。三九已至,卻和暖如春咐扭,著一層夾襖步出監(jiān)牢的瞬間芭挽,已是汗流浹背滑废。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留袜爪,地道東北人蠕趁。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像辛馆,于是被迫代替她去往敵國和親妻导。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容