xmlplus 組件設計系列之一 - 圖標(ICON)

圖標

網頁上使用的圖標分可爲三種:文件圖標、字體圖標和 SVG 圖標。對於文件圖標,下面僅以 PNG 格式來講明。css

<img src="http://xmlplus.cn/img/icon.png" class="img-responsive"/>html

PNG 圖標

對於 PNG 圖標的引用,有兩種方式。一種是直接由 HTML 元素 img 的 src 屬性給出。下面是一個簡單的示例。瀏覽器

// 01-01
Icon: {
    css: `#icon { width: 68px; height: 68px; }`,
    xml: `<img id='icon'/>`,
    fun: function (sys, items, opts) {
        this.attr("src", "img/" + this + ".png");
    }
}

這個示例的圖標文件位於組件所在文件的子級目錄 img/ 中。咱們能夠按以下的方式便捷地引用所需的圖標。注意組件 Icon 巧妙地使 id 屬性值與圖片文件名關聯,這樣能夠避免建立額外的屬性。svg

// 01-01
<div id='index'>
    <Icon id='msg'/>
    <Icon id='home'/>
    <Icon id='contact'/>
</div>

另外一種引用 PNG 圖標的方式是給相應的對象添加 background-image 樣式,而且由樣式中給出圖標所在路徑。下面是一個簡單的示例。函數

// 01-02
Icon: {
    css: `#icon { width: 68px; height: 68px; }`,
    xml: `<div id='icon'/>`,
    fun: function (sys, items, opts) {
        this.css("background-image", "url(img/" + this + ".png)");
    }
}

這種形式與前面由 img 標籤給出的圖標有許多類似之處。不一樣的是,前者動態指定的是 img 標籤的 src 值 ,然後者動態指定的則是 div 元素的 css 樣式。該組件與前面給出的 Icon 組件的使用方式徹底一致,這裏就不重複了。組件化

對於以上給出的組件 Icon,使用的是離散的圖標文件。實際應用中,一般給出的是一個包含許多圖標的 PNG 文件。這種狀況下該如何構建圖標組件呢?請看下面給出的一種較爲實用的方案。性能

// 01-03
Icon: {
    css: `#msg { background-position:  0 0; }
          #home { background-position: 0 -48px; }
          #contact { background-position: 0 -96px; }
          #icon { width: 68px; height: 68px; background-image: url(img/icons.png); }`,
    xml: `<div id='icon'/>`,
    fun: function (sys, items, opts) {
        sys.icon.addClass("#" + this);
    }
}

此組件在樣式項 css 中直接給出了圖標文件所在路徑,以及各類圖標在文件內的位置。而且圖標實例 id 與相應圖標類名對應。固然,組件的使用方式與前面給出的組件是一致的。字體

下面給出的是另外一種組件設計方案,它把位置信息移到了函數項中。此方案是可行的,但組件的執行效率不如前者。該組件每次實例化都要生成位置信息一次,而對於前者,因爲樣式項在組件實例化時,僅生成一次,因此保證了組件的執行性能。this

// 01-04
Icon: {
    css: `#icon { width: 48px; height: 48px; background-image: url(img/icons.png); }`,
    xml: `<div id='icon'/>`,
    fun: function (sys, items, opts) {
        var positions = {
            "msg": "0 0",
            "home": "0 -48px",
            "contact": "0 -96px"
        };
        sys.icon.css("background-position", positions[this]);
    }
}

注意,以上給出的一些圖標組件的設計技巧一樣也適用於圖片組件的設計。編碼

字體圖標

字體圖標經過引入包含圖標的字體文件,將圖標像文字同樣使用。它與 PNG 圖標相比,最關鍵一點在於它的矢量性。字體圖標的引用方式有兩種:經過類名的引用方式以及直接引用 unicode 的方式。

經過類名引用

這種類型的圖標內容定義在樣式項中,HTML 元素經過類名進行關聯。

// 01-05
Msg: {
    css: `#msg { font-size: 48px; width: 48px; height: 48px; line-height: 48px; }
          #msg:before { content: '\\e608'; }`,
    xml: "<div id='msg'/>"
}

直接引用 unicode

這種引用方式與前一種在本質上沒什麼不一樣,它只是將圖標內容由樣式項轉移到視圖項中而已。

