plasticine 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9d62d2afccb060f20cb4523c1e081bf75910f743840dd8d26ac99e6588ed52e
4
- data.tar.gz: 0335c9774a4a128d100a517ee5b110e7290299e713e6cea0d22ac24797dbc6e5
3
+ metadata.gz: e06229beab9aeca28afd22544eae0ba299a3b544aa1e2ef7dd647d829d05352e
4
+ data.tar.gz: ae6df7846d7a31f858d5e8d73d002056258e3e54ec0879cd393210d5048e4692
5
5
  SHA512:
6
- metadata.gz: 31ee24c88036f9a6f0b4ffc0dfb4c3b1268235b027e04ca4936a445efff1649eb35f4bfb5e41ba248302424cfe95838e918fc7184a26a84b042f21e7590b92de
7
- data.tar.gz: 6eb1a4dec359cad505ca6522a927904b84da027cf93ea3df7997b494642622d01c73f7973cb9f84c46e6e58b33f7dce1946e6dabb0b63668143ca706848e6992
6
+ metadata.gz: 4717e5615651acd9da8a1818cf0843bd6cf5f8152dbb5c97a96bf4c535d8ba614127e9d198121c13dc6951947540b28e86e3c41e1179e36e5370d4bf2e007a24
7
+ data.tar.gz: 2b8a9fe7bf6579310fe65a68ac3216b56b02031dacebf0116ea3296959324b87891079e6576849ba7f30f1ee26dc062ceeb67251f9299383e590a03b66be5d7e
@@ -6,6 +6,7 @@ class Plasticine
6
6
  $('div.plasticine').each (i, visual) =>
7
7
  switch $(visual).data('visual')
8
8
  when 'column' then @visuals.push new PlasticineColumn $(visual)
9
+ when 'line' then @visuals.push new PlasticineLine $(visual)
9
10
 
10
11
  d3IsLoaded: () -> if d3? then true else false
11
12
 
@@ -2,29 +2,24 @@ class @PlasticineColumn
2
2
  constructor: (@holder) ->
3
3
  @holder = $('.plasticine-column')
4
4
 
5
- @setLocale()
5
+ PlasticineHelpers.setLocale()
6
6
  @drawTooltip()
7
7
 
8
- width = @holderWidth()
9
- height = @holder.height()
10
-
11
- @xScale = d3.scale.ordinal()
8
+ @xScale = d3.scaleBand()
12
9
  @setXScaleRange()
13
10
 
14
- @yScale = d3.scale.linear().range([height,0])
11
+ @yScale = d3.scaleLinear().range([@holder.height(),0])
15
12
 
16
13
  @setXAxis()
17
14
  @setYAxis()
18
15
 
19
- @svg = d3.select("##{@holder.attr('id')}").append('svg').style('width', width).style('height', height).append('g')
20
-
21
- d3.json @holder.data('url'), (data) => @build(data)
16
+ @svg = d3.select("##{@holder.attr('id')}").append('svg').style('width', @holderWidth()).style('height', @holder.height()).append('g')
17
+ d3.json(@holder.data('url')).then (data) => @build(data)
22
18
 
23
19
 
24
20
  build: (data) ->
25
21
  columnIds = data.columns[0].y_values.map (d,i) -> "col#{i+1}"
26
-
27
- @colGroup = d3.scale.ordinal().range(columnIds).domain(columnIds)
22
+ colGroup = d3.scaleBand().range(columnIds).domain(columnIds)
28
23
 
29
24
  @xAxisFormat = data.axis_x_format
30
25
  @yAxisFormat = data.axis_y_format
@@ -33,9 +28,9 @@ class @PlasticineColumn
33
28
 
34
29
  data.columns.forEach (d) =>
35
30
  y0 = 0
36
- d.yValues = @colGroup.domain().map (name,i) => { name: name, y0: y0, y1: y0 += @formatValue(d.y_values[i], @yAxisFormat) }
31
+ d.yValues = colGroup.domain().map (name,i) => { name: name, y0: y0, y1: y0 += PlasticineHelpers.parseValue(d.y_values[i], @yAxisFormat) }
37
32
  d.total = d.yValues[d.yValues.length - 1].y1
