opal-d3 0.0.20170205

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/Gemfile +3 -0
  4. data/README.md +7 -0
  5. data/Rakefile +31 -0
  6. data/d3.js +16393 -0
  7. data/demo/Gemfile +4 -0
  8. data/demo/README.md +7 -0
  9. data/demo/app/data/elections_2016.rb +10 -0
  10. data/demo/app/data/harry_potter.rb +19 -0
  11. data/demo/app/data/iphones.rb +29 -0
  12. data/demo/app/data/london_population.rb +26 -0
  13. data/demo/app/data/man_vs_horse.rb +55 -0
  14. data/demo/app/data/mtg_modern_colors.rb +96 -0
  15. data/demo/app/data/mtg_modern_creatures.rb +116 -0
  16. data/demo/app/data/olympics_2016_medals.rb +100 -0
  17. data/demo/app/data/paradox.rb +60 -0
  18. data/demo/app/data/polish_pms.rb +28 -0
  19. data/demo/app/data/star_trek_voyager.rb +183 -0
  20. data/demo/app/data/weather_in_london.rb +381 -0
  21. data/demo/app/elections_2016.rb +19 -0
  22. data/demo/app/harry_potter.rb +35 -0
  23. data/demo/app/iphones.rb +47 -0
  24. data/demo/app/london_population.rb +46 -0
  25. data/demo/app/london_population_area.rb +42 -0
  26. data/demo/app/man_vs_horse.rb +53 -0
  27. data/demo/app/mtg_modern_colors.rb +49 -0
  28. data/demo/app/mtg_modern_creatures.rb +63 -0
  29. data/demo/app/olympics_2016_medals.rb +54 -0
  30. data/demo/app/paradox.rb +57 -0
  31. data/demo/app/polish_pms.rb +53 -0
  32. data/demo/app/star_trek_voyager.rb +39 -0
  33. data/demo/app/weather_in_london.rb +62 -0
  34. data/demo/assets/d3.js +16393 -0
  35. data/demo/assets/style.css +0 -0
  36. data/demo/config.ru +39 -0
  37. data/demo/views/index.erb +21 -0
  38. data/demo/views/visualization.erb +29 -0
  39. data/lib/opal/d3/arc.rb +21 -0
  40. data/lib/opal/d3/area.rb +49 -0
  41. data/lib/opal/d3/axis.rb +77 -0
  42. data/lib/opal/d3/band_scale.rb +29 -0
  43. data/lib/opal/d3/collections.rb +10 -0
  44. data/lib/opal/d3/color.rb +78 -0
  45. data/lib/opal/d3/continuous_scale.rb +64 -0
  46. data/lib/opal/d3/creator.rb +11 -0
  47. data/lib/opal/d3/curve.rb +74 -0
  48. data/lib/opal/d3/dsv.rb +103 -0
  49. data/lib/opal/d3/ease.rb +319 -0
  50. data/lib/opal/d3/format.rb +97 -0
  51. data/lib/opal/d3/histograms.rb +44 -0
  52. data/lib/opal/d3/interpolate.rb +125 -0
  53. data/lib/opal/d3/line.rb +29 -0
  54. data/lib/opal/d3/map.rb +52 -0
  55. data/lib/opal/d3/misc.rb +15 -0
  56. data/lib/opal/d3/native.rb +84 -0
  57. data/lib/opal/d3/nest.rb +100 -0
  58. data/lib/opal/d3/ordinal_scale.rb +56 -0
  59. data/lib/opal/d3/path.rb +22 -0
  60. data/lib/opal/d3/pie.rb +23 -0
  61. data/lib/opal/d3/point_scale.rb +26 -0
  62. data/lib/opal/d3/polygon.rb +16 -0
  63. data/lib/opal/d3/quadtree.rb +95 -0
  64. data/lib/opal/d3/quantile_scale.rb +21 -0
  65. data/lib/opal/d3/quantize_scale.rb +23 -0
  66. data/lib/opal/d3/radial_area.rb +49 -0
  67. data/lib/opal/d3/radial_line.rb +29 -0
  68. data/lib/opal/d3/random.rb +12 -0
  69. data/lib/opal/d3/search.rb +28 -0
  70. data/lib/opal/d3/selection.rb +149 -0
  71. data/lib/opal/d3/sequential_scale.rb +96 -0
  72. data/lib/opal/d3/set.rb +33 -0
  73. data/lib/opal/d3/stack.rb +11 -0
  74. data/lib/opal/d3/statistics.rb +81 -0
  75. data/lib/opal/d3/symbol.rb +70 -0
  76. data/lib/opal/d3/threshold_scale.rb +23 -0
  77. data/lib/opal/d3/time_format.rb +48 -0
  78. data/lib/opal/d3/time_interval.rb +81 -0
  79. data/lib/opal/d3/transformations.rb +13 -0
  80. data/lib/opal/d3/version.rb +5 -0
  81. data/lib/opal/d3.rb +62 -0
  82. data/lib/opal-d3.rb +9 -0
  83. data/opal-d3.gemspec +20 -0
  84. data/spec/arc_spec.rb +86 -0
  85. data/spec/area_spec.rb +102 -0
  86. data/spec/axis_spec.rb +174 -0
  87. data/spec/band_scale_spec.rb +73 -0
  88. data/spec/color_spec.rb +74 -0
  89. data/spec/continuous_scale_spec.rb +217 -0
  90. data/spec/coverage_spec.rb +23 -0
  91. data/spec/creator_spec.rb +15 -0
  92. data/spec/curve_spec.rb +214 -0
  93. data/spec/dsv_spec.rb +194 -0
  94. data/spec/ease_spec.rb +370 -0
  95. data/spec/format_spec.rb +87 -0
  96. data/spec/histograms_spec.rb +61 -0
  97. data/spec/html/d3.js +16393 -0
  98. data/spec/html/index.html.erb +12 -0
  99. data/spec/interpolate_spec.rb +152 -0
  100. data/spec/line_spec.rb +58 -0
  101. data/spec/map_spec.rb +80 -0
  102. data/spec/misc_spec.rb +19 -0
  103. data/spec/nest_spec.rb +89 -0
  104. data/spec/objects_spec.rb +22 -0
  105. data/spec/ordinal_scale_spec.rb +59 -0
  106. data/spec/path_spec.rb +65 -0
  107. data/spec/pie_spec.rb +114 -0
  108. data/spec/point_scale_spec.rb +58 -0
  109. data/spec/polygon_spec.rb +51 -0
  110. data/spec/quadtree_spec.rb +128 -0
  111. data/spec/quantile_scale_spec.rb +24 -0
  112. data/spec/quantize_scale_spec.rb +40 -0
  113. data/spec/radial_area_spec.rb +127 -0
  114. data/spec/radial_line_spec.rb +54 -0
  115. data/spec/random_spec.rb +34 -0
  116. data/spec/search_spec.rb +69 -0
  117. data/spec/selection_data_spec.rb +71 -0
  118. data/spec/selection_manipulation_spec.rb +179 -0
  119. data/spec/selection_spec.rb +214 -0
  120. data/spec/sequential_scale_spec.rb +90 -0
  121. data/spec/set_spec.rb +57 -0
  122. data/spec/spec_helper.rb +2 -0
  123. data/spec/stack_spec.rb +23 -0
  124. data/spec/statistics_spec.rb +65 -0
  125. data/spec/symbol_spec.rb +121 -0
  126. data/spec/threshold_scale_spec.rb +28 -0
  127. data/spec/time_format_spec.rb +99 -0
  128. data/spec/time_interval_spec.rb +304 -0
  129. data/spec/transformations_spec.rb +51 -0
  130. metadata +258 -0