// 01-05
Home: {
    css: `#home { font-size: 48px; width: 48px; height: 48px; line-height: 48px; }`,
    xml: `<div id='home'>&#xe609;<div/>`
}

下面給出的示例展現了兩種不一樣的引用字體圖標的方式。注意,此示例簡化了樣式項中與兼容性相關的內容,詳情請查閱配套源碼。

// 01-05
Index: {
    css: `@font-face { font-family: 'iconfont'; url('font/iconfont.ttf') format('truetype');}
          #msg, #home { font-family: 'iconfont'; font-style:normal; }
          #index > * { display: inline-block; padding: 10px; background: #F9F9F9; }`,
    xml: `<div id='index'>
            <Msg id='msg'/>
            <Home id='home'/>
          </div>`
}

SVG 圖標

最後來看看咱們的重頭戲,如何封裝以及使用 SVG 圖標。在 xmlplus 中,SVG 圖標是推薦的圖標使用形式,它容許直接嵌入代碼,無需額外引用相關文件。

經過 xlink:href 引用

對於這種方式,首先你須要一個 svg 圖標集,其包含的內容大概是下面這樣子。

<!-- 01-06 -->
<svg>
    <symbol id="icon" width='48px' height='48px' viewBox='0 0 24 24'>
        <g><polygon points='9,16.2 4.8,12 3.4,13.4 9,19 21,7 19.6,5.6'/></g>\
    </symbol>
	<!-- 還能夠有更多的symbol -->
</svg>

svg 圖標集有兩種存在方式,一個是以文件形式存在,這時 xlink:href 屬性值須要明確指明文件的 url,下面是一個示例。

<!-- 01-06 -->
<svg>
   <use xlink:href='http://example.com/file.svg#home'/>\
</svg>

另外一種形式是,圖標集直接存在於頁內,這種方式叫作頁內引用,它無需指明 url,只要指定相應 symbol 的 ID 值就行了。

<!-- 01-07 -->
<svg>
   <use xlink:href='#home'/>\
</svg>

對 svg 圖標的直接封裝

相對於經過 xlink:href 引用圖標,使用 xmlplus 的組件化技術直接封裝會是一種更好的方式。請看下面的一個 SVG 圖標組件。

// 01-08
Icon: {
    xml: "<svg width='48px' height='48px' viewBox='0 0 24 24'>\
            <g><polygon points='9,16.2 4.8,12 3.4,13.4 9,19 21,7 19.6,5.6'/></g>\
          </svg>",
    fun: function (sys, items, opts) {
        this.attr("fill", '' + this);
    }
}

這是一個鉤形圖標,組件中僅包含視圖項以及函數項成份。根據函數項的內容能夠知道,圖標顏色由組件實例的 id 屬性值給出。下面來看看如何使用該圖標。

// 01-08
Index: {
    css: `#example > * { padding: 10px; background: #F9F9F9; }
          #example > *:hover { fill: #fff; background: #563d7c; }`,
    xml: `<div id='index'>
            <Icon id='red'/>
            <Icon id='green'/>
            <Icon id='blue'/>
          </div>`,
    fun: function (sys, items, opts) {
        sys.example.on("click", "*", e => console.log(this + " clicked"));
    }
}

此示例展現了三個不一樣顏色的圖標,而且偵聽了圖標的點擊事件,打開瀏覽器控制檯,當點擊不一樣圖標時,能夠看到相應的輸出。

另外,有一種常見的 SVG 圖標的封裝方式,它把 SVG 文本通過 URL 編碼後直接在 img 的 src 屬性或者樣式 background-image 中給出。就像下面這樣子。

// 01-09
Icon: {
    css: `#icon {width: 16px; height: 16px; background-image: url('data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D...')}`,
    xml: "<div id='icon'/>"
}

這種方式與上一種方式比起來,有兩個缺點:其一,你看不出 SVG 的源文件。其二,你失去了對 SVG 圖標的操做權。固然,這種方式也並不是不能用。若是你不須要對圖標進行後續的操做,使用這種方式也是能夠接受的。另外,與之類似的一種圖標使用方式是對圖標 base64 編碼後的內嵌引用。下面是一個簡單的示範:

// 01-10
Icon: {
    xml: `<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIcAAA...' />`
}

這種方式與上一種 SVG 圖標的封裝方式是相似的。不過相對於 SVG 圖標組件的直接封裝,你一樣失去了對圖標的操做權。

相關文章
相關標籤/搜索