Skip to content

Commit 6d6e07b

Browse files
committed
Better automatic y-labelling.
1 parent 5e240e6 commit 6d6e07b

File tree

6 files changed

+117
-93
lines changed

6 files changed

+117
-93
lines changed

lib/morris.grid.coffee

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -161,31 +161,14 @@ class Morris.Grid extends Morris.EventEmitter
161161
@ymax += 1
162162

163163
if @options.axes is true or @options.grid is true
164-
# calculate grid placement
165-
span = @ymax - @ymin
166-
ymag = Math.floor(Math.log(span) / Math.log(10))
167-
unit = Math.pow(10, ymag)
168-
169-
# calculate initial grid min and max values
170-
gmin = Math.round(@ymin / unit) * unit
171-
gmax = Math.round(@ymax / unit) * unit
172-
step = (gmax - gmin) / (@options.numLines - 1)
173-
174-
# ensure zero is plotted where the range includes zero
175-
if gmin < 0 and gmax > 0
176-
gmin = Math.round(@ymin / step) * step
177-
gmax = Math.round(@ymax / step) * step
178-
179-
# special case for decimal numbers
180-
if step < 1
181-
smag = Math.floor(Math.log(step) / Math.log(10))
182-
@grid = for y in [gmin..gmax] by step
183-
parseFloat(y.toFixed(1 - smag))
164+
if @options.ymax == @defaults.ymax and @options.ymin == @defaults.ymin
165+
# calculate 'magic' grid placement
166+
@grid = @autoGridLines(@ymin, @ymax, @options.numLines)
167+
@ymin = Math.min(@ymin, @grid[0])
168+
@ymax = Math.max(@ymax, @grid[@grid.length - 1])
184169
else
185-
@grid = (y for y in [gmin..gmax] by step)
186-
187-
@ymin = gmin
188-
@ymax = gmax
170+
step = (@ymax - @ymin) / (@options.numLines - 1)
171+
@grid = (y for y in [@ymin..@ymax] by step)
189172

190173
@dirty = true
191174
@redraw() if redraw
@@ -205,6 +188,33 @@ class Morris.Grid extends Morris.EventEmitter
205188
else
206189
boundaryOption
207190

191+
autoGridLines: (ymin, ymax, nlines) ->
192+
span = ymax - ymin
193+
ymag = Math.floor(Math.log(span) / Math.log(10))
194+
unit = Math.pow(10, ymag)
195+
196+
# calculate initial grid min and max values
197+
gmin = Math.floor(ymin / unit) * unit
198+
gmax = Math.ceil(ymax / unit) * unit
199+
step = (gmax - gmin) / (nlines - 1)
200+
if unit == 1 and step > 1 and Math.ceil(step) != step
201+
step = Math.ceil(step)
202+
gmax = gmin + step * (nlines - 1)
203+
204+
# ensure zero is plotted where the range includes zero
205+
if gmin < 0 and gmax > 0
206+
gmin = Math.floor(ymin / step) * step
207+
gmax = Math.ceil(ymax / step) * step
208+
209+
# special case for decimal numbers
210+
if step < 1
211+
smag = Math.floor(Math.log(step) / Math.log(10))
212+
grid = for y in [gmin..gmax] by step
213+
parseFloat(y.toFixed(1 - smag))
214+
else
215+
grid = (y for y in [gmin..gmax] by step)
216+
grid
217+
208218
_calc: ->
209219
w = @el.width()
210220
h = @el.height()

morris.js

Lines changed: 48 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

morris.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
describe 'Morris.Grid#autoGridLines', ->
2+
3+
beforeEach ->
4+
@subject = Morris.Grid.prototype.autoGridLines
5+
6+
it 'should draw at fixed intervals', ->
7+
@subject(0, 4, 5).should.deep.equal [0, 1, 2, 3, 4]
8+
@subject(0, 400, 5).should.deep.equal [0, 100, 200, 300, 400]
9+
10+
it 'should pick intervals that show significant numbers', ->
11+
@subject(102, 499, 5).should.deep.equal [100, 200, 300, 400, 500]
12+
13+
it 'should draw zero when it falls within [ymin..ymax]', ->
14+
@subject(-100, 300, 5).should.deep.equal [-100, 0, 100, 200, 300]
15+
@subject(-50, 350, 5).should.deep.equal [-125, 0, 125, 250, 375]
16+
@subject(-400, 400, 5).should.deep.equal [-400, -200, 0, 200, 400]
17+
@subject(100, 500, 5).should.deep.equal [100, 200, 300, 400, 500]
18+
@subject(-500, -100, 5).should.deep.equal [-500, -400, -300, -200, -100]
19+
20+
it 'should generate decimal labels to 2 significant figures', ->
21+
@subject(0, 1, 5).should.deep.equal [0, 0.25, 0.5, 0.75, 1]
22+
@subject(0.1, 0.5, 5).should.deep.equal [0.1, 0.2, 0.3, 0.4, 0.5]
23+
24+
it 'should use integer intervals for intervals larger than 1', ->
25+
@subject(0, 9, 5).should.deep.equal [0, 3, 6, 9, 12]

spec/lib/grid/interval_spec.coffee

Lines changed: 0 additions & 42 deletions
This file was deleted.

spec/lib/grid/set_data_spec.coffee

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,12 @@ describe 'Morris.Grid#setData', ->
197197
line.data.length.should.equal 0
198198
line.setData([{x: 2, y: '12'}, {x: 1, y: '13.5'}, {x: 4, y: '14'}, {x: 3, y: '16'}])
199199
line.data.length.should.equal 4
200+
201+
it 'should automatically choose significant numbers for y-labels', ->
202+
line = Morris.Line
203+
element: 'graph',
204+
data: [{x: 1, y: 0}, {x: 2, y: 3600}]
205+
xkey: 'x'
206+
ykeys: ['y']
207+
labels: ['y']
208+
line.grid.should == [0, 1000, 2000, 3000, 4000]

0 commit comments

Comments
 (0)