38
- d.x = @formatValue(d.x_value, @xAxisFormat)
33
+ d.x = PlasticineHelpers.parseValue(d.x_value, @xAxisFormat)
39
34
 
40
35
  @xScale.domain data.columns.map( (d) -> d.x )
41
36
  @yScale.domain [0, d3.max(data.columns, (d) => d.total * @holder.data('y-spacing-ratio'))]
@@ -68,67 +63,38 @@ class @PlasticineColumn
68
63
  @refreshYAxis()
69
64
 
70
65
 
71
- formatValue: (value, format) ->
72
- switch format
73
- when 'date' then new Date(value)
74
- else value
66
+ hideTooltip: () -> @holder.find('.tooltip').hide()
75
67
 
76
68
  holderWidth: () -> @holder.width()
77
69
 
78
- refreshXAxis: () ->
79
- @setXAxis()
80
- @svg.select('.x.axis').call @xAxis
81
-
82
-
83
- refreshYAxis: () ->
84
- @setYAxis()
85
- @svg.select('.y.axis').call @yAxis
86
-
87
-
88
- setXAxis: () ->
89
- @xAxis = d3.svg.axis().scale(@xScale).orient('bottom')
90
- @xAxis.tickSize -@holder.height()
91
-
92
- switch @xAxisFormat
93
- when 'date' then @xAxis.tickFormat(d3.time.format('%b'))
94
- when 'quarter' then @xAxis.tickFormat (d) => @toQuarter(d)
95
- when 'year' then @xAxis.tickFormat (d) => @toYear(d)
96
- when 'money' then @xAxis.tickFormat (d) => @toPrice(d)
97
-
98
-
99
- setYAxis: () ->
100
- @yAxis = d3.svg.axis().scale(@yScale).orient("left");
101
- @yAxis.tickSize -@holderWidth()
102
- @yAxis.ticks @yAxisTickCount
103
-
104
- switch @yAxisFormat
105
- when 'date' then @yAxis.tickFormat(d3.time.format('%b'))
106
- when 'money' then @yAxis.tickFormat (d) => @toPrice(d)
107
-
108
- hideTooltip: () -> @holder.find('.tooltip').hide()
109
-
110
70
  refreshColumns: () ->
111
71
  self = this
112
72
 
113
73
  $('g.column').remove()
114
74
 
115
- @columns.enter().append('g')
116
- .attr('class', 'column')
75
+ @columns.enter().append("g").attr('class', 'column')
117
76
  .attr('data-x-val', (d) -> d.x_value)
118
- .attr('transform', (d) => 'translate(' + @xScale(d.x) + ',0)')
119
77
  .attr('x', (d) => @xScale(d.x))
78
+ .attr('transform', (d) => 'translate(' + @xScale(d.x) + ',0)')
120
79
  .on("mouseover", (d) -> self.showTooltip(@, d))
121
80
  .on("mouseout", (d) -> self.hideTooltip(@))
122
- @columns.exit().remove()
123
81
 
124
- @columns.selectAll('rect')
125
- .data((d) -> d.yValues)
126
- .enter()
127
- .append('rect')
128
- .attr('width', @xScale.rangeBand())
129
- .attr('y', (d) => @yScale d.y1)
130
- .attr('height', (d) => @yScale(d.y0) - @yScale(d.y1))
131
- .attr('class', (d) => @colGroup d.name)
82
+ .selectAll("rect").data((d) => d.yValues).enter()
83
+ .append("rect")
84
+ .attr('class', (d,i) => "col#{i+1}")
85
+ .attr("width", @xScale.bandwidth())
86
+ .attr("y", (d) => @yScale d.y1)
87
+ .attr("height", (d) => @yScale(d.y0) - @yScale(d.y1))
88
+
89
+
90
+ refreshXAxis: () ->
91
+ @setXAxis()
92
+ @svg.select('.x.axis').call @xAxis
93
+
94
+
95
+ refreshYAxis: () ->
96
+ @setYAxis()
97
+ @svg.select('.y.axis').call @yAxis
132
98
 
133
99
 
134
100
  resizeX: () ->
@@ -142,24 +108,15 @@ class @PlasticineColumn
142
108
  @refreshColumns()
143
109
 
144
110
 
