莫里斯圆环图始终在12点开始(中间顶部)

时间:2015-06-14 08:19:03

标签: javascript morris.js

我正在使用Morris圆环图,我想尝试确保这些片段始终在12点开始,以便在同一屏幕上同时查看多个图表时有一定的一致性。

之前我使用的是jQuery circliful https://github.com/pguso/jquery-plugin-circliful但效果很好,但Retina屏幕的质量非常模糊,所以我检查了Morris,它做了我想做的事吧。

我想要一些看起来像第一个片段总是从顶部中间开始的东西:

Circliful Morris

有谁知道如何实现这个目标?

var donut= Morris.Donut({
  element: 'donut-example',
  data: [
    {label: "New clients", value: 35},
    {label: "In-Store Sales", value: 65}
  ],
  colors: ['#90c070', '#eeeeee'],
  select :0   
});

donut.select(0);

http://jsfiddle.net/0t976ez6/

1 个答案:

答案 0 :(得分:2)

不,据我从源代码中可以看出,Morris中没有API(公共或私有)来做到这一点。 See Donut's redraw()表示它如何渲染图表:它总是从最低点开始,然后逆时针方向。

现在,我建议在继续之前考虑切换到其他图表库。例如,有一个D3.js - 不是最简单的库,但它提供了几乎所有东西的自由,有时可能很难使用。但是你可以想到的每件事都有一吨的例子。比如,这里有一个blog post关于使用D3创建类似的外观圆环图。

但是,嘿,这是一个JavaScript,我们可以修补东西,所以没有什么是不可能的!

警告:修补库代码不是最好的主意!你必须小心,只有当它真的是唯一的方式时才这样做。

最简单(当然不是最简单)的方法是将猴子补丁Morris.Donut.redraw()从Math.PI(中间顶部)开始,顺时针方向。为此,last局部变量的初始值应该从0更改为Math.PI,并且找到下一个起始点的逻辑会稍微调整一下。

这是一个工作示例,其中包含了使用特殊PATCHED注释修补的行:

/**
 * Careful: patched lib-function!
 *
 * In case of problems, see <a href="https://github.com/morrisjs/morris.js/blob/master/morris.js#L1894">original</a>
 */
Morris.Donut.prototype.redraw = function() {
  var C, cx, cy, i, idx, last, max_value, min, next, seg, total, value, w, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
  this.raphael.clear();
  cx = this.el.width() / 2;
  cy = this.el.height() / 2;
  w = (Math.min(cx, cy) - 10) / 3;
  total = 0;
  _ref = this.values;
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    value = _ref[_i];
    total += value;
  }
  min = 5 / (2 * w);
  C = 1.9999 * Math.PI - min * this.data.length;
  // ------------ PATCHED: start from the top
  last = Math.PI;
  // original:
  // last = 0
  // ------------
  idx = 0;
  this.segments = [];
  _ref1 = this.values;
  for (i = _j = 0, _len1 = _ref1.length; _j < _len1; i = ++_j) {
    value = _ref1[i];
    // ------------ PATCHED: change direction of rendering
    next = last - min - C * (value / total);
    seg = new Morris.DonutSegment(cx, cy, w * 2, w, next, last, this.data[i].color || this.options.colors[idx % this.options.colors.length], this.options.backgroundColor, idx, this.raphael);
    // original:
    // next = last + min + C * (value / total);
    // seg = new Morris.DonutSegment(cx, cy, w * 2, w, last, next, this.data[i].color || this.options.colors[idx % this.options.colors.length], this.options.backgroundColor, idx, this.raphael);
    // ------------
    seg.render();
    this.segments.push(seg);
    seg.on('hover', this.select);
    seg.on('click', this.click);
    last = next;
    idx += 1;
  }
  this.text1 = this.drawEmptyDonutLabel(cx, cy - 10, this.options.labelColor, 15, 800);
  this.text2 = this.drawEmptyDonutLabel(cx, cy + 10, this.options.labelColor, 14);
  max_value = Math.max.apply(Math, this.values);
  idx = 0;
  _ref2 = this.values;
  _results = [];
  for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
    value = _ref2[_k];
    if (value === max_value) {
      this.select(idx);
      break;
    }
    _results.push(idx += 1);
  }
  return _results;
};

var donut = Morris.Donut({
  element: 'donut-example',
  data: [{
    label: "In-Store Sales",
    value: 55
  }, {
    label: "New clients",
    value: 25
  }, {
    label: "Reseller stores",
    value: 20
  }],
  colors: ['#90c070', '#ee9090', '#9090ee'],
  select: 0
});

donut.select(0);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://rawgit.com/morrisjs/morris.js/master/morris.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css" rel="stylesheet" />
<div id="donut-example" style="height: 250px;"></div>

当然,可能有另一种方法可以实现同样的目的:也许我忽略了一些局部变量变化的符号,这将导致相同的渲染。