xmlplus组件设计系列之图标(ICON)(1)


Posted in Javascript onMay 05, 2017

网页上使用的图标分可为三种:文件图标、字体图标和 SVG 图标。对于文件图标,下面仅以 PNG 格式来说明。

PNG 图标

对于 PNG 图标的引用,有两种方式。一种是直接由 HTML 元素 img 的 src 属性给出。下面是一个简单的示例。

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

这里假定图标文件与组件所在文件在同级目录中,于是可以按如下的方式便捷地引用所需的图标。注意组件 Icon 巧妙地使 id 属性值与图片文件名关联,这样可以避免创建额外的属性。

Example: {
  css: "#example > * { padding: 10px; background: #F9F9F9; }",
  xml: "<div id='example' class='bs-example'>\
      <Icon id='msg'/>\
      <Icon id='home'/>\
      <Icon id='contact'/>\
     </div>"
}

另一种引用 PNG 图标的方式是给相应的对象添加 background-image 样式,并且由样式中给出图标所在路径。下面是一个简单的示例。

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

这种形式与前面由 img 标签给出的图标有许多相似之处。不同的是,前者动态指定的是 img 标签的 src 值 ,而后者动态指定的则是 div 元素的 css 样式。该组件与前面给出的 Icon 组件的使用方式完全一致,这里就不重复了。

对于以上给出的组件 Icon,使用的是离散的图标文件。实际应用中,通常给出的是一个包含许多图标的 PNG 文件。这种情况下该如何构建图标组件呢?请看下面给出的一种较为实用的方案。

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

此组件在样式项 css 中直接给出了图标文件所在路径,以及各种图标在文件内的位置。并且图标实例 id 与相应图标类名对应。当然,组件的使用方式与前面给出的组件是一致的。

下面给出的是另一种组件设计方案,它把位置信息移到了函数项中。此方案是可行的,但组件的执行效率不如前者。该组件每次实例化都要生成位置信息一次,而对于前者,由于样式项在组件实例化时,仅生成一次,所以保证了组件的执行性能。

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

字体图标

字体图标通过引入包含图标的字体文件,将图标像文字一样使用。它与 PNG 图标相比,最关键一点在于它的矢量性。字体图标的引用方式有两种:通过类名的引用方式以及直接引用 unicode 的方式。

通过类名引用

这种类型的图标内容定义在样式项中,HTML 元素通过类名进行关联。

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

直接引用unicode

这种引用方式与前一种在本质上没什么不同,它只是将图标内容由样式项转移到视图项中而已。

Home: {
  css: "#home { font-size: 48px; width: 68px; height: 68px; line-height: 48px; }",
  xml: "<div id='home'><div/>"
}

下面给出的示例展示了两种不同的引用字体图标的方式。注意,此示例简化了样式项中与兼容性相关的内容,详情请查阅配套源码。

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

SVG 图标

最后来看看我们的重头戏,如何封装以及使用 SVG 图标。在 xmlplus 中,SVG 图标是推荐的图标使用形式,它允许直接嵌入代码,无需额外引用相关文件。

通过 xlink:href 引用

对于这种方式,首先你需要一个 svg 图标集,其包含的内容大概是下面这样子。

<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,下面是一个示例。

<svg>
  <use xlink:href='http://example.com/file.svg#icon'/>\
</svg>

另一种形式是,图标集直接存在于页内,这种方式叫做页内引用,它无需指明 url,只要指定相应 symbol 的 id 就好了。

<svg>
  <use xlink:href='#icon'/>\
</svg>

对svg 图标的直接封装

相对于通过 xlink:href 引用图标,使用 xmlplus 的组件化技术直接封装会是一种更好的方式。请看下面的一个 SVG 图标组件。

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 属性值给出。下面来看看如何使用该图标。