145
- setLocale: () ->
146
- french = d3.locale(
147
- "decimal": ",",
148
- "thousands": " ",
149
- "grouping": [3],
150
- "currency": ["$", ""],
151
- "dateTime": "%a %b %e %X %Y",
152
- "date": "%d-%m-%Y",
153
- "time": "%H:%M:%S",
154
- "periods": ["AM", "PM"],
155
- "days": ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"],
156
- "shortDays": ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"],
157
- "months": ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"],
158
- "shortMonths": ["Jan", "Fev", "Mar", "Avr", "Mai", "Jun", "Jul", "Aou", "Sep", "Oct", "Nov", "Dec"]
159
- )
111
+ setXAxis: () ->
112
+ @xAxis = d3.axisBottom(@xScale)
113
+ @xAxis.tickSize -@holder.height()
160
114
 
161
- d3.time.format = french.timeFormat
162
- d3.format = french.numberFormat
115
+ switch @xAxisFormat
116
+ when 'date' then @xAxis.tickFormat(d3.timeFormat('%b'))
117
+ when 'quarter' then @xAxis.tickFormat (d) => PlasticineHelpers.toQuarter(d, @quarterStartMonth)
118
+ when 'year' then @xAxis.tickFormat (d) => PlasticineHelpers.toYear(d, @quarterStartMonth)
119
+ when 'money' then @xAxis.tickFormat (d) => PlasticineHelpers.toPrice(d)
163
120
 
164
121
 
165
122
  setXScaleRange: () ->
@@ -167,8 +124,18 @@ class @PlasticineColumn
167
124
  columnsLeftPadding = @holder.data('columns-left-padding')
168
125
  columnsRightPadding = @holder.data('columns-right-padding')
169
126
  width = @holderWidth()
127
+
128
+ @xScale = @xScale.rangeRound([columnsLeftPadding, width - columnsRightPadding]).padding(columnsMargin);
129
+
130
+
131
+ setYAxis: () ->
132
+ @yAxis = d3.axisLeft(@yScale)
133
+ @yAxis.tickSize -@holderWidth()
134
+ @yAxis.ticks @yAxisTickCount
170
135
 
171
- @xScale = @xScale.rangeRoundBands([columnsLeftPadding, width - columnsRightPadding], columnsMargin, 0)
136
+ switch @yAxisFormat
137
+ when 'date' then @yAxis.tickFormat(d3.timeFormat('%b'))
138
+ when 'money' then @yAxis.tickFormat (d) => PlasticineHelpers.toPrice(d)
172
139
 
173
140
 
174
141
  showTooltip: (bar, data) ->
@@ -190,54 +157,3 @@ class @PlasticineColumn
190
157
  .style("left", tooltipX + "px")
191
158
  .style("top", (yPosition - tooltip.outerHeight()) + "px")
192
159
 
