mirror of
https://github.com/morrisjs/morris.js.git
synced 2024-11-10 21:36:34 +01:00
draw functionality broken out into methods on each class
This commit is contained in:
parent
14c56165c6
commit
32b06226c2
@ -26,7 +26,7 @@ class Morris.Area extends Morris.Line
|
||||
path = @paths[i]
|
||||
if path isnt null
|
||||
path = path + "L#{@transX(@xmax)},#{@bottom}L#{@transX(@xmin)},#{@bottom}Z"
|
||||
@morrisSVG.drawFilledPath(path, @fillForSeries(i))
|
||||
@drawFilledPath(path, @fillForSeries(i))
|
||||
super()
|
||||
|
||||
fillForSeries: (i) ->
|
||||
@ -35,3 +35,8 @@ class Morris.Area extends Morris.Line
|
||||
color.h,
|
||||
Math.min(255, color.s * 0.75),
|
||||
Math.min(255, color.l * 1.25))
|
||||
|
||||
drawFilledPath: (path, fill) ->
|
||||
@raphael.path(path)
|
||||
.attr('fill', fill)
|
||||
.attr('stroke-width', 0)
|
||||
|
@ -59,7 +59,7 @@ class Morris.Bar extends Morris.Grid
|
||||
prevLabelMargin = null
|
||||
for i in [0...@data.length]
|
||||
row = @data[@data.length - 1 - i]
|
||||
label = @morrisSVG.drawXAxisLabel(row._x, ypos, row.label)
|
||||
label = @drawXAxisLabel(row._x, ypos, row.label)
|
||||
labelBox = label.getBBox()
|
||||
# ensure a minimum of `xLabelMargin` pixels between labels, and ensure
|
||||
# labels don't overflow the container
|
||||
@ -94,7 +94,7 @@ class Morris.Bar extends Morris.Grid
|
||||
size = bottom - top
|
||||
|
||||
top -= lastTop if @options.stacked
|
||||
@morrisSVG.drawBar(left, top, barWidth, size, @colorFor(row, sidx, 'bar'))
|
||||
@drawBar(left, top, barWidth, size, @colorFor(row, sidx, 'bar'))
|
||||
|
||||
lastTop += size
|
||||
else
|
||||
@ -152,3 +152,13 @@ class Morris.Bar extends Morris.Grid
|
||||
"""
|
||||
x = @left + (index + 0.5) * @width / @data.length
|
||||
[content, x]
|
||||
|
||||
drawXAxisLabel: (xPos, yPos, text) ->
|
||||
label = @raphael.text(xPos, yPos, text)
|
||||
.attr('font-size', @options.gridTextSize)
|
||||
.attr('fill', @options.gridTextColor)
|
||||
|
||||
drawBar: (xPos, yPos, width, height, barColor) ->
|
||||
@raphael.rect(xPos, yPos, width, height)
|
||||
.attr('fill', barColor)
|
||||
.attr('stroke-width', 0)
|
||||
|
@ -54,7 +54,7 @@ class Morris.Donut
|
||||
redraw: ->
|
||||
@el.empty()
|
||||
|
||||
@morrisSVG = new Morris.SVG(@el[0], @options)
|
||||
@raphael = new Raphael(@el[0])
|
||||
|
||||
cx = @el.width() / 2
|
||||
cy = @el.height() / 2
|
||||
@ -71,14 +71,14 @@ class Morris.Donut
|
||||
@segments = []
|
||||
for d in @data
|
||||
next = last + min + C * (d.value / total)
|
||||
seg = new Morris.DonutSegment(cx, cy, w*2, w, last, next, @options.colors[idx % @options.colors.length], d)
|
||||
seg.render @morrisSVG
|
||||
seg = new Morris.DonutSegment(cx, cy, w*2, w, last, next, @options.colors[idx % @options.colors.length], d, @raphael)
|
||||
seg.render()
|
||||
@segments.push seg
|
||||
seg.on 'hover', @select
|
||||
last = next
|
||||
idx += 1
|
||||
@text1 = @morrisSVG.drawEmptyDonutLabel(cx, cy - 10, 15, 800)
|
||||
@text2 = @morrisSVG.drawEmptyDonutLabel(cx, cy + 10, 14)
|
||||
@text1 = @drawEmptyDonutLabel(cx, cy - 10, 15, 800)
|
||||
@text2 = @drawEmptyDonutLabel(cx, cy + 10, 14)
|
||||
max_value = Math.max.apply(null, d.value for d in @data)
|
||||
idx = 0
|
||||
for d in @data
|
||||
@ -109,12 +109,17 @@ class Morris.Donut
|
||||
text2scale = Math.min(maxWidth / text2bbox.width, maxHeightBottom / text2bbox.height)
|
||||
@text2.attr(transform: "S#{text2scale},#{text2scale},#{text2bbox.x + text2bbox.width / 2},#{text2bbox.y}")
|
||||
|
||||
drawEmptyDonutLabel: (xPos, yPos, fontSize, fontWeight) ->
|
||||
text = @raphael.text(xPos, yPos, '').attr('font-size', fontSize)
|
||||
text.attr('font-weight', fontWeight) if fontWeight?
|
||||
return text
|
||||
|
||||
|
||||
# A segment within a donut chart.
|
||||
#
|
||||
# @private
|
||||
class Morris.DonutSegment extends Morris.EventEmitter
|
||||
constructor: (@cx, @cy, @inner, @outer, p0, p1, @color, @data) ->
|
||||
constructor: (@cx, @cy, @inner, @outer, p0, p1, @color, @data, @raphael) ->
|
||||
@sin_p0 = Math.sin(p0)
|
||||
@cos_p0 = Math.cos(p0)
|
||||
@sin_p1 = Math.sin(p1)
|
||||
@ -147,9 +152,18 @@ class Morris.DonutSegment extends Morris.EventEmitter
|
||||
"M#{ix0},#{iy0}" +
|
||||
"A#{r},#{r},0,#{@long},0,#{ix1},#{iy1}")
|
||||
|
||||
render: (morrisSVG) ->
|
||||
@arc = morrisSVG.drawDonutArc(@hilight, @color)
|
||||
@seg = morrisSVG.drawDonutSegment(@path, @color, => @fire('hover', @))
|
||||
render: ->
|
||||
@arc = @drawDonutArc(@hilight, @color)
|
||||
@seg = @drawDonutSegment(@path, @color, => @fire('hover', @))
|
||||
|
||||
drawDonutArc: (path, color) ->
|
||||
@raphael.path(path)
|
||||
.attr(stroke: color, 'stroke-width': 2, opacity: 0)
|
||||
|
||||
drawDonutSegment: (path, color, hoverFunction) ->
|
||||
@raphael.path(path)
|
||||
.attr(fill: color, stroke: 'white', 'stroke-width': 3)
|
||||
.hover(hoverFunction)
|
||||
|
||||
select: =>
|
||||
unless @selected
|
||||
|
@ -26,8 +26,7 @@ class Morris.Grid extends Morris.EventEmitter
|
||||
@options.postUnits = options.units
|
||||
|
||||
# the raphael drawing instance
|
||||
@r = new Raphael(@el[0])
|
||||
@morrisSVG = new Morris.SVG(@el[0], @options)
|
||||
@raphael = new Raphael(@el[0])
|
||||
|
||||
# some redraw stuff
|
||||
@elementWidth = null
|
||||
@ -228,7 +227,7 @@ class Morris.Grid extends Morris.EventEmitter
|
||||
# If you need to re-size your charts, call this method after changing the
|
||||
# size of the container element.
|
||||
redraw: ->
|
||||
@morrisSVG.clear()
|
||||
@raphael.clear()
|
||||
@_calc()
|
||||
@drawGrid()
|
||||
@drawGoals()
|
||||
@ -239,12 +238,12 @@ class Morris.Grid extends Morris.EventEmitter
|
||||
#
|
||||
drawGoals: ->
|
||||
for goal, i in @options.goals
|
||||
@morrisSVG.drawGoal("M#{@left},#{@transY(goal)}H#{@left + @width}")
|
||||
@drawGoal("M#{@left},#{@transY(goal)}H#{@left + @width}")
|
||||
|
||||
# draw events vertical lines
|
||||
drawEvents: ->
|
||||
for event, i in @events
|
||||
@morrisSVG.drawEvent("M#{@transX(event)},#{@bottom}V#{@top}")
|
||||
@drawEvent("M#{@transX(event)},#{@bottom}V#{@top}")
|
||||
|
||||
# draw y axis labels, horizontal lines
|
||||
#
|
||||
@ -256,14 +255,17 @@ class Morris.Grid extends Morris.EventEmitter
|
||||
v = parseFloat(lineY.toFixed(@precision))
|
||||
y = @transY(v)
|
||||
if @options.axes
|
||||
@morrisSVG.drawYAxisLabel(@left - @options.padding / 2, y, @yAxisFormat(v))
|
||||
@drawYAxisLabel(@left - @options.padding / 2, y, @yAxisFormat(v))
|
||||
if @options.grid
|
||||
@morrisSVG.drawGridLine("M#{@left},#{y}H#{@left + @width}")
|
||||
@drawGridLine("M#{@left},#{y}H#{@left + @width}")
|
||||
|
||||
# @private
|
||||
#
|
||||
measureText: (text, fontSize = 12) ->
|
||||
@morrisSVG.measureText(text, fontSize)
|
||||
tt = @raphael.text(100, 100, text).attr('font-size', fontSize)
|
||||
ret = tt.getBBox()
|
||||
tt.remove()
|
||||
ret
|
||||
|
||||
# @private
|
||||
#
|
||||
@ -282,6 +284,27 @@ class Morris.Grid extends Morris.EventEmitter
|
||||
if hit?
|
||||
@hover.update(hit...)
|
||||
|
||||
drawGoal: (path) ->
|
||||
@raphael.path(path)
|
||||
.attr('stroke', @options.goalLineColors[i % @options.goalLineColors.length])
|
||||
.attr('stroke-width', @options.goalStrokeWidth)
|
||||
|
||||
drawEvent: (path) ->
|
||||
@raphael.path(path)
|
||||
.attr('stroke', @options.eventLineColors[i % @options.eventLineColors.length])
|
||||
.attr('stroke-width', @options.eventStrokeWidth)
|
||||
|
||||
drawYAxisLabel: (xPos, yPos, text) ->
|
||||
@raphael.text(xPos, yPos, text)
|
||||
.attr('font-size', @options.gridTextSize)
|
||||
.attr('fill', @options.gridTextColor)
|
||||
.attr('text-anchor', 'end')
|
||||
|
||||
drawGridLine: (path) ->
|
||||
@raphael.path(path)
|
||||
.attr('stroke', @options.gridLineColor)
|
||||
.attr('stroke-width', @options.gridStrokeWidth)
|
||||
|
||||
# Parse a date into a javascript timestamp
|
||||
#
|
||||
#
|
||||
|
@ -138,7 +138,7 @@ class Morris.Line extends Morris.Grid
|
||||
ypos = @bottom + @options.gridTextSize * 1.25
|
||||
prevLabelMargin = null
|
||||
drawLabel = (labelText, xpos) =>
|
||||
label = @morrisSVG.drawXAxisLabel(@transX(xpos), ypos, labelText)
|
||||
label = @drawXAxisLabel(@transX(xpos), ypos, labelText)
|
||||
labelBox = label.getBBox()
|
||||
# ensure a minimum of `xLabelMargin` pixels between labels, and ensure
|
||||
# labels don't overflow the container
|
||||
@ -168,12 +168,12 @@ class Morris.Line extends Morris.Grid
|
||||
for i in [@options.ykeys.length-1..0]
|
||||
path = @paths[i]
|
||||
if path isnt null
|
||||
@morrisSVG.drawLinePath(path, @colorFor(row, i, 'line')) #row isn't available here?
|
||||
@drawLinePath(path, @colorFor(row, i, 'line')) #row isn't available here?
|
||||
@seriesPoints = ([] for i in [0...@options.ykeys.length])
|
||||
for i in [@options.ykeys.length-1..0]
|
||||
for row in @data
|
||||
if row._y[i]?
|
||||
circle = @morrisSVG.drawLinePoint(row._x, row._y[i], @options.pointSize, @colorFor(row, i, 'point'), i)
|
||||
circle = @drawLinePoint(row._x, row._y[i], @options.pointSize, @colorFor(row, i, 'point'), i)
|
||||
else
|
||||
circle = null
|
||||
@seriesPoints[i].push(circle)
|
||||
@ -246,6 +246,29 @@ class Morris.Line extends Morris.Grid
|
||||
else
|
||||
@options.lineColors[sidx % @options.lineColors.length]
|
||||
|
||||
drawXAxisLabel: (xPos, yPos, text) ->
|
||||
@raphael.text(xPos, yPos, text)
|
||||
.attr('font-size', @options.gridTextSize)
|
||||
.attr('fill', @options.gridTextColor)
|
||||
|
||||
drawLinePath: (path, lineColor) ->
|
||||
@raphael.path(path)
|
||||
.attr('stroke', lineColor)
|
||||
.attr('stroke-width', @options.lineWidth)
|
||||
|
||||
drawLinePoint: (xPos, yPos, size, pointColor, lineIndex) ->
|
||||
@raphael.circle(xPos, yPos, size)
|
||||
.attr('fill', pointColor)
|
||||
.attr('stroke-width', @strokeWidthForSeries(lineIndex))
|
||||
.attr('stroke', @strokeForSeries(lineIndex))
|
||||
|
||||
# @private
|
||||
strokeWidthForSeries: (index) ->
|
||||
@options.pointWidths[index % @options.pointWidths.length]
|
||||
|
||||
# @private
|
||||
strokeForSeries: (index) ->
|
||||
@options.pointStrokeColors[index % @options.pointStrokeColors.length]
|
||||
|
||||
# generate a series of label, timestamp pairs for x-axis labels
|
||||
#
|
||||
|
@ -1,82 +0,0 @@
|
||||
class Morris.SVG
|
||||
|
||||
constructor: (element, options) ->
|
||||
@raphael = new Raphael(element)
|
||||
@options = options
|
||||
|
||||
clear: ->
|
||||
@raphael.clear()
|
||||
|
||||
drawGoal: (path) ->
|
||||
@raphael.path(path)
|
||||
.attr('stroke', @options.goalLineColors[i % @options.goalLineColors.length])
|
||||
.attr('stroke-width', @options.goalStrokeWidth)
|
||||
|
||||
drawEvent: (path) ->
|
||||
@raphael.path(path)
|
||||
.attr('stroke', @options.eventLineColors[i % @options.eventLineColors.length])
|
||||
.attr('stroke-width', @options.eventStrokeWidth)
|
||||
|
||||
drawYAxisLabel: (xPos, yPos, text) ->
|
||||
@raphael.text(xPos, yPos, text)
|
||||
.attr('font-size', @options.gridTextSize)
|
||||
.attr('fill', @options.gridTextColor)
|
||||
.attr('text-anchor', 'end')
|
||||
|
||||
drawXAxisLabel: (xPos, yPos, text) ->
|
||||
label = @raphael.text(xPos, yPos, text)
|
||||
.attr('font-size', @options.gridTextSize)
|
||||
.attr('fill', @options.gridTextColor)
|
||||
|
||||
drawGridLine: (path) ->
|
||||
@raphael.path(path)
|
||||
.attr('stroke', @options.gridLineColor)
|
||||
.attr('stroke-width', @options.gridStrokeWidth)
|
||||
|
||||
measureText: (text, fontSize = 12) ->
|
||||
tt = @raphael.text(100, 100, text).attr('font-size', fontSize)
|
||||
ret = tt.getBBox()
|
||||
tt.remove()
|
||||
ret
|
||||
|
||||
drawEmptyDonutLabel: (xPos, yPos, fontSize, fontWeight) ->
|
||||
text = @raphael.text(xPos, yPos, '').attr('font-size', fontSize)
|
||||
text.attr('font-weight', fontWeight) if fontWeight?
|
||||
return text
|
||||
|
||||
drawDonutArc: (path, color) ->
|
||||
@raphael.path(path).attr(stroke: color, 'stroke-width': 2, opacity: 0)
|
||||
|
||||
drawDonutSegment: (path, color, hoverFunction) ->
|
||||
@raphael.path(path)
|
||||
.attr(fill: color, stroke: 'white', 'stroke-width': 3)
|
||||
.hover(hoverFunction)
|
||||
|
||||
drawFilledPath: (path, fill) ->
|
||||
@raphael.path(path)
|
||||
.attr('fill', fill)
|
||||
.attr('stroke-width', 0)
|
||||
|
||||
drawLinePath: (path, lineColor) ->
|
||||
@raphael.path(path)
|
||||
.attr('stroke', lineColor)
|
||||
.attr('stroke-width', @options.lineWidth)
|
||||
|
||||
drawLinePoint: (xPos, yPos, size, pointColor, lineIndex) ->
|
||||
circle = @raphael.circle(xPos, yPos, size)
|
||||
.attr('fill', pointColor)
|
||||
.attr('stroke-width', @strokeWidthForSeries(lineIndex))
|
||||
.attr('stroke', @strokeForSeries(lineIndex))
|
||||
|
||||
drawBar: (xPos, yPos, width, height, barColor) ->
|
||||
@raphael.rect(xPos, yPos, width, height)
|
||||
.attr('fill', barColor)
|
||||
.attr('stroke-width', 0)
|
||||
|
||||
# @private
|
||||
strokeWidthForSeries: (index) ->
|
||||
@options.pointWidths[index % @options.pointWidths.length]
|
||||
|
||||
# @private
|
||||
strokeForSeries: (index) ->
|
||||
@options.pointStrokeColors[index % @options.pointStrokeColors.length]
|
@ -25,10 +25,10 @@ describe 'Morris.Line', ->
|
||||
pointStrokeColors: [red, blue]
|
||||
pointWidths: [1, 2]
|
||||
pointFillColors: [null, red]
|
||||
chart.morrisSVG.strokeWidthForSeries(0).should.equal 1
|
||||
chart.morrisSVG.strokeForSeries(0).should.equal red
|
||||
chart.morrisSVG.strokeWidthForSeries(1).should.equal 2
|
||||
chart.morrisSVG.strokeForSeries(1).should.equal blue
|
||||
chart.strokeWidthForSeries(0).should.equal 1
|
||||
chart.strokeForSeries(0).should.equal red
|
||||
chart.strokeWidthForSeries(1).should.equal 2
|
||||
chart.strokeForSeries(1).should.equal blue
|
||||
chart.colorFor(chart.data[0], 0, 'point').should.equal chart.colorFor(chart.data[0], 0, 'line')
|
||||
chart.colorFor(chart.data[1], 1, 'point').should.equal red
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user