我正在使用Morris圆环图,我想尝试确保这些片段始终在12点开始,以便在同一屏幕上同时查看多个图表时有一定的一致性。
之前我使用的是jQuery circliful https://github.com/pguso/jquery-plugin-circliful但效果很好,但Retina屏幕的质量非常模糊,所以我检查了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);
答案 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>
当然,可能有另一种方法可以实现同样的目的:也许我忽略了一些局部变量变化的符号,这将导致相同的渲染。