193
-
194
- toPrice: (amount) ->
195
- if amount is 0
196
- price = "0"
197
- else
198
- price = String(amount)[0..-3]
199
- price = "0" if price is ""
200
-
201
- price = switch price.length
202
- when 4 then [price.slice(0, 1), ' ', price.slice(1)].join('')
203
- when 5 then [price.slice(0, 2), ' ', price.slice(2)].join('')
204
- when 6 then [price.slice(0, 3), ' ', price.slice(3)].join('')
205
- when 7 then [price.slice(0, 4), ' ', price.slice(4)].join('')
206
- else price
207
-
208
- # Show decimals
209
- #price += ',' + String(amount).slice(-2)
210
-
211
- price += '$'
212
-
213
-
214
- toQuarter: (strDate) ->
215
- date = new Date(strDate + 'T12:00:00')
216
-
217
- month = date.getMonth() + 1
218
- monthEquiv = (month + (13 - @quarterStartMonth)) % 12
219
-
220
- value = switch
221
- when monthEquiv <= 3 then 'Q1'
222
- when monthEquiv <= 6 then 'Q2'
223
- when monthEquiv <= 9 then 'Q3'
224
- else 'Q4'
225
-
226
- year = Number(date.getFullYear())
227
-
228
- if (value is "Q1" and @quarterStartMonth >= 10) or ((value is "Q1" or value is "Q2") and @quarterStartMonth >= 7 and @quarterStartMonth < 10)
229
- year += 1
230
-
231
- value += " #{year}"
232
- value
233
-
234
-
235
- toYear: (strDate) ->
236
- date = new Date(strDate + 'T12:00:00')
237
-
238
- year = Number(date.getFullYear())
239
-
240
- if @quarterStartMonth >= 7 and (date.getMonth() + 1) >= 7
241
- year += 1
242
-
243
- year
@@ -0,0 +1,77 @@
1
+ @PlasticineHelpers = {}
2
+
3
+
4
+ PlasticineHelpers.parseValue = (value, format) ->
5
+ switch format
6
+ when 'date' then new Date(value)
7
+ else value
8
+
9
+ PlasticineHelpers.setLocale = () ->
10
+ d3.timeFormatDefaultLocale(
11
+ "decimal": ",",
12
+ "thousands": " ",
13
+ "grouping": [3],
14
+ "currency": ["$", ""],
15
+ "dateTime": "%a %b %e %X %Y",
16
+ "date": "%d-%m-%Y",
17
+ "time": "%H:%M:%S",
18
+ "periods": ["AM", "PM"],
19
+ "days": ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"],
20
+ "shortDays": ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"],
21
+ "months": ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"],
22
+ "shortMonths": ["Jan", "Fev", "Mar", "Avr", "Mai", "Jun", "Jul", "Aou", "Sep", "Oct", "Nov", "Dec"]
23
+ )
24
+
25
+
26
+ PlasticineHelpers.toPrice = (amount) ->
27
+ if amount is 0
28
+ price = "0"
29
+ else
30
+ price = String(amount)[0..-3]
31
+ price = "0" if price is ""
32
+
33
+ price = switch price.length
34
+ when 4 then [price.slice(0, 1), ' ', price.slice(1)].join('')
35
+ when 5 then [price.slice(0, 2), ' ', price.slice(2)].join('')
36
+ when 6 then [price.slice(0, 3), ' ', price.slice(3)].join('')
37
+ when 7 then [price.slice(0, 1), ' ', price.slice(1, 4), ' ', price.slice(4)].join('')
38
+ when 8 then [price.slice(0, 2), ' ', price.slice(2, 5), ' ', price.slice(4)].join('')
39
+ else price
40
+
41
+ # Show decimals
42
+ #price += ',' + String(amount).slice(-2)
43
+
44
+ price += ' $'
45
+
46
+
47
+ PlasticineHelpers.toQuarter = (strDate, quarterStartMonth) ->
48
+ date = new Date(strDate + 'T12:00:00')
49
+ month = date.getMonth() + 1
50
+ monthEquiv = (month + (13 - quarterStartMonth)) % 12
51
+
52
+ value = switch
53
+ when monthEquiv <= 3 then 'Q1'
54
+ when monthEquiv <= 6 then 'Q2'
55
+ when monthEquiv <= 9 then 'Q3'
56
+ else 'Q4'
57
+
58
+ year = Number(date.getFullYear())
59
+
60
+ if (value is "Q1" and quarterStartMonth >= 10) or ((value is "Q1" or value is "Q2") and quarterStartMonth >= 7 and quarterStartMonth < 10)
61
+ year += 1
62
+
63
+ value += " #{year}"
64
+ value
65
+
66
+
67
+ PlasticineHelpers.toYear = (strDate, quarterStartMonth) ->
68
+ date = new Date(strDate + 'T12:00:00')
69
+
70
+ year = Number(date.getFullYear())
71
+
72
+ if quarterStartMonth >= 7 and (date.getMonth() + 1) >= 7
73
+ year += 1
74
+
75
+ year
76
+
77
+
@@ -1,3 +1,5 @@
1
1
  //= require d3
2
2
  //= require ./base
3
+ //= require ./helpers
3
4
  //= require ./column
