mirror of
https://github.com/morrisjs/morris.js.git
synced 2024-11-10 21:36:34 +01:00
#199, added behaveLikeLine and fillOpacity options, refactored morris.line to separate line and point draw operation
This commit is contained in:
parent
0cbd83371f
commit
3c9fff0aa0
31
examples/area-as-line.html
Normal file
31
examples/area-as-line.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!doctype html>
|
||||
<head>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
|
||||
<script src="https://raw.github.com/DmitryBaranovskiy/raphael/300aa589f5a0ba7fce667cd62c7cdda0bd5ad904/raphael-min.js"></script>
|
||||
<script src="../morris.js"></script>
|
||||
<script src="lib/prettify.js"></script>
|
||||
<script src="lib/example.js"></script>
|
||||
<link rel="stylesheet" href="lib/example.css">
|
||||
<link rel="stylesheet" href="lib/prettify.css">
|
||||
<link rel="stylesheet" href="../morris.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Area charts behaving like line charts</h1>
|
||||
<div id="graph"></div>
|
||||
<pre id="code" class="prettyprint linenums">
|
||||
// Use Morris.Area instead of Morris.Line
|
||||
Morris.Area({
|
||||
element: 'graph',
|
||||
behaveLikeLine: true,
|
||||
data: [
|
||||
{x: '2011 Q1', y: 3, z: 3},
|
||||
{x: '2011 Q2', y: 2, z: 1},
|
||||
{x: '2011 Q3', y: 2, z: 4},
|
||||
{x: '2011 Q4', y: 3, z: 3}
|
||||
],
|
||||
xkey: 'x',
|
||||
ykeys: ['y', 'z'],
|
||||
labels: ['Y', 'Z']
|
||||
});
|
||||
</pre>
|
||||
</body>
|
@ -19,7 +19,7 @@ Morris.Area({
|
||||
data: [
|
||||
{x: '2011 Q1', y: 3, z: 3},
|
||||
{x: '2011 Q2', y: 2, z: 0},
|
||||
{x: '2011 Q3', y: 0, z: 2},
|
||||
{x: '2011 Q3', y: 2, z: 5},
|
||||
{x: '2011 Q4', y: 4, z: 4}
|
||||
],
|
||||
xkey: 'x',
|
||||
|
@ -1,10 +1,20 @@
|
||||
class Morris.Area extends Morris.Line
|
||||
# Initialise
|
||||
#
|
||||
areaDefaults =
|
||||
fillOpacity: 'auto'
|
||||
behaveLikeLine: false
|
||||
|
||||
constructor: (options) ->
|
||||
return new Morris.Area(options) unless (@ instanceof Morris.Area)
|
||||
@cumulative = true
|
||||
super(options)
|
||||
areaOptions = $.extend {}, areaDefaults, options
|
||||
|
||||
@cumulative = not areaOptions.behaveLikeLine
|
||||
|
||||
if areaOptions.fillOpacity is 'auto'
|
||||
areaOptions.fillOpacity = if areaOptions.behaveLikeLine then .8 else 1
|
||||
|
||||
super(areaOptions)
|
||||
|
||||
# calculate series data point coordinates
|
||||
#
|
||||
@ -14,29 +24,43 @@ class Morris.Area extends Morris.Line
|
||||
row._x = @transX(row.x)
|
||||
total = 0
|
||||
row._y = for y in row.y
|
||||
if @options.behaveLikeLine
|
||||
@transY(y)
|
||||
else
|
||||
total += (y || 0)
|
||||
@transY(total)
|
||||
row._ymax = row._y[row._y.length - 1]
|
||||
row._ymax = Math.max.apply Math, row._y
|
||||
|
||||
# draw the data series
|
||||
#
|
||||
# @private
|
||||
drawSeries: ->
|
||||
for i in [@options.ykeys.length-1..0]
|
||||
path = @paths[i]
|
||||
@seriesPoints = []
|
||||
if @options.behaveLikeLine
|
||||
range = [0..@options.ykeys.length-1]
|
||||
else
|
||||
range = [@options.ykeys.length-1..0]
|
||||
|
||||
for i in range
|
||||
@_drawFillFor i
|
||||
@_drawLineFor i
|
||||
@_drawPointFor i
|
||||
|
||||
_drawFillFor: (index) ->
|
||||
path = @paths[index]
|
||||
if path isnt null
|
||||
path = path + "L#{@transX(@xmax)},#{@bottom}L#{@transX(@xmin)},#{@bottom}Z"
|
||||
@drawFilledPath(path, @fillForSeries(i))
|
||||
super()
|
||||
@drawFilledPath path, @fillForSeries(index)
|
||||
|
||||
fillForSeries: (i) ->
|
||||
color = Raphael.rgb2hsl @colorFor(@data[i], i, 'line')
|
||||
Raphael.hsl(
|
||||
color.h,
|
||||
Math.min(255, color.s * 0.75),
|
||||
Math.min(255, color.l * 1.25))
|
||||
Math.min(255, if @options.behaveLikeLine then color.s * 0.9 else color.s * 0.75),
|
||||
Math.min(255, if @options.behaveLikeLine then color.l * 1.2 else color.l * 1.25))
|
||||
|
||||
drawFilledPath: (path, fill) ->
|
||||
@raphael.path(path)
|
||||
.attr('fill', fill)
|
||||
.attr('fill-opacity', @options.fillOpacity)
|
||||
.attr('stroke-width', 0)
|
||||
|
@ -166,18 +166,24 @@ class Morris.Line extends Morris.Grid
|
||||
#
|
||||
# @private
|
||||
drawSeries: ->
|
||||
@seriesPoints = []
|
||||
for i in [@options.ykeys.length-1..0]
|
||||
path = @paths[i]
|
||||
if path isnt null
|
||||
@drawLinePath(path, @colorFor(row, i, 'line')) #row isn't available here?
|
||||
@seriesPoints = ([] for i in [0...@options.ykeys.length])
|
||||
@_drawLineFor i
|
||||
for i in [@options.ykeys.length-1..0]
|
||||
@_drawPointFor i
|
||||
|
||||
_drawPointFor: (index) ->
|
||||
@seriesPoints[index] = []
|
||||
for row in @data
|
||||
if row._y[i]?
|
||||
circle = @drawLinePoint(row._x, row._y[i], @options.pointSize, @colorFor(row, i, 'point'), i)
|
||||
else
|
||||
circle = null
|
||||
@seriesPoints[i].push(circle)
|
||||
if row._y[index]?
|
||||
circle = @drawLinePoint(row._x, row._y[index], @options.pointSize, @colorFor(row, index, 'point'), index)
|
||||
@seriesPoints[index].push(circle)
|
||||
|
||||
_drawLineFor: (index) ->
|
||||
path = @paths[index]
|
||||
if path isnt null
|
||||
@drawLinePath path, @colorFor(null, index, 'line')
|
||||
|
||||
# create a path for a data series
|
||||
#
|
||||
|
116
morris.js
116
morris.js
@ -793,42 +793,42 @@
|
||||
};
|
||||
|
||||
Line.prototype.drawSeries = function() {
|
||||
var circle, i, path, row, _i, _j, _ref, _ref1, _results;
|
||||
var i, _i, _j, _ref, _ref1, _results;
|
||||
this.seriesPoints = [];
|
||||
for (i = _i = _ref = this.options.ykeys.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) {
|
||||
path = this.paths[i];
|
||||
if (path !== null) {
|
||||
this.drawLinePath(path, this.colorFor(row, i, 'line'));
|
||||
this._drawLineFor(i);
|
||||
}
|
||||
}
|
||||
this.seriesPoints = (function() {
|
||||
var _j, _ref1, _results;
|
||||
_results = [];
|
||||
for (i = _j = 0, _ref1 = this.options.ykeys.length; 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
|
||||
_results.push([]);
|
||||
}
|
||||
return _results;
|
||||
}).call(this);
|
||||
_results = [];
|
||||
for (i = _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; i = _ref1 <= 0 ? ++_j : --_j) {
|
||||
_results.push((function() {
|
||||
var _k, _len, _ref2, _results1;
|
||||
_ref2 = this.data;
|
||||
_results1 = [];
|
||||
for (_k = 0, _len = _ref2.length; _k < _len; _k++) {
|
||||
row = _ref2[_k];
|
||||
if (row._y[i] != null) {
|
||||
circle = this.drawLinePoint(row._x, row._y[i], this.options.pointSize, this.colorFor(row, i, 'point'), i);
|
||||
} else {
|
||||
circle = null;
|
||||
}
|
||||
_results1.push(this.seriesPoints[i].push(circle));
|
||||
}
|
||||
return _results1;
|
||||
}).call(this));
|
||||
_results.push(this._drawPointFor(i));
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
Line.prototype._drawPointFor = function(index) {
|
||||
var circle, row, _i, _len, _ref, _results;
|
||||
this.seriesPoints[index] = [];
|
||||
_ref = this.data;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
row = _ref[_i];
|
||||
circle = null;
|
||||
if (row._y[index] != null) {
|
||||
circle = this.drawLinePoint(row._x, row._y[index], this.options.pointSize, this.colorFor(row, index, 'point'), index);
|
||||
}
|
||||
_results.push(this.seriesPoints[index].push(circle));
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
Line.prototype._drawLineFor = function(index) {
|
||||
var path;
|
||||
path = this.paths[index];
|
||||
if (path !== null) {
|
||||
return this.drawLinePath(path, this.colorFor(null, index, 'line'));
|
||||
}
|
||||
};
|
||||
|
||||
Line.createPath = function(coords, smooth, bottom) {
|
||||
var coord, g, grads, i, ix, lg, path, prevCoord, x1, x2, y1, y2, _i, _len;
|
||||
path = "";
|
||||
@ -1079,15 +1079,26 @@
|
||||
Morris.AUTO_LABEL_ORDER = ["decade", "year", "month", "day", "hour", "30min", "15min", "10min", "5min", "minute", "30sec", "15sec", "10sec", "5sec", "second"];
|
||||
|
||||
Morris.Area = (function(_super) {
|
||||
var areaDefaults;
|
||||
|
||||
__extends(Area, _super);
|
||||
|
||||
areaDefaults = {
|
||||
fillOpacity: 'auto',
|
||||
behaveLikeLine: false
|
||||
};
|
||||
|
||||
function Area(options) {
|
||||
var areaOptions;
|
||||
if (!(this instanceof Morris.Area)) {
|
||||
return new Morris.Area(options);
|
||||
}
|
||||
this.cumulative = true;
|
||||
Area.__super__.constructor.call(this, options);
|
||||
areaOptions = $.extend({}, areaDefaults, options);
|
||||
this.cumulative = !areaOptions.behaveLikeLine;
|
||||
if (areaOptions.fillOpacity === 'auto') {
|
||||
areaOptions.fillOpacity = areaOptions.behaveLikeLine ? .8 : 1;
|
||||
}
|
||||
Area.__super__.constructor.call(this, areaOptions);
|
||||
}
|
||||
|
||||
Area.prototype.calcPoints = function() {
|
||||
@ -1104,36 +1115,63 @@
|
||||
_results1 = [];
|
||||
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
||||
y = _ref1[_j];
|
||||
if (this.options.behaveLikeLine) {
|
||||
_results1.push(this.transY(y));
|
||||
} else {
|
||||
total += y || 0;
|
||||
_results1.push(this.transY(total));
|
||||
}
|
||||
}
|
||||
return _results1;
|
||||
}).call(this);
|
||||
_results.push(row._ymax = row._y[row._y.length - 1]);
|
||||
_results.push(row._ymax = Math.max.apply(Math, row._y));
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
Area.prototype.drawSeries = function() {
|
||||
var i, path, _i, _ref;
|
||||
for (i = _i = _ref = this.options.ykeys.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) {
|
||||
path = this.paths[i];
|
||||
var i, range, _i, _j, _k, _len, _ref, _ref1, _results, _results1, _results2;
|
||||
this.seriesPoints = [];
|
||||
if (this.options.behaveLikeLine) {
|
||||
range = (function() {
|
||||
_results = [];
|
||||
for (var _i = 0, _ref = this.options.ykeys.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); }
|
||||
return _results;
|
||||
}).apply(this);
|
||||
} else {
|
||||
range = (function() {
|
||||
_results1 = [];
|
||||
for (var _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; _ref1 <= 0 ? _j++ : _j--){ _results1.push(_j); }
|
||||
return _results1;
|
||||
}).apply(this);
|
||||
}
|
||||
_results2 = [];
|
||||
for (_k = 0, _len = range.length; _k < _len; _k++) {
|
||||
i = range[_k];
|
||||
this._drawFillFor(i);
|
||||
this._drawLineFor(i);
|
||||
_results2.push(this._drawPointFor(i));
|
||||
}
|
||||
return _results2;
|
||||
};
|
||||
|
||||
Area.prototype._drawFillFor = function(index) {
|
||||
var path;
|
||||
path = this.paths[index];
|
||||
if (path !== null) {
|
||||
path = path + ("L" + (this.transX(this.xmax)) + "," + this.bottom + "L" + (this.transX(this.xmin)) + "," + this.bottom + "Z");
|
||||
this.drawFilledPath(path, this.fillForSeries(i));
|
||||
return this.drawFilledPath(path, this.fillForSeries(index));
|
||||
}
|
||||
}
|
||||
return Area.__super__.drawSeries.call(this);
|
||||
};
|
||||
|
||||
Area.prototype.fillForSeries = function(i) {
|
||||
var color;
|
||||
color = Raphael.rgb2hsl(this.colorFor(this.data[i], i, 'line'));
|
||||
return Raphael.hsl(color.h, Math.min(255, color.s * 0.75), Math.min(255, color.l * 1.25));
|
||||
return Raphael.hsl(color.h, Math.min(255, this.options.behaveLikeLine ? color.s * 0.9 : color.s * 0.75), Math.min(255, this.options.behaveLikeLine ? color.l * 1.2 : color.l * 1.25));
|
||||
};
|
||||
|
||||
Area.prototype.drawFilledPath = function(path, fill) {
|
||||
return this.raphael.path(path).attr('fill', fill).attr('stroke-width', 0);
|
||||
return this.raphael.path(path).attr('fill', fill).attr('fill-opacity', this.options.fillOpacity).attr('stroke-width', 0);
|
||||
};
|
||||
|
||||
return Area;
|
||||
|
2
morris.min.js
vendored
2
morris.min.js
vendored
File diff suppressed because one or more lines are too long
@ -42,6 +42,19 @@ describe 'Morris.Area', ->
|
||||
gridTextColor: '#888'
|
||||
gridTextSize: 12
|
||||
|
||||
it 'should not be cumulative if behaveLikeLine', ->
|
||||
chart = Morris.Area $.extend {}, defaults, behaveLikeLine: true
|
||||
chart.cumulative.should.equal false
|
||||
|
||||
it 'should have a line with transparent fill if behaveLikeLine', ->
|
||||
chart = Morris.Area $.extend {}, defaults, behaveLikeLine: true
|
||||
$('#graph').find("path[fill-opacity='0.8']").size().should.equal 1
|
||||
|
||||
it 'should not have a line with transparent fill', ->
|
||||
chart = Morris.Area $.extend {}, defaults
|
||||
$('#graph').find("path[fill-opacity='0.8']").size().should.equal 0
|
||||
|
||||
it 'should have a line with the fill of a modified line color', ->
|
||||
chart = Morris.Area $.extend {}, defaults
|
||||
$('#graph').find("path[fill='#2577b5']").size().should.equal 1
|
||||
$('#graph').find("path[fill='#0b62a4']").size().should.equal 0
|
||||
$('#graph').find("path[fill='#7a92a3']").size().should.equal 0
|
||||
|
Loading…
Reference in New Issue
Block a user