added pie chart

This commit is contained in:
Luis Correa d'Almeida 2012-10-16 01:00:57 +01:00
parent 60eae6a697
commit 30206c1355
4 changed files with 277 additions and 1 deletions

View file

@ -7,6 +7,11 @@ body {
height: 250px;
margin: 20px auto 0 auto;
}
#pie {
width: 400px;
height: 400px;
margin: 20px auto 0 auto;
}
pre {
height: 250px;
overflow: auto;

110
lib/morris.pie.coffee Normal file
View file

@ -0,0 +1,110 @@
class Morris.Pie
defaults:
colors: [
'#0B62A4'
'#3980B5'
'#679DC6'
'#95BBD7'
'#B0CCE1'
'#095791'
'#095085'
'#083E67'
'#052C48'
'#042135'
]
enhanceMax: false
constructor: (options)->
return new Morris.Pie(options) if not (@ instanceof Morris.Pie)
if typeof options.element is 'string'
@el = $ document.getElementById(options.element)
else
@el = $ options.element
throw new Error("Graph placeholder not found.") if @el == null || @el.length == 0
@options = $.extend {}, @defaults, options
# data
return false if options.data is undefined or options.data.length is 0
@data = options.data
@el.addClass 'graph-initialised'
@paper = new Raphael(@el[0])
@segments = []
@draw()
draw: ->
@paper.clear()
total = 0
total += x.value for x in @data
max = Math.max.apply(null, x.value for x in @data)
currentAngle = 0
cx = @el.width() / 2
cy = @el.height() / 2
r = (Math.min(cx, cy) - 10) / 3
for labelAndValue, index in @data
value = labelAndValue.value
label = labelAndValue.label
step = 360 * value / total
color = @options.colors[index % @options.colors.length]
pieSegment = new Morris.PieSegment(@paper, cx, cy, r, currentAngle, step, labelAndValue, color)
pieSegment.on "hover", @select
pieSegment.render()
pieSegment.select() if labelAndValue.value == max && @options.enhanceMax
@segments.push pieSegment
currentAngle += step
select: (segmentToSelect)=>
segment.deselect() for segment in @segments
segmentToSelect.select()
class Morris.PieSegment extends Morris.EventEmitter
constructor: (@paper, @cx, @cy, @r, @currentAngle, @step, @labelAndValue, @color)->
@rad = Math.PI / 180
@distanceFromEdge = 30
@labelAngle = @currentAngle + (@step / 2)
@endAngle = @currentAngle + @step
@x1 = @cx + @r * Math.cos(-@currentAngle * @rad)
@x2 = @cx + @r * Math.cos(-@endAngle * @rad)
@y1 = @cy + @r * Math.sin(-@currentAngle * @rad)
@y2 = @cy + @r * Math.sin(-@endAngle * @rad)
render: ()->
@segment = @paper.path(["M", @cx, @cy, "L", @x1, @y1, "A", @r, @r, 0, +(@endAngle - @currentAngle > 180), 0, @x2, @y2, "z"]).attr({ fill: @color, stroke: "#FFFFFF", "stroke-width": 2} ).hover(=> @fire('hover', @))
@label = @paper.text(@cx + (@r + @distanceFromEdge ) * Math.cos(-@labelAngle * @rad), @cy + (@r + @distanceFromEdge ) * Math.sin(-@labelAngle * @rad), @labelAndValue.label).attr({fill: "#000000", "font-weight": "bold", stroke: "none", opacity: 1, "font-size": 12})
@value = @paper.text(@cx + (@r + @distanceFromEdge ) * Math.cos(-@labelAngle * @rad), @cy + (@r + @distanceFromEdge ) * Math.sin(-@labelAngle * @rad) + 14, @labelAndValue.value).attr({fill: @color, stroke: "none", opacity: 1, "font-size": 12})
select: =>
unless @selected
@segment.stop().animate({transform: "s1.1 1.1 " + @cx + " " + @cy}, 150, "<>")
@selected = true
deselect: =>
if @selected
@segment.stop().animate({transform: ""}, 150, "<>")
@selected = false

161
morris.js
View file

@ -992,4 +992,165 @@
Morris.AUTO_LABEL_ORDER = ["year", "month", "day", "hour", "30min", "15min", "10min", "5min", "minute", "30sec", "15sec", "10sec", "5sec", "second"];
Morris.Pie = (function() {
Pie.prototype.defaults = {
colors: ['#0B62A4', '#3980B5', '#679DC6', '#95BBD7', '#B0CCE1', '#095791', '#095085', '#083E67', '#052C48', '#042135'],
enhanceMax: false
};
function Pie(options) {
this.select = __bind(this.select, this);
if (!(this instanceof Morris.Pie)) {
return new Morris.Pie(options);
}
if (typeof options.element === 'string') {
this.el = $(document.getElementById(options.element));
} else {
this.el = $(options.element);
}
if (this.el === null || this.el.length === 0) {
throw new Error("Graph placeholder not found.");
}
this.options = $.extend({}, this.defaults, options);
if (options.data === void 0 || options.data.length === 0) {
return false;
}
this.data = options.data;
this.el.addClass('graph-initialised');
this.paper = new Raphael(this.el[0]);
this.segments = [];
this.draw();
}
Pie.prototype.draw = function() {
var color, currentAngle, cx, cy, index, label, labelAndValue, max, pieSegment, r, step, total, value, x, _i, _j, _len, _len1, _ref, _ref1, _results;
this.paper.clear();
total = 0;
_ref = this.data;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
x = _ref[_i];
total += x.value;
}
max = Math.max.apply(null, (function() {
var _j, _len1, _ref1, _results;
_ref1 = this.data;
_results = [];
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
x = _ref1[_j];
_results.push(x.value);
}
return _results;
}).call(this));
currentAngle = 0;
cx = this.el.width() / 2;
cy = this.el.height() / 2;
r = (Math.min(cx, cy) - 10) / 3;
_ref1 = this.data;
_results = [];
for (index = _j = 0, _len1 = _ref1.length; _j < _len1; index = ++_j) {
labelAndValue = _ref1[index];
value = labelAndValue.value;
label = labelAndValue.label;
step = 360 * value / total;
color = this.options.colors[index % this.options.colors.length];
pieSegment = new Morris.PieSegment(this.paper, cx, cy, r, currentAngle, step, labelAndValue, color);
pieSegment.on("hover", this.select);
pieSegment.render();
if (labelAndValue.value === max && this.options.enhanceMax) {
pieSegment.select();
}
this.segments.push(pieSegment);
_results.push(currentAngle += step);
}
return _results;
};
Pie.prototype.select = function(segmentToSelect) {
var segment, _i, _len, _ref;
_ref = this.segments;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
segment = _ref[_i];
segment.deselect();
}
return segmentToSelect.select();
};
return Pie;
})();
Morris.PieSegment = (function(_super) {
__extends(PieSegment, _super);
function PieSegment(paper, cx, cy, r, currentAngle, step, labelAndValue, color) {
this.paper = paper;
this.cx = cx;
this.cy = cy;
this.r = r;
this.currentAngle = currentAngle;
this.step = step;
this.labelAndValue = labelAndValue;
this.color = color;
this.deselect = __bind(this.deselect, this);
this.select = __bind(this.select, this);
this.rad = Math.PI / 180;
this.distanceFromEdge = 30;
this.labelAngle = this.currentAngle + (this.step / 2);
this.endAngle = this.currentAngle + this.step;
this.x1 = this.cx + this.r * Math.cos(-this.currentAngle * this.rad);
this.x2 = this.cx + this.r * Math.cos(-this.endAngle * this.rad);
this.y1 = this.cy + this.r * Math.sin(-this.currentAngle * this.rad);
this.y2 = this.cy + this.r * Math.sin(-this.endAngle * this.rad);
}
PieSegment.prototype.render = function() {
var _this = this;
this.segment = this.paper.path(["M", this.cx, this.cy, "L", this.x1, this.y1, "A", this.r, this.r, 0, +(this.endAngle - this.currentAngle > 180), 0, this.x2, this.y2, "z"]).attr({
fill: this.color,
stroke: "#FFFFFF",
"stroke-width": 2
}).hover(function() {
return _this.fire('hover', _this);
});
this.label = this.paper.text(this.cx + (this.r + this.distanceFromEdge) * Math.cos(-this.labelAngle * this.rad), this.cy + (this.r + this.distanceFromEdge) * Math.sin(-this.labelAngle * this.rad), this.labelAndValue.label).attr({
fill: "#000000",
"font-weight": "bold",
stroke: "none",
opacity: 1,
"font-size": 12
});
return this.value = this.paper.text(this.cx + (this.r + this.distanceFromEdge) * Math.cos(-this.labelAngle * this.rad), this.cy + (this.r + this.distanceFromEdge) * Math.sin(-this.labelAngle * this.rad) + 14, this.labelAndValue.value).attr({
fill: this.color,
stroke: "none",
opacity: 1,
"font-size": 12
});
};
PieSegment.prototype.select = function() {
if (!this.selected) {
this.segment.stop().animate({
transform: "s1.1 1.1 " + this.cx + " " + this.cy
}, 150, "<>");
return this.selected = true;
}
};
PieSegment.prototype.deselect = function() {
if (this.selected) {
this.segment.stop().animate({
transform: ""
}, 150, "<>");
return this.selected = false;
}
};
return PieSegment;
})(Morris.EventEmitter);
}).call(this);

2
morris.min.js vendored

File diff suppressed because one or more lines are too long