xianbin 发表于 2013-1-29 08:31:07

对jqplot的CategoryAxisRenderer插件进行扩展,底部Tick在鼠标在上时浮动显示名称。

在前一篇文章中介绍了如何让jqplot的柱形图tick下标出现省略号,参考:
《对jqplot的CategoryAxisRenderer插件进行扩展,让文字出现省略号》
http://xianbin.iteye.com/blog/1701667

下面介绍如何扩展jqplot,让其实现鼠标移动到下标tick的时候出现浮动提示框,显示完整的tick名称。

文件命名为:jqplot.categoryAxisRenderer.extend.js
在引入jqplot.categoryAxisRenderer.js之后,再引入该js,以便覆盖原有的实现。下面代码已经实现了将tick下标显示为带省略号的文字并出现浮动提示框。


http://dl.iteye.com/upload/attachment/0077/2418/8fa14d80-a1d2-3e15-9740-eea0eee87c48.jpg


/** * 本扩展插件是对jqplot插件jqplot.categoryAxisRenderer的扩展,主要修改了显示图形下标Tick的处理, * 在显示Tick之前,判断Tick标签的长度,当标题长度超过tickMaxLength定义的长度时,截获前 * tickMaxLength - 1个字符,然后加上省略号。 ** 作者:suxianbin */(function($) {    $.jqplot.CategoryAxisRenderer.prototype.createTicks = function() {      // we're are operating on an axis here      var ticks = this._ticks;      var userTicks = this.ticks;      var name = this.name;      // databounds were set on axis initialization.      var db = this._dataBounds;      var dim, interval;      var min, max;      var pos1, pos2;      var tt, i;                // X轴的标题文字最大长度      var tickMaxLength = this.tickMaxLength;      // if we already have ticks, use them.      if (userTicks.length) {            // adjust with blanks if we have groups            if (this.groups > 1 && !this._grouped) {                var l = userTicks.length;                var skip = parseInt(l/this.groups, 10);                var count = 0;                for (var i=skip; i<l; i+=skip) {                  userTicks.splice(i+count, 0, ' ');                  count++;                }                this._grouped = true;            }            this.min = 0.5;            this.max = userTicks.length + 0.5;            var range = this.max - this.min;            this.numberTicks = 2*userTicks.length + 1;            for (i=0; i<userTicks.length; i++){                tt = this.min + 2 * i * range / (this.numberTicks-1);                // need a marker before and after the tick                var t = new this.tickRenderer(this.tickOptions);                t.showLabel = false;                // t.showMark = true;                t.setTick(tt, this.name);                this._ticks.push(t);                var t = new this.tickRenderer(this.tickOptions);                              // 当标题长度超过tickMaxLength定义的长度时,截获前tickMaxLength - 1个字符,                // 然后加上省略号。if (tickMaxLength) {var userTick = userTicks.length <= tickMaxLength ? userTicks: userTicks.substring(0, (tickMaxLength - 1)) + '...';t.label = userTick;t.userTick = userTicks;} else {t.label = userTicks;}                              // t.showLabel = true;                t.showMark = false;                t.showGridline = false;                t.setTick(tt+0.5, this.name);                this._ticks.push(t);            }            // now add the last tick at the end            var t = new this.tickRenderer(this.tickOptions);            t.showLabel = false;            // t.showMark = true;            t.setTick(tt+1, this.name);            this._ticks.push(t);      }      // we don't have any ticks yet, let's make some!      else {            if (name == 'xaxis' || name == 'x2axis') {                dim = this._plotDimensions.width;            }            else {                dim = this._plotDimensions.height;            }                        // if min, max and number of ticks specified, user can't specify interval.            if (this.min != null && this.max != null && this.numberTicks != null) {                this.tickInterval = null;            }                        // if max, min, and interval specified and interval won't fit, ignore interval.            if (this.min != null && this.max != null && this.tickInterval != null) {                if (parseInt((this.max-this.min)/this.tickInterval, 10) != (this.max-this.min)/this.tickInterval) {                  this.tickInterval = null;                }            }                  // find out how many categories are in the lines and collect labels            var labels = [];            var numcats = 0;            var min = 0.5;            var max, val;            var isMerged = false;            for (var i=0; i<this._series.length; i++) {                var s = this._series;                for (var j=0; j<s.data.length; j++) {                  if (this.name == 'xaxis' || this.name == 'x2axis') {                        val = s.data;                  }                  else {                        val = s.data;                  }                  if ($.inArray(val, labels) == -1) {                        isMerged = true;                        numcats += 1;                              labels.push(val);                  }                }            }                        if (isMerged && this.sortMergedLabels) {                labels.sort(function(a,b) { return a - b; });            }                        // keep a reference to these tick labels to use for redrawing plot (see bug #57)            this.ticks = labels;                        // now bin the data values to the right lables.            for (var i=0; i<this._series.length; i++) {                var s = this._series;                for (var j=0; j<s.data.length; j++) {                  if (this.name == 'xaxis' || this.name == 'x2axis') {                        val = s.data;                  }                  else {                        val = s.data;                  }                  // for category axis, force the values into category bins.                  // we should have the value in the label array now.                  var idx = $.inArray(val, labels)+1;                  if (this.name == 'xaxis' || this.name == 'x2axis') {                        s.data = idx;                  }                  else {                        s.data = idx;                  }                }            }                        // adjust with blanks if we have groups            if (this.groups > 1 && !this._grouped) {                var l = labels.length;                var skip = parseInt(l/this.groups, 10);                var count = 0;                for (var i=skip; i<l; i+=skip+1) {                  labels = ' ';                }                this._grouped = true;            }                  max = numcats + 0.5;            if (this.numberTicks == null) {                this.numberTicks = 2*numcats + 1;            }            var range = max - min;            this.min = min;            this.max = max;            var track = 0;                        // todo: adjust this so more ticks displayed.            var maxVisibleTicks = parseInt(3+dim/10, 10);            var skip = parseInt(numcats/maxVisibleTicks, 10);            if (this.tickInterval == null) {                this.tickInterval = range / (this.numberTicks-1);            }            // if tickInterval is specified, we will ignore any computed maximum.            for (var i=0; i<this.numberTicks; i++){                tt = this.min + i * this.tickInterval;                var t = new this.tickRenderer(this.tickOptions);                // if even tick, it isn't a category, it's a divider                if (i/2 == parseInt(i/2, 10)) {                  t.showLabel = false;                  t.showMark = true;                }                else {                  if (skip>0 && track<skip) {                        t.showLabel = false;                        track += 1;                  }                  else {                        t.showLabel = true;                        track = 0;                  }                     t.label = t.formatter(t.formatString, labels[(i-1)/2]);                  t.showMark = false;                  t.showGridline = false;                }                t.setTick(tt, this.name);                this._ticks.push(t);            }      }    };            // called with scope of axis    $.jqplot.CategoryAxisRenderer.prototype.pack = function(pos, offsets) {      var ticks = this._ticks;      var max = this.max;      var min = this.min;      var offmax = offsets.max;      var offmin = offsets.min;      var lshow = (this._label == null) ? false : this._label.show;      var i;      for (var p in pos) {            this._elem.css(p, pos);      }                this._offsets = offsets;      // pixellength will be + for x axes and - for y axes becasue pixels always measured from top left.      var pixellength = offmax - offmin;      var unitlength = max - min;                // point to unit and unit to point conversions references to Plot DOM element top left corner.      this.p2u = function(p){            return (p - offmin) * unitlength / pixellength + min;      };                this.u2p = function(u){            return (u - min) * pixellength / unitlength + offmin;      };                        if (this.name == 'xaxis' || this.name == 'x2axis'){            this.series_u2p = function(u){                return (u - min) * pixellength / unitlength;            };            this.series_p2u = function(p){                return p * unitlength / pixellength + min;            };      }                else {            this.series_u2p = function(u){                return (u - max) * pixellength / unitlength;            };            this.series_p2u = function(p){                return p * unitlength / pixellength + max;            };      }                if (this.show) {            if (this.name == 'xaxis' || this.name == 'x2axis') {                for (i=0; i<ticks.length; i++) {                  var t = ticks;                  if (t.show && t.showLabel) {                        var shim;                                                if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {                            // will need to adjust auto positioning based on which axis this is.                            var temp = (this.name == 'xaxis') ? 1 : -1;                            switch (t.labelPosition) {                              case 'auto':                                    // position at end                                    if (temp * t.angle < 0) {                                        shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;                                    }                                    // position at start                                    else {                                        shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;                                    }                                    break;                              case 'end':                                    shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;                                    break;                              case 'start':                                    shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;                                    break;                              case 'middle':                                    shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;                                    break;                              default:                                    shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;                                    break;                            }                        }                        else {                            shim = -t.getWidth()/2;                        }                        var val = this.u2p(t.value) + shim + 'px';                        t._elem.css('left', val);                        t.pack();                        /*                         * 增加X轴Tick的弹出提醒框,内容为下标的全称。                         */                        t._elem.css('cursor', 'default');                        t._elem.css('z-index', 888);                        t._elem.attr('userTick', t.userTick);                                                t._elem.mouseover(function (e) {                        var userTick = $(this).attr('usertick');                        _showUserTickTip(userTick, e);                        });                                                t._elem.mouseout(function () {                        _hideUserTickTip();                        });                  }                }                              var labeledge=['bottom', 0];                if (lshow) {                  var w = this._label._elem.outerWidth(true);                  this._label._elem.css('left', offmin + pixellength/2 - w/2 + 'px');                  if (this.name == 'xaxis') {                        this._label._elem.css('bottom', '0px');                        labeledge = ['bottom', this._label._elem.outerHeight(true)];                  }                  else {                        this._label._elem.css('top', '0px');                        labeledge = ['top', this._label._elem.outerHeight(true)];                  }                  this._label.pack();                }                              // draw the group labels                var step = parseInt(this._ticks.length/this.groups, 10);                for (i=0; i<this._groupLabels.length; i++) {                  var mid = 0;                  var count = 0;                  for (var j=i*step; j<=(i+1)*step; j++) {                        if (this._ticks._elem && this._ticks.label != " ") {                            var t = this._ticks._elem;                            var p = t.position();                            mid += p.left + t.outerWidth(true)/2;                            count++;                        }                  }                  mid = mid/count;                  this._groupLabels.css({'left':(mid - this._groupLabels.outerWidth(true)/2)});                  this._groupLabels.css(labeledge, labeledge);                }            }            else {                for (i=0; i<ticks.length; i++) {                  var t = ticks;                  if (t.show && t.showLabel) {                                                var shim;                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {                            // will need to adjust auto positioning based on which axis this is.                            var temp = (this.name == 'yaxis') ? 1 : -1;                            switch (t.labelPosition) {                              case 'auto':                                    // position at end                              case 'end':                                    if (temp * t.angle < 0) {                                        shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2;                                    }                                    else {                                        shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2;                                    }                                    break;                              case 'start':                                    if (t.angle > 0) {                                        shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2;                                    }                                    else {                                        shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2;                                    }                                    break;                              case 'middle':                                    // if (t.angle > 0) {                                    //   shim = -t.getHeight()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;                                    // }                                    // else {                                    //   shim = -t.getHeight()/2 - t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;                                    // }                                    shim = -t.getHeight()/2;                                    break;                              default:                                    shim = -t.getHeight()/2;                                    break;                            }                        }                        else {                            shim = -t.getHeight()/2;                        }                                                var val = this.u2p(t.value) + shim + 'px';                        t._elem.css('top', val);                        t.pack();                  }                }                              var labeledge=['left', 0];                if (lshow) {                  var h = this._label._elem.outerHeight(true);                  this._label._elem.css('top', offmax - pixellength/2 - h/2 + 'px');                  if (this.name == 'yaxis') {                        this._label._elem.css('left', '0px');                        labeledge = ['left', this._label._elem.outerWidth(true)];                  }                  else {                        this._label._elem.css('right', '0px');                        labeledge = ['right', this._label._elem.outerWidth(true)];                  }                     this._label.pack();                }                              // draw the group labels, position top here, do left after label position.                var step = parseInt(this._ticks.length/this.groups, 10);                for (i=0; i<this._groupLabels.length; i++) {                  var mid = 0;                  var count = 0;                  for (var j=i*step; j<=(i+1)*step; j++) {                        if (this._ticks._elem && this._ticks.label != " ") {                            var t = this._ticks._elem;                            var p = t.position();                            mid += p.top + t.outerHeight()/2;                            count++;                        }                  }                  mid = mid/count;                  this._groupLabels.css({'top':mid - this._groupLabels.outerHeight()/2});                  this._groupLabels.css(labeledge, labeledge);                                    }            }      }    };    // 显示Tick下标全称的提示框    function _showUserTickTip(userTick, event) {var containerId = 'userTickTipDiv';var container = $('#' + containerId);if (container == undefined || container == null || container.length == 0) {container = $('<div class="jqplot-cursor-tooltip chartDetailDiv"></div>');container.attr('id', containerId);var table = '<table class="jqplot-highlighter">'+ '<tr><td><span id="userTickValue"></span></td></tr>'+ '</table>';$(table).appendTo(container);container.appendTo('body');}$('#userTickValue').text(userTick);// 计算显示框的位置,如果超过右边边界则在左边显示var left = event.pageX;var detailPopDivWidth = container.width();var docWidth = $(window).width();var leftX = left + detailPopDivWidth + 10; // 10 表示与边界的间隔if (leftX > docWidth) {left = event.pageX - detailPopDivWidth;}container.css({display : 'block',left : left,top : event.pageY - 25});}      // 隐藏Tick下标全称的提示框    function _hideUserTickTip() {$('#userTickTipDiv').css({display : 'none'});    }})(jQuery);
页: [1]
查看完整版本: 对jqplot的CategoryAxisRenderer插件进行扩展,底部Tick在鼠标在上时浮动显示名称。