jQuery插件编写:对象级插件示例(三)
在这一篇中将介绍一个完整的对象级别插件示例,叫做子弹图插件。关于子弹头图表是什么可以百度查一下,它和我们常见的柱状图很相似。最终效果如下图所示
图一
先回顾一下上一篇文章中说过开发一个对象级别插件分为以下三步:
第一、创建静态的HTML模板和CSS文件
第二、编写插件逻辑,在选定的页面元素上动态添加HTML结构
第三、如果需要和用户交互,还应动态绑定相应的处理事件
在本文展示的这个插件示例中包含了上述三个步骤,将会一一进行说明。这个插件并不是我自己从头开发的。我是在别人的基础上做了适当的修改完成的。原插件的地址可以访问这里获得:
https://github.com/NETTUTS/An-In-Depth-Review-of-the-jQuery-Widget-Factory
插件所用到的HTML模板和CSS样式基本都是原来的,只做了很少的修改。而插件的js逻辑内容则全部是我重写过的。
下面开始介绍插件的内容。
第一步:创建HTML和CSS静态结构
1.1 HTML标签(文件:model.html)
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>子弹图静态HTML模型</title>
- <link rel="stylesheet" href="jquery.bulletchart.css">
- </head>
- <body>
- <div class="chart bullet-chart" style="width: 85%;">
- <div class="legend">
- <div class="legend-item" data-index="0">
- <span class="legend-symbol bar"></span><span class="legend-label">Projected
- Target</span>
- </div>
- <div class="legend-item" data-index="1">
- <span class="legend-symbol bar blue"></span><span
- class="legend-label">Actual Target</span>
- </div>
- <div class="legend-item" data-index="2">
- <span class="legend-symbol marker green"></span><span
- class="legend-label">Green Line</span>
- </div>
- <div class="legend-item" data-index="3">
- <span class="legend-symbol marker red"></span><span
- class="legend-label">Minimum Threshold</span>
- </div>
- </div>
- <div class="chart-container">
- <div class="bar" style="width: 80%;"></div>
- <div class="bar blue" style="width: 70%;"></div>
- <div class="marker green" style="left: 60%;"></div>
- <div class="marker red" style="left: 50%;"></div>
- </div>
- <div class="tick-bar">
- <span class="tick" style="left: 0%;"></span><span class="tick-label"
- style="left: 0%;">0</span><span class="tick" style="left: 25%;"></span><span
- class="tick-label" style="left: 25%;">25</span><span class="tick"
- style="left: 50%;"></span><span class="tick-label"
- style="left: 50%;">50</span><span class="tick" style="left: 75%;"></span><span
- class="tick-label" style="left: 75%;">75</span><span class="tick"
- style="left: 100%;"></span><span class="tick-label"
- style="left: 100%;">100</span>
- </div>
- </div>
- </body>
- </html>
1.2 CSS文件(jquery.bulletchart.css)
- .bullet-chart { font-size: 16px; -webkit-user-select: none; }
- /* 留出足够空间显示图表的刻度 */
- .bullet-chart {
- padding-bottom : 50px;
- }
- .bullet-chart .chart-container {
- height: 30px;
- background: #EEE;
- position: relative;
- /* margin-left: 2.1em; */
- }
- /* Bar 默认为灰色 */
- .bullet-chart .bar {
- background: #777;
- position: absolute;
- /* 垂直居中 */
- height: 10px;
- top: 50%;
- margin-top: -5px;
- }
- /* Marker */
- .bullet-chart .marker {
- background: #555;
- width: 2px;
- height: 20px;
- position: absolute;
- left: 250px;
- top: 50%;
- margin-top: -10px;
- }
- .bullet-chart .red { background: #cd6668; }
- .bullet-chart .green { background: #72cd84; }
- .bullet-chart .blue { background: #64a0cb; }
- .bullet-chart .purple { background: #a77cdb; }
- .bullet-chart .orange { background: #ffb95e; }
- .bullet-chart .cyan { background: #a0e2ff; }
- /* Ticks */
- .bullet-chart .tick-bar {
- position: relative;
- top: 30px;
- border-top: 1px solid #AAA;
- }
- .bullet-chart .tick-bar .tick {
- position: absolute;
- width: 1px;
- height: 6px;
- top: -1px;
- background: #AAA;
- }
- .bullet-chart .tick-bar .tick-label {
- text-align: center;
- position: absolute;
- font-size: 0.6em;
- width: 2.1em;
- margin-left: -1.05em;
- top: 5px;
- color: #AAA;
- }
- /* Legend */
- .bullet-chart .legend {
- margin: 0 0 1em 0;
- border: 1px solid #EEE;
- padding: 0.5em 0 0 0.5em;
- max-width: 300px;
- }
- .bullet-chart .legend .legend-item {
- display: inline-block;
- margin: 0 0.5em 0.5em 0;
- background: #FFE;
- padding: 0 5px;
- border-radius: 2px;
- cursor: pointer;
- }
- .legend-item .legend-symbol {
- position: static;
- margin: 0px;
- display: inline-block;
- vertical-align: middle;
- }
- .legend-item .legend-symbol.marker {
- height: 12px;
- width: 2px;
- }
- .legend-item .legend-symbol.bar {
- height: 12px;
- width: 7px;
- }
- .legend-item .legend-label {
- font-size: 0.6em;
- vertical-align: middle;
- margin-left: 5px;
- }
- .fade { opacity: 0.5; }
有了HTML和CSS我们就能看到插件运行后的最终效果图。如图一所示。这只是开发的第一步,但也是很重要的一步。这个时候不能仅仅效果一出来就急着去写插件逻辑(JS代码)。应该先对其兼容性做到足够的测试。确保在写JS之前插件所用到的HTML和CSS已经确定不再改变,尤其是HTML结构上不能随意改变。至于原因很明显,HTML结构的改变会导致原来的JS不可用的。
第二步、第三步:编写插件逻辑,添加用户交互事件
2.1 JS文件(jquery.bulletchart.js)
由于代码比较多,不会一一解释,当然还是在关键的地方加上了注释。而且,这里也包含了第三步的内容,即添加相应的用户事件。代码也不是太复杂,相信有jquery经验的你能够看懂。
- /**
- * 子弹图插件,基于网上的一个控件改编而成
- * 网上原插件地址:https://github.com/NETTUTS/An-In-Depth-Review-of-the-jQuery-Widget-Factory
- * http://net.tutsplus.com/tutorials/javascript-ajax/an-in-depth-review-of-jquerys-widget-factory/
- * 日期:2013-6-5
- * @author 张书振
- */
- (function($) {
- $.fn.bulletchart = function(options) {
- var settings = {
- // 宽度为相对于容器的百分比: 0 - 100
- size: 100,
- // 显示的图形有两种,一种是bar,只是以竖线显示,另一种是marker,以矩形条显示
- // title 是显示的名称,value是百分比值 0-100,css可以指定颜色值 green,blue,purple,red,orange,cyan
- // [{ title: 'Sample Bar', value: 75, css: '' }],
- bars: [],
- // [{ title: 'Sample Marker', value: 50, css: 'green' }],
- markers: [],
- // 刻度必须是百分比数值 : 0 - 100
- ticks: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
- };
- settings = $.extend(settings, options || {});
- return this.each(function() {
- init($(this));
- });
- /**
- * 初始化插件函数
- * @param $target 将要应用插件的目标DOM节点,是个jQuery对象
- */
- function init($target) {
- $target.addClass("bullet-chart");
- // 设置图标的显示宽度,百分比
- $target.css("width", settings.size + "%");
- //添加legend
- var $legend = $("<div class='legend'></div>").appendTo($target);
- var legendIndex = 0;
- $.each(settings.bars, function() { // 此循环遍历添加bar类型 legend内容
- var $legendItem = $("<div class='legend-item'></div>")
- .attr("data-index", legendIndex++) // 给每个legendItem添加索引,便于单击事件处理
- .appendTo($legend);
- var $legendSymbol = $("<span class='legend-symbol bar'></span>").appendTo($legendItem);
- $legendSymbol.addClass(this.css);
- var $legendLabel = $("<span class='legend-label'></span>").appendTo($legendItem);
- $legendLabel.text(this.title);
- });
- $.each(settings.markers, function() { // 此循环遍历添加marker类型 legend内容
- var $legendItem = $("<div class='legend-item'></div>")
- .attr("data-index", legendIndex++)
- .appendTo($legend);
- var $legendSymbol = $("<span class='legend-symbol marker'></span>").appendTo($legendItem);
- $legendSymbol.addClass(this.css);
- var $legendLabel = $("<span class='legend-label'></span>").appendTo($legendItem);
- $legendLabel.text(this.title);
- });
- //添加图表
- var $container = $("<div class='chart-container'></div>").appendTo($target);
- var $tickbar = $("<div class='tick-bar'></div>").appendTo($target);
- //刻度
- $.each(settings.ticks, function() {
- $("<span class='tick'></span>")
- .css("left", this + "%")
- .appendTo($tickbar);
- $("<span class='tick-label'><span>")
- .css("left", this + "%")
- .text(this)
- .appendTo($tickbar);
- });
- //绘制bar 和 marker 图形
- $.each(settings.bars, function() {
- $("<div class='bar'></div>")
- .addClass(this.css)
- .animate({ width : this.value + "%" })
- .appendTo($container);
- });
- $.each(settings.markers, function() {
- $("<div class='marker'></div>")
- .addClass(this.css)
- .css("left", this.value + "%")
- .appendTo($container);
- });
- // 这里就是第三步的内容,为legend添加事件,鼠标单击事件,显示或隐藏相应的bar和marker图形
- $(".legend-item", $target).toggle(
- function(event) {
- var $legendItem = $(this);
- $legendItem.addClass("fade");
- $(".chart-container>.bar, .chart-container>.marker", $target).eq($legendItem.attr("data-index"))
- .fadeOut();
- },
- function(event) {
- var $legendItem = $(this);
- $legendItem.removeClass("fade");
- $(".chart-container>.bar, .chart-container>.marker", $target).eq($legendItem.attr("data-index"))
- .fadeIn();
- }
- );
- }
- };
- })(jQuery);
2.2 Demo测试页面(demo.html)
- <!doctype html>
- <html lang="en">
- <head>
- <meta charset="utf-8">
- <title>BulletChart: A jQuery Widget</title>
- <meta name="description" content="BulletChart: A jQuery Widget">
- <meta name="author" content="SitePoint">
- <link rel="stylesheet" href="jquery.bulletchart.css">
- <script src="jquery-1.8.3.js"></script>
- <script src="jquery.bulletchart.js"></script>
- <script type="text/javascript">
- $(function(){
- $("#bulletChartBtn").click(function(){
- $('.chart').bulletchart({
- size: 85,
- bars: [
- { title: 'Projected Target', value: 80, css: '' },
- { title: 'Actual Target', value: 70, css: 'blue' }
- ],
- markers: [
- { title: 'Green Line', value: 60, css: 'green' },
- { title: 'Minimum Threshold', value: 50, css: 'red' }
- ],
- ticks: [0, 25, 50, 75, 100]
- });
- });
- });
- </script>
- </head>
- <body>
- <input id="bulletChartBtn" type="button" value="BulletChart"/><br/>
- <div class="chart"></div>
- <div class="chart"></div>
- </body>
- </html>