@@ -0,0 +1,42 @@
1
+ require "opal"
2
+ require "opal-d3"
3
+ require "data/london_population"
4
+
5
+ svg = D3.select("#visualization")
6
+ .append("svg")
7
+ .attr("height", "500px")
8
+ .attr("width", "100%")
9
+ width = svg.style("width").to_i
10
+
11
+ x = D3.scale_linear.domain([1801, 2011]).range([0, width-60])
12
+ y = D3.scale_linear.domain([0, 9_000_000]).range([400, 0])
13
+
14
+ greater_area = D3.area
15
+ .x{|d| x.(d.year) }
16
+ .y0(400)
17
+ .y1{|d| y.(d.greater)}
18
+ .curve(D3.curve_natural)
19
+
20
+ inner_area = D3.area
21
+ .x{|d| x.(d.year) }
22
+ .y0(400)
23
+ .y1{|d| y.(d.inner)}
24
+ .curve(D3.curve_natural)
25
+
26
+ graph_area = svg.append("g")
27
+ .attr("transform", "translate(60, 20)")
28
+ graph_area.append("path")
29
+ .attr("d", greater_area.(LondonPopulation))
30
+ .attr("fill", "pink")
31
+ graph_area.append("path")
32
+ .attr("d", inner_area.(LondonPopulation))
33
+ .attr("fill", "steelblue")
34
+
35
+ axis_bottom = D3.axis_bottom(x).tick_format(D3.format("d"))
36
+ axis_left = D3.axis_left(y).tick_format{|d| "#{d/1_000_000}M"}
37
+ graph_area.call(axis_left)
38
+ graph_area.append("g").attr("transform", "translate(0, 400)").call(axis_bottom)
39
+
40
+ list = D3.select("#visualization").append("table")
41
+ list.append("tr").append("td").text("Outer London").style("background", "pink")
42
+ list.append("tr").append("td").text("Inner London").style("background", "steelblue")
@@ -0,0 +1,53 @@
1
+ require "opal"
2
+ require "opal-d3"
3
+ require "data/man_vs_horse"
4
+
5
+ svg = D3.select("#visualization")
6
+ .append("svg")
7
+ .attr("height", "1200px")
8
+ .attr("width", "100%")
9
+ width = svg.style("width").to_i
10
+
11
+ max_time = ManVsHorse.flat_map{|d| [d.horse_time, d.human_time]}.max
12
+ min_year = ManVsHorse.map(&:year).min
13
+ max_year = ManVsHorse.map(&:year).max
14
+
15
+ x = D3.scale_linear.domain([0, max_time]).range([0,width-90]).nice
16
+ y = D3.scale_linear.domain([min_year, max_year+1]).range([0, 1160])
17
+ c = D3.scale_ordinal.range(D3.scheme_category_10)
18
+
19
+ graph_area = svg.append("g")
20
+ .attr("transform", "translate(60, 20)")
21
+
22
+ graph_area.append("g")
23
+ .select_all("rect")
24
+ .data(ManVsHorse).enter
25
+ .append("rect")
26
+ .attr("x"){|d| 0 }
27
+ .attr("y"){|d| y.(d.year) }
28
+ .attr("width"){|d| x.(d.horse_time) }
29
+ .attr("height"){|d,i| 0.35 * (y.(i+1) - y.(i)) }
30
+ .attr("fill"){|d| c.("horse") }
31
+
32
+ graph_area.append("g")
33
+ .select_all("rect")
34
+ .data(ManVsHorse).enter
35
+ .append("rect")
36
+ .attr("x"){|d| 0 }
37
+ .attr("y"){|d| y.(d.year+0.45) }
38
+ .attr("width"){|d| x.(d.human_time) }
39
+ .attr("height"){|d,i| 0.35 * (y.(i+1) - y.(i)) }
40
+ .attr("fill"){|d| c.("man") }
41
+
42
+ svg.append("g")
43
+ .attr("transform", "translate(0, 20)")
44
+ .select_all("text")
45
+ .data(ManVsHorse).enter
46
+ .append("text")
47
+ .attr("x"){|d| 0 }
48
+ .attr("y"){|d| y.(d.year+0.5) }
49
+ .text{|d| (d.winner == "Horse" ? "🐎" : "🏃") + " #{d.year}" }
50
+
51
+ axis_bottom = D3.axis_bottom(x)
52
+ .tick_format{|v| h = (v / 60).floor; m = (v % 60).floor; "%d:%02d" % [h,m] }
53
+ graph_area.append("g").attr("transform", "translate(0, 1160)").call(axis_bottom)
@@ -0,0 +1,49 @@
1
+ require "opal"
2
+ require "opal-d3"
3
+ require "data/mtg_modern_colors"
4
+
5
+ flex = D3.select("#visualization")
6
+ .append("div")
7
+ .style("display", "flex")
8
+ .style("flex-wrap", "wrap")
9
+
10
+ MtgModernColors.group_by(&:cmc).sort.each do |cmc, cards|
11
+ svg = flex.append("svg")
12
+ .attr("height", "200px")
13
+ .attr("width", "200px")
14
+ graph_area = svg
15
+ .append("g")
16
+ .attr("transform", "translate(100,100)")
17
+ graph_area.append("text")
18
+ .attr("text-anchor", "middle")
19
+ .attr("y", 10)
20
+ .text(cmc)
21
+ .attr("font-size", "30px")
22
+
23
+ cards.sort_by!{|c| "wubrgxm".index(c.color)}
24
+ pie = D3.pie.value(&:count).sort(nil)
25
+
26
+ pie.(cards).each do |arc_data|
27
+ arc = D3.arc
28
+ .inner_radius(40)
29
+ .outer_radius(90)
30
+ .start_angle(arc_data[:start_angle])
31
+ .end_angle(arc_data[:end_angle])
32
+
33
+ color = {
34
+ w: "white",
35
+ u: "blue",
36
+ b: "black",
37
+ r: "red",
38
+ g: "green",
39
+ x: "grey",
40
+ m: "yellow",
41
+ }[arc_data[:data].color]
42
+
43
+ graph_area.append("path")
44
+ .attr("d", arc.())
45
+ .attr("fill", color)
46
+ .attr("stroke", "black")
47
+ .attr("stroke-width", "1px")
48
+ end
49
+ end
@@ -0,0 +1,63 @@
1
+ require "opal"
2
+ require "opal-d3"
3
+ require "data/mtg_modern_creatures"
4
+
5
+ svg = D3.select("#visualization")
6
+ .append("svg")
7
+ .attr("height", "600px")
8
+ .attr("width", "600px")
9
+
10
+ # Use one scale not two so it's a square
11
+ min, max = MtgModernCreatures.flat_map{|c| [c.power, c.toughness]}.minmax
12
+
13
+ pt = D3.scale_linear.domain([min-1, max+1]).range([0, 580])
14
+ box_size = pt.(1) - pt.(0)
15
+ c = D3.scale_log
16
+ .domain([1, MtgModernCreatures.map(&:count).max])
17
+ .range(["rgb(128, 255, 128)", "rgb(128, 128, 255)"])
18
+
19
+ graph_area = svg.append("g").attr("transform", "translate(0,0)")
20
+
21
+ MtgModernCreatures.each do |cards|
22
+ graph_area.append("rect")
23
+ .attr("x", pt.(cards.toughness))
24
+ .attr("y", pt.(cards.power))
25
+ .attr("height", box_size)
26
+ .attr("width", box_size)
27
+ .attr("fill", c.(cards.count))
28
+ graph_area.append("text")
29
+ .attr("x", pt.(cards.toughness) + box_size/2)
30
+ .attr("y", pt.(cards.power) + box_size/2 + 5)
31
+ .attr("text-anchor", "middle")
32
+ .text(cards.count)
33
+ end
34
+
35
+ (min..max).each do |v|
36
+ graph_area.append("text")
37
+ .attr("x", pt.(v) + box_size/2)
38
+ .attr("y", pt.(min-1) + box_size/2 + 5)
39
+ .attr("text-anchor", "middle")
40
+ .text(v)
41
+
42
+ graph_area.append("text")
43
+ .attr("y", pt.(v) + box_size/2 + 5)
44
+ .attr("x", pt.(min-1) + box_size/2)
45
+ .attr("text-anchor", "middle")
46
+ .text(v)
47
+ end
48
+
49
+ (min..max+1).each do |v|
50
+ graph_area.append("line")
51
+ .attr("x1", pt.(min))
52
+ .attr("x2", pt.(max+1))
53
+ .attr("y1", pt.(v))
54
+ .attr("y2", pt.(v))
55
+ .attr("stroke", "black")
56
+
57
+ graph_area.append("line")
58
+ .attr("y1", pt.(min))
59
+ .attr("y2", pt.(max+1))
60
+ .attr("x1", pt.(v))
61
+ .attr("x2", pt.(v))
62
+ .attr("stroke", "black")
63
+ end
@@ -0,0 +1,54 @@
1
+ require "opal"
2
+ require "opal-d3"
3
+ require "data/olympics_2016_medals"
4
+
5
+ height = Olympics2016Medals.size * 24
6
+ svg = D3.select("#visualization")
7
+ .append("svg")
8
+ .attr("height", "#{height}px")
9
+ .attr("width", "100%")
10
+
11
+ width = svg.style("width").to_i
12
+ max_medals = Olympics2016Medals.map(&:total).max
13
+
14
+ x = D3.scale_linear.domain([0, max_medals]).range([0, width-50])
15
+ y = D3.scale_linear.domain([0, Olympics2016Medals.size]).range([0, height])
16
+
17
+ svg.append("g").attr("transform", "translate(50, 0)")
18
+ .select_all("rect")
19
+ .data(Olympics2016Medals)
20
+ .enter.append("rect")
21
+ .attr("height", 20)
22
+ .attr("width"){|d| x.(d.gold)}
23
+ .attr("x", 0)
24
+ .attr("y"){|d,i| y.(i)}
25
+ .attr("fill", "gold")
26
+
27
+ svg.append("g").attr("transform", "translate(50, 0)")
28
+ .select_all("rect")
29
+ .data(Olympics2016Medals)
30
+ .enter.append("rect")
31
+ .attr("height", 20)
32
+ .attr("width"){|d| x.(d.silver)}
33
+ .attr("x"){|d| x.(d.gold) }
34
+ .attr("y"){|d,i| y.(i)}
35
+ .attr("fill", "silver")
36
+
37
+ svg.append("g").attr("transform", "translate(50, 0)")
38
+ .select_all("rect")
39
+ .data(Olympics2016Medals)
40
+ .enter.append("rect")
41
+ .attr("height", 20)
42
+ .attr("width"){|d| x.(d.bronze)}
43
+ .attr("x"){|d| x.(d.gold + d.silver) }
44
+ .attr("y"){|d,i| y.(i)}
45
+ .attr("fill", "#CD7F32")
46
+
47
+ svg.append("g")
48
+ .select_all("text")
49
+ .data(Olympics2016Medals)
50
+ .enter.append("text")
51
+ .attr("x", 0)
52
+ .attr("y"){|d,i| y.(i) + 16}
53
+ .text{|d| d.acronym}
54
+ .style("font-size", "20px")
@@ -0,0 +1,57 @@
1
+ require "opal"
2
+ require "opal-d3"
3
+ require "data/paradox"
4
+
5
+ svg = D3.select("#visualization")
6
+ .append("svg")
7
+ .attr("height", "600px")
8
+ .attr("width", "100%")
9
+ width = svg.style("width").to_i
10
+
11
+ min_date, max_date = ParadoxGames.map(&:time).minmax
12
+ count = ParadoxGames.map{|g| [g.series, g.number]}.uniq.size
13
+ bar_height = 580 / count
14
+
15
+ x = D3.scale_linear.domain([min_date, max_date]).range([0,width-220])
16
+ y = D3.scale_ordinal.range(count.times.map{|x| bar_height * x})
17
+ c = D3.scale_ordinal.range(D3.scheme_category_10)
18
+ stripes = D3.scale_ordinal.range([0,1])
19
+
20
+ graph_area = svg.append("g")
21
+ .attr("transform", "translate(200, 20)")
22
+
23
+ ParadoxGames.each do |game|
24
+ dlc = (game.dlc != "")
25
+ full_game = "#{game.series} #{game.number}"
26
+
27
+ graph_area.append("circle")
28
+ .attr("cx", x.(game.time))
29
+ .attr("cy", y.(full_game))
30
+ .attr("r", dlc ? 8 : 12)
31
+ .attr("fill", c.("#{game.series}"))
32
+ .attr("opacity", 0.6)
33
+ .attr("stroke-width", "1px")
34
+ .attr("stroke", "black")
35
+
36
+ unless dlc
37
+ graph_area.append("text")
38
+ .attr("x", -200 + 5)
39
+ .attr("y", y.(full_game) + 4)
40
+ .text(full_game)
41
+
42
+ color = D3.color(c.("#{game.series}"))
43
+ color = color.brighter(stripes.("#{full_game}"))
44
+ graph_area.append("rect")
45
+ .attr("x", -200)
46
+ .attr("width", width)
47
+ .attr("y", y.(full_game) - bar_height/2)
48
+ .attr("height", bar_height)
49
+ .attr("fill", color)
50
+ .attr("opacity", 0.2)
51
+ end
52
+ end
53
+
54
+
55
+ axis_bottom = D3.axis_bottom(x)
56
+ .tick_format(D3.time_format("%B %Y"))
57
+ graph_area.append("g").attr("transform", "translate(0, 560)").call(axis_bottom)
@@ -0,0 +1,53 @@
1
+ require "opal"
2
+ require "opal-d3"
3
+ require "data/polish_pms"
4
+
5
+ svg = D3.select("#visualization")
6
+ .append("svg")
7
+ .attr("height", "600px")
8
+ .attr("width", "100%")
9
+ width = svg.style("width").to_i
10
+
11
+ min_date = PolishPMs.map(&:start).min
12
+ max_date = PolishPMs.map(&:end).max
13
+
14
+ x = D3.scale_linear.domain([min_date, max_date]).range([100,width-90])
15
+ y = D3.scale_linear.domain([0, PolishPMs.size+1]).range([0, 580])
16
+ c = D3.scale_ordinal.range(D3.scheme_category_20)
17
+
18
+ graph_area = svg.append("g")
19
+ .attr("transform", "translate(60, 20)")
20
+
21
+ graph_area.append("g")
22
+ .select_all("rect")
23
+ .data(PolishPMs).enter
24
+ .append("rect")
25
+ .attr("x"){|d| x.(d.start) }
26
+ .attr("y"){|d,i| y.(i) }
27
+ .attr("width"){|d| x.(d.end) - x.(d.start) }
28
+ .attr("height"){|d,i| 0.8 * (y.(i+1) - y.(i)) }
29
+ .attr("fill"){|d| c.(d.party)}
30
+
31
+ graph_area.append("g")
32
+ .select_all("text")
33
+ .data(PolishPMs).enter
34
+ .append("text")
35
+ .text{|d| d.name}
36
+ .attr("x"){|d| x.(d.start) - 4 }
37
+ .attr("y"){|d,i| y.(i+0.5) }
38
+ .attr("text-anchor", "end")
39
+ .style("font-size", "12px")
40
+
41
+ graph_area.append("g")
42
+ .select_all("text")
43
+ .data(PolishPMs).enter
44
+ .append("text")
45
+ .text{|d| d.party }
46
+ .attr("x"){|d| x.(d.start) + 4 }
47
+ .attr("y"){|d,i| y.(i+0.5) }
48
+ .attr("text-anchor", "begin")
49
+ .style("font-size", "12px")
50
+
51
+ axis_bottom = D3.axis_bottom(x)
52
+ .tick_format(D3.time_format("%B %Y"))
53
+ graph_area.append("g").attr("transform", "translate(0, 560)").call(axis_bottom)
@@ -0,0 +1,39 @@
1
+ require "opal"
2
+ require "opal-d3"
3
+ require "data/star_trek_voyager"
4
+
5
+ svg = D3.select("#visualization")
6
+ .append("svg")
7
+ .attr("height", "600px")
8
+ .attr("width", "100%")
9
+ width = svg.style("width").to_i
10
+
11
+ x = D3.scale_linear.domain([0, StarTrekVoyager.size-1]).range([40, width-20])
12
+ y = D3.scale_linear.domain(StarTrekVoyager.map(&:rating).minmax).range([550, 50])
13
+ c = D3.scale_ordinal.range(D3.scheme_category_10)
14
+
15
+ (1..7).each do |season|
16
+ episodes = StarTrekVoyager.select{|episode| episode.season == season }
17
+ avg = D3.mean(episodes.map(&:rating))
18
+ svg.append("line")
19
+ .attr("x1", x.(episodes.map(&:number).min))
20
+ .attr("x2", x.(episodes.map(&:number).max))
21
+ .attr("y1", y.(avg))
22
+ .attr("y2", y.(avg))
23
+ .attr("stroke", c.(season))
24
+ .attr("stroke-width", 2)
25
+ .attr("opacity", 0.4)
26
+ end
27
+
28
+ StarTrekVoyager.each do |episode|
29
+ svg.append("circle")
30
+ .attr("cx", x.(episode.number))
31
+ .attr("cy", y.(episode.rating))
32
+ .attr("r", 4)
33
+ .attr("fill", c.(episode.season))
34
+ .attr("opacity", 0.6)
35
+ end
36
+
37
+ axis = D3.axis_left(y)
38
+ svg.append("g").attr("transform","translate(30, 0)")
39
+ .call(axis)
@@ -0,0 +1,62 @@
1
+ require "opal"
2
+ require "opal-d3"
3
+ require "data/weather_in_london"
4
+
5
+ row = D3.select("#visualization").append("div").attr("class", "row")
6
+
7
+ min_temp = WeatherInLondon.map(&:min).min
8
+ max_temp = WeatherInLondon.map(&:max).max
9
+
10
+ x = D3.scale_linear.domain([1,31]).range([30, 190])
11
+ y = D3.scale_linear.domain([min_temp, max_temp]).range([180, 20])
12
+
13
+ (1..12).each do |month|
14
+ header = D3.time_format("%B").(Time.parse("2016-#{month}-01"))
15
+ panel = row.append("div").attr("class", "col-xs-6 col-sm-4")
16
+ panel.append("h3").text(header)
17
+ svg = panel.append("svg")
18
+ .attr("height", "200px")
19
+ .attr("width", "200px")
20
+
21
+ svg.append("rect")
22
+ .attr("x", 20)
23
+ .attr("y", 10)
24
+ .attr("width", 180)
25
+ .attr("height", 180)
26
+ .attr("fill", "lightgrey")
27
+
28
+ data = WeatherInLondon.select{|row| row.month == month}
29
+
30
+ max_temp = D3.line
31
+ .x{|d| x.(d.day) }
32
+ .y{|d| y.(d.max) }
33
+ .curve(D3.curve_natural)
34
+ svg.append("path")
35
+ .attr("d", max_temp.(data))
36
+ .attr("stroke", "red")
37
+ .attr("stroke-width", "2px")
38
+ .attr("fill", "none")
39
+
40
+ mean_temp = D3.line
41
+ .x{|d| x.(d.day) }
42
+ .y{|d| y.(d.mean) }
43
+ .curve(D3.curve_natural)
44
+ svg.append("path")
45
+ .attr("d", mean_temp.(data))
46
+ .attr("stroke", "black")
47
+ .attr("stroke-width", "2px")
48
+ .attr("fill", "none")
49
+
50
+ min_temp = D3.line
51
+ .x{|d| x.(d.day) }
52
+ .y{|d| y.(d.min) }
53
+ .curve(D3.curve_natural)
54
+ svg.append("path")
55
+ .attr("d", min_temp.(data))
56
+ .attr("stroke", "blue")
57
+ .attr("stroke-width", "2px")
58
+ .attr("fill", "none")
59
+
60
+ axis_left = D3.axis_left(y).tick_size(2)
61
+ svg.append("g").attr("transform", "translate(20,0)").call(axis_left)
62
+ end