5
+ //= require ./line
@@ -0,0 +1,143 @@
1
+ class @PlasticineLine
2
+ constructor: (@holder) ->
3
+ @holder = $('.plasticine-line')
4
+
5
+ PlasticineHelpers.setLocale()
6
+ #@drawTooltip()
7
+
8
+ @xScale = d3.scaleBand()
9
+ @setXScaleRange()
10
+
11
+ @yScale = d3.scaleLinear().range([@holder.height(),0])
12
+
13
+ @setXAxis()
14
+ @setYAxis()
15
+
16
+ @svg = d3.select("##{@holder.attr('id')}").append('svg').style('width', @holderWidth()).style('height', @holder.height()).append('g')
17
+ d3.json(@holder.data('url')).then (data) => @build(data)
18
+
19
+
20
+ build: (data) ->
21
+ @xAxisFormat = data['axis_x_format']
22
+ @yAxisFormat = data['axis_y_format']
23
+ @yAxisTickCount = data['axis_y_tick_count']
24
+ @chartLayout = data['chart_layout']
25
+ @quarterStartMonth = Number(data.quarter_start_month)
26
+
27
+ maxY = if @chartLayout == 'area' then data['max_y_stack'] * 1.1 else data['max_y']
28
+
29
+ data['lines'].forEach (line) =>
30
+ line.dots.forEach (d) =>
31
+ d.x = PlasticineHelpers.parseValue(d.x, @xAxisFormat)
32
+
33
+ @xScale.domain data['lines'][0].dots.map( (d) -> d.x )
34
+ @yScale.domain [0, maxY]
35
+
36
+ @drawYAxis()
37
+
38
+ if @chartLayout == 'area'
39
+ stackedDataset = []
40
+ stackedKeys = []
41
+
42
+ data['lines'].forEach (line,i) =>
43
+ line.dots.forEach (d,j) =>
44
+ stackedDataset.push { x: d.x } if i == 0
45
+ stackedKeys.push "y#{i+1}" if j == 0
46
+ stackedDataset[j]["y#{i+1}"] = d.y
47
+
48
+ stack = d3.stack().keys(stackedKeys)
49
+ series = stack(stackedDataset);
50
+
51
+ @chartPath = d3.area().curve(d3.curveCardinal)
52
+ .x( (d,i) => @xScale(stackedDataset[i].x) )
53
+ .y0( (d) => @yScale(d[0]) )
54
+ .y1( (d) => @yScale(d[1]) )
55
+ else
56
+ series = data['lines']
57
+ @chartPath = d3.line().curve(d3.curveCardinal)
58
+ .x( (d) => @xScale(d.x))
59
+ .y( (d) => @yScale(d.y))
60
+
61
+ @lines = @svg.append('g').attr('class', "elements #{@chartLayout}").selectAll('.element').data(series)
62
+ @refreshLines()
63
+
64
+ @drawXAxis()
65
+
66
+ d3.select(window).on("resize." + @holder.attr("id"), () => @resizeX())
67
+
68
+
69
+ refreshLines: () ->
70
+ $('g.element').remove()
71
+
72
+ element = @lines.enter().append('g').attr('class', "element")
73
+ element.append("path")
74
+ .attr('class', 'line')
75
+ .attr('d', (d) => if @chartLayout == 'area' then @chartPath(d) else @chartPath(d.dots))
76
+
77
+
78
+ drawXAxis: () ->
79
+ height = @holder.height()
80
+ @svg.append('g').attr('class', 'x axis')
81
+ .attr('transform', 'translate(0,' + height + ')')
82
+ .call @xAxis
83
+
84
+ @refreshXAxis()
85
+
86
+
87
+ drawYAxis: () ->
88
+ group = @svg.append("g").attr("class", "y axis").call @yAxis
89
+ group.selectAll("g").filter((d) -> d).classed("minor", true)
90
+
91
+ @refreshYAxis()
92
+
93
+
94
+ holderWidth: () -> @holder.width()
95
+
96
+ refreshXAxis: () ->
97
+ @setXAxis()
98
+ @svg.select('.x.axis').call @xAxis
99
+
100
+
101
+ refreshYAxis: () ->
102
+ @setYAxis()
103
+ @svg.select('.y.axis').call @yAxis
104
+
105
+
106
+ resizeX: () ->
107
+ d3.select(@svg.node().parentNode).style('width', @holderWidth() + 'px')
108
+
109
+ @setXScaleRange()
110
+
111
+ @refreshXAxis()
112
+ @refreshYAxis()
113
+ @refreshLines()
114
+
115
+
116
+ setXAxis: () ->
117
+ @xAxis = d3.axisBottom(@xScale)
118
+ @xAxis.tickSize -@holder.height()
119
+
120
+ switch @xAxisFormat
121
+ when 'date' then @xAxis.tickFormat(d3.timeFormat('%b'))
122
+ when 'quarter' then @xAxis.tickFormat (d) => PlasticineHelpers.toQuarter(d, @quarterStartMonth)
123
+ when 'year' then @xAxis.tickFormat (d) => PlasticineHelpers.toYear(d, @quarterStartMonth)
124
+ when 'money' then @xAxis.tickFormat (d) => PlasticineHelpers.toPrice(d)
125
+
126
+
127
+ setXScaleRange: () ->
128
+ linesMargin = @holder.data('lines-margin')
129
+ linesLeftPadding = @holder.data('lines-left-padding')
130
+ linesRightPadding = @holder.data('lines-right-padding')
131
+ width = @holderWidth()
132
+
133
+ @xScale = @xScale.rangeRound([linesLeftPadding, width - linesRightPadding]).padding(linesMargin);
134
+
135
+
136
+ setYAxis: () ->
137
+ @yAxis = d3.axisLeft(@yScale)
138
+ @yAxis.tickSize -@holderWidth()
139
+ @yAxis.ticks @yAxisTickCount
140
+
141
+ switch @yAxisFormat
142
+ when 'date' then @yAxis.tickFormat(d3.timeFormat('%b'))
143
+ when 'money' then @yAxis.tickFormat (d) => PlasticineHelpers.toPrice(d)
@@ -1,5 +1,5 @@
1
1
  div.plasticine-column{border:none;clear:both;height:500px;margin:0;padding:0;width:100%;
2
- svg{overflow:visible;height:100%;width:100%;}
2
+ svg{overflow:hidden;height:100%;width:100%;}
3
3
 
4
4
  path{fill:none;opacity:0;}
5
5
 
@@ -1,4 +1,5 @@
1
1
  /*
2
2
  *= require ./base
3
3
  *= require ./column
4
+ *= require ./line
4
5
  */
@@ -0,0 +1,67 @@
1
+ div.plasticine-line{border:none;clear:both;height:500px;margin:0;padding:0;width:100%;
2
+ svg{overflow:hidden;height:100%;width:100%;}
3
+
4
+ path{fill:none;opacity:0;}
5
+
6
+ g.axis{shape-rendering:crispEdges;
7
+ g.tick {
8
+ line{stroke:#efefef;}
9
+ .minor line {stroke:#efefef;}
10
+ text{text-transform:uppercase;fill:#999;font-size:1.4rem;font-weight:500;}
11
+ }
12
+
13
+ &.x g.tick{
14
+ line{opacity:0;}
15
+ text{
16
+ transform: translate(0px,10px);
17
+ -ms-transform: translate(0px,10px);
18
+ -webkit-transform: translate(0px,10px);
19
+ -moz-transform: translate(0px,10px);
20
+ }
21
+ }
22
+
23
+ &.y g.tick{
24
+ text{text-align:right;}
25
+ }
26
+ }
27
+
28
+ g.elements.line g.element{
29
+ path{opacity:1;stroke-width:2px;}
30
+
31
+ &:nth-child(1) path{stroke:#00ccff;}
32
+ &:nth-child(2) path{stroke:#0099ff;}
33
+ &:nth-child(3) path{stroke:#6633cc;}
34
+ &:nth-child(4) path{stroke:#9900ff;}
35
+ &:nth-child(5) path{stroke:#ff00cc;}
36
+ &:nth-child(6) path{stroke:#ff0000;}
37
+ &:nth-child(7) path{stroke:#ff6600;}
38
+ &:nth-child(8) path{stroke:#ffcc00;}
39
+ &:nth-child(9) path{stroke:#7fe533;}
40
+ &:nth-child(10) path{stroke:#00ffcc;}
41
+ &:nth-child(11) path{stroke:#02b490;}
42
+ &:nth-child(12) path{stroke:#047794;}
43
+ &:nth-child(13) path{stroke:#04568d;}
44
+ &:nth-child(14) path{stroke:#3b1881;}
45
+ &:nth-child(15) path{stroke:#500384;}
46
+ }
47
+
48
+ g.elements.area g.element{
49
+ path{opacity:1;}
50
+ &:nth-child(1) path{fill:#00ccff;stroke:#00ccff;}
51
+ &:nth-child(2) path{fill:#0099ff;stroke:#0099ff;}
52
+ &:nth-child(3) path{fill:#6633cc;stroke:#6633cc;}
53
+ &:nth-child(4) path{fill:#9900ff;stroke:#9900ff;}
54
+ &:nth-child(5) path{fill:#ff00cc;stroke:#ff00cc;}
55
+ &:nth-child(6) path{fill:#ff0000;stroke:#ff0000;}
56
+ &:nth-child(7) path{fill:#ff6600;stroke:#ff6600;}
57
+ &:nth-child(8) path{fill:#ffcc00;stroke:#ffcc00;}
58
+ &:nth-child(9) path{fill:#7fe533;stroke:#7fe533;}
59
+ &:nth-child(10) path{fill:#00ffcc;stroke:#00ffcc;}
60
+ &:nth-child(11) path{fill:#02b490;stroke:#02b490;}
61
+ &:nth-child(12) path{fill:#047794;stroke:#047794;}
62
+ &:nth-child(13) path{fill:#04568d;stroke:#04568d;}
63
+ &:nth-child(14) path{fill:#3b1881;stroke:#3b1881;}
64
+ &:nth-child(15) path{fill:#500384;stroke:#500384;}
65
+ }
66
+ }
67
+
File without changes
File without changes
data/config/routes.rb CHANGED
File without changes
@@ -0,0 +1,77 @@
1
+ class Plasticine::Builder::Line < Plasticine::Builder::Base
2
+ attr_reader :lines
3
+
4
+ def initialize(id, options={})
5
+ super
6
+
7
+ @visual.merge! lines: [], nature: 'line', axis_x_format: :string, axis_y_format: :number, axis_y_tick_count: 10, chart_layout: 'line', order: nil, quarter_start_month: 1
8
+ @lines = {}
9
+ end
10
+
11
+
12
+ def axis_x_format=(format)
13
+ @visual[:axis_x_format] = format
14
+ end
15
+
16
+ def axis_y_format=(format)
17
+ @visual[:axis_y_format] = format
18
+ end
19
+
20
+ def axis_y_tick_count=(tick_count)
21
+ @visual[:axis_y_tick_count] = tick_count
22
+ end
23
+
24
+ def chart_layout=(clayout)
25
+ @visual[:chart_layout] = clayout
26
+ end
27
+
28
+ def quarter_start_month=(month)
29
+ @visual[:quarter_start_month] = month
30
+ end
31
+
32
+ def order=(direction)
33
+ @visual[:order] = direction # asc or desc
34
+ end
35
+
36
+
37
+ def add_line(id, label)
38
+ @lines[id] = { label: label, dots: [], total_y: 0 } if not @lines[id]
39
+ end
40
+
41
+ def add_dot(line_id, x, y)
42
+ @lines[line_id][:dots] << { x: x, y: y }
43
+ @lines[line_id][:total_y] += y
44
+ end
45
+
46
+ def close_visual
47
+ super
48
+
49
+ #@chart[:legend] = (@chart[:lines].length > 1) if @chart[:legend].nil?
50
+ set_max_y
51
+ @visual[:lines] = @lines.each_value.map { |d| d }
52
+
53
+ if @visual[:order]
54
+ @visual[:lines] = @visual[:lines].sort_by{ |l| l[:total_y] }
55
+ @visual[:lines].reverse! if @visual[:order] == 'asc'
56
+ end
57
+
58
+ end
59
+
60
+ def set_max_y
61
+ stacks = {}
62
+ max_y = 0
63
+
64
+ @lines.each_value do |line|
65
+ line[:dots].each do |dot|
66
+ key = dot[:x].to_s
67
+ stacks[key] = 0 if not stacks[key]
68
+ stacks[key] += dot[:y]
69
+ max_y = dot[:y] if max_y < dot[:y]
70
+ end
71
+ end
72
+
73
+ @visual[:max_y_stack] = stacks.max_by{|k,v| v}[1] # Return the highest stacked value for a specific X
74
+ @visual[:max_y] = max_y
75
+ end
76
+
77
+ end
@@ -41,3 +41,4 @@ end
41
41
 
42
42
  require 'plasticine/builder/base'
43
43
  require 'plasticine/builder/column'
44
+ require 'plasticine/builder/line'