Example: {
  css: "#example > * { padding: 10px; background: #F9F9F9; }\
     #example > *:hover { fill: #fff; background: #563d7c; }",
  xml: "<div id='example'>\
      <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 中给出。就像下面这样子。

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 编码后的内嵌引用。下面是一个简单的示范:

Icon: {
  xml: "<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIcAAA..." />"
}

这种方式与上一种 SVG 图标的封装方式是类似的。不过相对于 SVG 图标组件的直接封装,你同样失去了对图标的操作权。

本系列文章基于 xmlplus 框架。如果你对 xmlplus 没有多少了解,可以访问 www.xmlplus.cn。这里有详尽的入门文档可供参考。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript innerText和innerHtml应用
Jan 28 Javascript
《JavaScript高级程序设计》阅读笔记(三) ECMAScript中的引用类型
Feb 27 Javascript
jquery阻止冒泡事件使用模拟事件
Sep 06 Javascript
jQuery的实例及必知重要的jQuery选择器详解
May 20 Javascript
Javascript 判断两个IP是否在同一网段实例代码
Nov 28 Javascript
浅析JavaScript中作用域和作用域链
Dec 06 Javascript
微信小程序实现瀑布流布局与无限加载的方法详解
May 12 Javascript
Vue中mintui的field实现blur和focus事件的方法
Aug 25 Javascript
vue-cli 打包后提交到线上出现 &quot;Uncaught SyntaxError:Unexpected token&quot; 报错
Nov 06 Javascript
js遍历详解(forEach, map, for, for...in, for...of)
Aug 28 Javascript
Vue+Node服务器查询Mongo数据库及页面数据传递操作实例分析
Dec 20 Javascript
vue项目打包后路由错误的解决方法
Apr 13 Vue.js
xmlplus组件设计系列之网格(DataGrid)(10)
May 05 #Javascript
移动端web滚动分页的实现方法
May 05 #Javascript
vue.js之vue-cli脚手架的搭建详解
May 05 #Javascript
Vue中使用vux的配置详解
May 05 #Javascript
Angular directive递归实现目录树结构代码实例
May 05 #Javascript
微信小程序开发图片拖拽实例详解
May 05 #Javascript
javascript 中关于array的常用方法详解
May 05 #Javascript
You might like
PHP的FTP学习(一)
2006/10/09 PHP
Laravel解决nesting level错误和隐藏index.php的问题
2019/10/12 PHP
Jquery优化效率 提升性能解决方案
2010/09/06 Javascript
jQuery 源码分析笔记(7) Queue
2011/06/19 Javascript
用JS做的简单的可折叠的两级树形菜单
2013/09/21 Javascript
用js+iframe形成页面的一种遮罩效果的具体实现
2013/12/31 Javascript
如何用JavaScript定义一个类
2014/09/12 Javascript
理解javascript中DOM事件
2015/12/25 Javascript
jQuery根据表单name获取值的方法
2016/05/24 Javascript
喜大普奔!jQuery发布 3.0 最终版
2016/06/12 Javascript
JS递归遍历对象获得Value值方法技巧
2016/06/14 Javascript
picLazyLoad 实现图片延时加载(包含背景图片)
2016/07/21 Javascript
jQuery ajax方法传递中文时出现中文乱码的解决方法
2016/07/25 Javascript
javascript中call,apply,bind函数用法示例
2016/12/19 Javascript
vue.js+Element实现表格里的增删改查
2017/01/18 Javascript
将input框中输入内容显示在相应的div中【三种方法可选】
2017/05/08 Javascript
JavaScript读写二进制数据的方法详解
2018/09/09 Javascript
在Node.js中将SVG图像转换为PNG,JPEG,TIFF,WEBP和HEIF格式的方法
2019/08/22 Javascript
layui 富文本编辑器和textarea值的相互传递方法
2019/09/18 Javascript
React实现类似淘宝tab居中切换效果的示例代码
2020/06/02 Javascript
解决Vue项目中tff报错的问题
2020/10/21 Javascript
Python中使用装饰器和元编程实现结构体类实例
2015/01/28 Python
Django中模型Model添加JSON类型字段的方法
2015/06/17 Python
Python对字符串实现去重操作的方法示例
2017/08/11 Python
python批量查询、汉字去重处理CSV文件
2018/05/31 Python
Python中文件的写入读取以及附加文字方法
2019/01/23 Python
pandas实现将日期转换成timestamp
2019/12/07 Python
python操作gitlab API过程解析
2019/12/27 Python
tensorflow基于CNN实战mnist手写识别(小白必看)
2020/07/20 Python
python性能测试工具locust的使用
2020/12/28 Python
联想韩国官网:Lenovo Korea
2018/05/10 全球购物
Bravofly德国:预订廉价航班和酒店
2019/09/22 全球购物
一月红领巾广播稿
2014/02/11 职场文书
弄虚作假心得体会
2014/09/10 职场文书
2014年工程工作总结
2014/11/25 职场文书
英国数字版游戏销量周榜公布 《小缇娜的奇幻之地》登顶
2022/04/03 其他游戏