timebars.coffee 3.18 KB
Newer Older
Kjetil Thuen's avatar
Kjetil Thuen committed
1
2
d3 = require 'd3-browserify'
lodash = require 'lodash'
3

4
5
completeData = {}

Kjetil Thuen's avatar
Kjetil Thuen committed
6
7
chartWidth = (chartId) ->
  parseInt d3.select(chartId).style "width"
8

Kjetil Thuen's avatar
Kjetil Thuen committed
9
10
chartHeight = (chartId) ->
  700
11

Kjetil Thuen's avatar
Kjetil Thuen committed
12
13
numBars = (chartId) ->
  vals = lodash.first(lodash.values completeData[chartId])
14
  vals.length
Kjetil Thuen's avatar
Kjetil Thuen committed
15

Kjetil Thuen's avatar
Kjetil Thuen committed
16
17
margin = (chartId) ->
  chartWidth(chartId) / 50
18

19
speed = -> 500
Kjetil Thuen's avatar
Kjetil Thuen committed
20
21
barThickness = (chartId) ->
  Math.floor(chartHeight(chartId) / numBars(chartId)) - 2
22

Kjetil Thuen's avatar
Kjetil Thuen committed
23
x = (chartId) ->
24
25
26
  d3.scale.linear()
    .domain [
      0,
Kjetil Thuen's avatar
Kjetil Thuen committed
27
28
29
      d3.max(valuesFromFrame(chartId, 0), (d) ->
        Math.max(d.rvalue, d.lvalue)
      )
30
    ]
Kjetil Thuen's avatar
Kjetil Thuen committed
31
    .range [ 0, (chartWidth(chartId) / 2) - (margin(chartId) * 2) ]
32

Kjetil Thuen's avatar
Kjetil Thuen committed
33
y = (chartId, val) ->
34
  d3.scale.linear()
Kjetil Thuen's avatar
Kjetil Thuen committed
35
36
    .domain(d3.extent valuesFromFrame(chartId, 0), (d) -> d.age)
    .range [ 0, chartHeight(chartId) ]
37

38
39
40
41
42
43
44
45
x_axis = d3.svg.axis()
  .orient "bottom"
  .ticks 5

y_axis = d3.svg.axis()
  .orient "left"
  .ticks 5

Kjetil Thuen's avatar
Kjetil Thuen committed
46
addBar = (newBar, chartId) ->
47
48
49
  barGroup = newBar.append "g"
    .attr "class", "valuepoint"
    .attr "transform", (d, i) ->
Kjetil Thuen's avatar
Kjetil Thuen committed
50
      "translate(0, " + (y(chartId)(i) + 1) + ")"
51
52
53

  barGroup.append "rect"
    .attr "class", "right"
Kjetil Thuen's avatar
Kjetil Thuen committed
54
55
56
    .attr "x", chartWidth(chartId) / 2 + margin(chartId)
    .attr "width", (d) -> x(chartId)(d.rvalue)
    .attr "height", barThickness chartId
57
58
59

  barGroup.append "rect"
    .attr "class", "left"
Kjetil Thuen's avatar
Kjetil Thuen committed
60
61
62
63
64
65
66
67
68
69
70
71
    .attr "x", (d) -> (chartWidth(chartId) / 2) -
        x(chartId)(d.lvalue) - margin(chartId)
    .attr "width", (d) -> x(chartId)(d.lvalue)
    .attr "height", barThickness(chartId)

valuesFromFrame = (chartId, frameNum) ->
  frameIndexes = lodash.keys(completeData[chartId])
  completeData[chartId]['' + frameIndexes[frameNum] + '']

updateChart = (chartId, frameNum) ->
  data = valuesFromFrame chartId, frameNum
  chart = d3.select chartId + " svg.chart"
72
  valuepoints = chart.selectAll "g.valuepoint"
73
    .data data, (d) -> d.birthyear
74
75
76

  valuepoints.transition()
    .attr "transform", (d, i) ->
Kjetil Thuen's avatar
Kjetil Thuen committed
77
      "translate(0, " + (y(chartId)(i) + 1) + ")"
78

Kjetil Thuen's avatar
Kjetil Thuen committed
79
  addBar valuepoints.enter(), chartId
80
81

  valuepoints.exit()
82
    .transition()
83
84
    .duration speed() / 2
    .attr "height", 0
85
    .remove()
86
  undefined
87

Kjetil Thuen's avatar
Kjetil Thuen committed
88
nextFrame = (chartId, frameNum) ->
89
90
  num = frameNum or 0
  num++
Kjetil Thuen's avatar
Kjetil Thuen committed
91
  if num >= lodash.keys(completeData[chartId]).length
92
    num = 0
Kjetil Thuen's avatar
Kjetil Thuen committed
93
  updateChart chartId, num
94
95
96
97
98
99
100
101
102
  num

#Constructor.
#
#The data parameter should be an object with named years. Each year member
#should be an array with at least two members (male and female, further members
#are ignored), each element in these arrays should contain an object that has
#the value property.
#
103
104
#The conteinarId is just a string identfying a div within wich the graph should
#be built. There can be several simultanious graphs
Kjetil Thuen's avatar
Kjetil Thuen committed
105
setupChart = (chartId, data) ->
106
  if data
Kjetil Thuen's avatar
Kjetil Thuen committed
107
    completeData[chartId] = data
108
109
110
111
112
113
114
115

  lodash.forEach (lodash.keys completeData), (id) ->
    d3.select id
      .html ""

    d3.select id
      .insert "svg"
        .attr "class", "chart"
Kjetil Thuen's avatar
Kjetil Thuen committed
116
        .attr "shape-rendering", "geometricPrecision"
117
118
        .attr "width", chartWidth(id)
        .attr "height", chartHeight(id)
119
120
121
      .call x_axis
      .call y_axis

122
123
124
    nextFrame id, 0

  window.onresize = setupChart
125

126
127
128
exports.setupChart = setupChart
exports.speed = speed
exports.nextFrame = nextFrame