hyper-d3 1.0.0.lap23
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +313 -0
- data/README.md +118 -0
- data/Rakefile +31 -0
- data/hyper-d3.gemspec +27 -0
- data/lib/d3.rb +68 -0
- data/lib/d3/arc.rb +29 -0
- data/lib/d3/area.rb +53 -0
- data/lib/d3/axis.rb +79 -0
- data/lib/d3/band_scale.rb +30 -0
- data/lib/d3/collections.rb +9 -0
- data/lib/d3/color.rb +76 -0
- data/lib/d3/color_schemes.rb +34 -0
- data/lib/d3/continuous_scale.rb +60 -0
- data/lib/d3/creator.rb +11 -0
- data/lib/d3/curve.rb +74 -0
- data/lib/d3/dsv.rb +103 -0
- data/lib/d3/ease.rb +319 -0
- data/lib/d3/format.rb +95 -0
- data/lib/d3/histograms.rb +46 -0
- data/lib/d3/interpolate.rb +125 -0
- data/lib/d3/line.rb +27 -0
- data/lib/d3/map.rb +48 -0
- data/lib/d3/misc.rb +15 -0
- data/lib/d3/native.rb +112 -0
- data/lib/d3/nest.rb +100 -0
- data/lib/d3/ordinal_scale.rb +39 -0
- data/lib/d3/path.rb +24 -0
- data/lib/d3/pie.rb +25 -0
- data/lib/d3/point_scale.rb +27 -0
- data/lib/d3/polygon.rb +18 -0
- data/lib/d3/quadtree.rb +89 -0
- data/lib/d3/quantile_scale.rb +19 -0
- data/lib/d3/quantize_scale.rb +20 -0
- data/lib/d3/radial_area.rb +55 -0
- data/lib/d3/radial_line.rb +27 -0
- data/lib/d3/random.rb +14 -0
- data/lib/d3/search.rb +30 -0
- data/lib/d3/selection.rb +151 -0
- data/lib/d3/sequential_scale.rb +31 -0
- data/lib/d3/set.rb +30 -0
- data/lib/d3/source/d3-drag.js +234 -0
- data/lib/d3/source/d3-scale-chromatic.js +484 -0
- data/lib/d3/source/d3.js +17178 -0
- data/lib/d3/stack.rb +13 -0
- data/lib/d3/statistics.rb +81 -0
- data/lib/d3/symbol.rb +70 -0
- data/lib/d3/threshold_scale.rb +22 -0
- data/lib/d3/time_format.rb +47 -0
- data/lib/d3/time_interval.rb +85 -0
- data/lib/d3/transformations.rb +16 -0
- data/lib/hyper-d3.rb +17 -0
- data/lib/hyperloop/d3/component.rb +12 -0
- data/lib/hyperloop/d3/mixin.rb +59 -0
- data/lib/hyperloop/d3/version.rb +5 -0
- data/spec/arc_spec.rb +80 -0
- data/spec/area_spec.rb +98 -0
- data/spec/axis_spec.rb +174 -0
- data/spec/band_scale_spec.rb +73 -0
- data/spec/color_spec.rb +74 -0
- data/spec/continuous_scale_spec.rb +217 -0
- data/spec/coverage_spec.rb +16 -0
- data/spec/creator_spec.rb +15 -0
- data/spec/curve_spec.rb +206 -0
- data/spec/dsv_spec.rb +194 -0
- data/spec/ease_spec.rb +370 -0
- data/spec/format_spec.rb +87 -0
- data/spec/histograms_spec.rb +61 -0
- data/spec/html/index.html.erb +11 -0
- data/spec/interpolate_spec.rb +152 -0
- data/spec/line_spec.rb +54 -0
- data/spec/map_spec.rb +80 -0
- data/spec/misc_spec.rb +21 -0
- data/spec/nest_spec.rb +89 -0
- data/spec/objects_spec.rb +22 -0
- data/spec/ordinal_scale_spec.rb +59 -0
- data/spec/path_spec.rb +65 -0
- data/spec/pie_spec.rb +114 -0
- data/spec/point_scale_spec.rb +58 -0
- data/spec/polygon_spec.rb +51 -0
- data/spec/quadtree_spec.rb +128 -0
- data/spec/quantile_scale_spec.rb +24 -0
- data/spec/quantize_scale_spec.rb +40 -0
- data/spec/radial_area_spec.rb +123 -0
- data/spec/radial_line_spec.rb +50 -0
- data/spec/random_spec.rb +34 -0
- data/spec/search_spec.rb +69 -0
- data/spec/selection_data_spec.rb +64 -0
- data/spec/selection_manipulation_spec.rb +166 -0
- data/spec/selection_spec.rb +187 -0
- data/spec/sequential_scale_spec.rb +90 -0
- data/spec/set_spec.rb +57 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/stack_spec.rb +5 -0
- data/spec/statistics_spec.rb +65 -0
- data/spec/symbol_spec.rb +116 -0
- data/spec/test_app/.gitignore +23 -0
- data/spec/test_app/Gemfile +7 -0
- data/spec/test_app/Gemfile.lock +206 -0
- data/spec/test_app/README.md +9 -0
- data/spec/test_app/Rakefile +6 -0
- data/spec/test_app/app/assets/config/manifest.js +3 -0
- data/spec/test_app/app/assets/images/.keep +0 -0
- data/spec/test_app/app/assets/javascripts/application.js +13 -0
- data/spec/test_app/app/assets/javascripts/cable.js +13 -0
- data/spec/test_app/app/assets/javascripts/channels/.keep +0 -0
- data/spec/test_app/app/assets/javascripts/data/elections_2016.rb +10 -0
- data/spec/test_app/app/assets/javascripts/data/harry_potter.rb +19 -0
- data/spec/test_app/app/assets/javascripts/data/iphones.rb +29 -0
- data/spec/test_app/app/assets/javascripts/data/london_population.rb +26 -0
- data/spec/test_app/app/assets/javascripts/data/man_vs_horse.rb +55 -0
- data/spec/test_app/app/assets/javascripts/data/mtg_modern_colors.rb +96 -0
- data/spec/test_app/app/assets/javascripts/data/mtg_modern_creatures.rb +116 -0
- data/spec/test_app/app/assets/javascripts/data/olympics_2016_medals.rb +100 -0
- data/spec/test_app/app/assets/javascripts/data/paradox.rb +60 -0
- data/spec/test_app/app/assets/javascripts/data/polish_pms.rb +28 -0
- data/spec/test_app/app/assets/javascripts/data/star_trek_voyager.rb +183 -0
- data/spec/test_app/app/assets/javascripts/data/weather_in_london.rb +381 -0
- data/spec/test_app/app/assets/javascripts/elections_2016.rb +27 -0
- data/spec/test_app/app/assets/javascripts/harry_potter.rb +42 -0
- data/spec/test_app/app/assets/javascripts/iphones.rb +54 -0
- data/spec/test_app/app/assets/javascripts/london_population.rb +53 -0
- data/spec/test_app/app/assets/javascripts/london_population_area.rb +49 -0
- data/spec/test_app/app/assets/javascripts/man_vs_horse.rb +60 -0
- data/spec/test_app/app/assets/javascripts/mtg_modern_colors.rb +56 -0
- data/spec/test_app/app/assets/javascripts/mtg_modern_creatures.rb +70 -0
- data/spec/test_app/app/assets/javascripts/olympics_2016_medals.rb +62 -0
- data/spec/test_app/app/assets/javascripts/paradox.rb +64 -0
- data/spec/test_app/app/assets/javascripts/polish_pms.rb +60 -0
- data/spec/test_app/app/assets/javascripts/star_trek_voyager.rb +44 -0
- data/spec/test_app/app/assets/javascripts/weather_in_london.rb +69 -0
- data/spec/test_app/app/assets/stylesheets/application.css +15 -0
- data/spec/test_app/app/channels/application_cable/channel.rb +4 -0
- data/spec/test_app/app/channels/application_cable/connection.rb +4 -0
- data/spec/test_app/app/controllers/application_controller.rb +27 -0
- data/spec/test_app/app/controllers/concerns/.keep +0 -0
- data/spec/test_app/app/helpers/application_helper.rb +2 -0
- data/spec/test_app/app/jobs/application_job.rb +2 -0
- data/spec/test_app/app/mailers/application_mailer.rb +4 -0
- data/spec/test_app/app/models/application_record.rb +3 -0
- data/spec/test_app/app/models/concerns/.keep +0 -0
- data/spec/test_app/app/views/application/index.erb +18 -0
- data/spec/test_app/app/views/application/visualization.erb +28 -0
- data/spec/test_app/app/views/layouts/application.html.erb +13 -0
- data/spec/test_app/bin/bundle +3 -0
- data/spec/test_app/bin/rails +4 -0
- data/spec/test_app/bin/rake +4 -0
- data/spec/test_app/bin/setup +38 -0
- data/spec/test_app/bin/update +29 -0
- data/spec/test_app/bin/yarn +11 -0
- data/spec/test_app/config.ru +5 -0
- data/spec/test_app/config/application.rb +18 -0
- data/spec/test_app/config/boot.rb +3 -0
- data/spec/test_app/config/cable.yml +10 -0
- data/spec/test_app/config/database.yml +25 -0
- data/spec/test_app/config/environment.rb +5 -0
- data/spec/test_app/config/environments/development.rb +54 -0
- data/spec/test_app/config/environments/production.rb +91 -0
- data/spec/test_app/config/environments/test.rb +42 -0
- data/spec/test_app/config/initializers/application_controller_renderer.rb +8 -0
- data/spec/test_app/config/initializers/assets.rb +14 -0
- data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/test_app/config/initializers/cookies_serializer.rb +5 -0
- data/spec/test_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/test_app/config/initializers/inflections.rb +16 -0
- data/spec/test_app/config/initializers/mime_types.rb +4 -0
- data/spec/test_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/test_app/config/locales/en.yml +33 -0
- data/spec/test_app/config/puma.rb +56 -0
- data/spec/test_app/config/routes.rb +5 -0
- data/spec/test_app/config/secrets.yml +32 -0
- data/spec/test_app/config/spring.rb +6 -0
- data/spec/test_app/db/seeds.rb +7 -0
- data/spec/test_app/lib/assets/.keep +0 -0
- data/spec/test_app/lib/tasks/.keep +0 -0
- data/spec/test_app/log/.keep +0 -0
- data/spec/test_app/package.json +5 -0
- data/spec/test_app/public/404.html +67 -0
- data/spec/test_app/public/422.html +67 -0
- data/spec/test_app/public/500.html +66 -0
- data/spec/test_app/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/test_app/public/apple-touch-icon.png +0 -0
- data/spec/test_app/public/favicon.ico +0 -0
- data/spec/test_app/public/robots.txt +1 -0
- data/spec/test_app/test/application_system_test_case.rb +5 -0
- data/spec/test_app/test/controllers/.keep +0 -0
- data/spec/test_app/test/fixtures/.keep +0 -0
- data/spec/test_app/test/fixtures/files/.keep +0 -0
- data/spec/test_app/test/helpers/.keep +0 -0
- data/spec/test_app/test/integration/.keep +0 -0
- data/spec/test_app/test/mailers/.keep +0 -0
- data/spec/test_app/test/models/.keep +0 -0
- data/spec/test_app/test/system/.keep +0 -0
- data/spec/test_app/test/test_helper.rb +10 -0
- data/spec/test_app/tmp/.keep +0 -0
- data/spec/test_app/vendor/.keep +0 -0
- data/spec/threshold_scale_spec.rb +28 -0
- data/spec/time_format_spec.rb +100 -0
- data/spec/time_interval_spec.rb +314 -0
- data/spec/transformations_spec.rb +51 -0
- data/startrekvoyager.png +0 -0
- metadata +529 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
require "react/test/utils" # just for mounting manually here, please ignore
|
2
|
+
require "data/elections_2016"
|
3
|
+
|
4
|
+
class ElectionComponent
|
5
|
+
include Hyperloop::D3::Mixin
|
6
|
+
|
7
|
+
render_with_selection('DIV') do |selection, election_data|
|
8
|
+
list = selection.append("ul")
|
9
|
+
max_votes = election_data.map(&:votes).max
|
10
|
+
|
11
|
+
election_data.each do |candidate|
|
12
|
+
item = list.append("li")
|
13
|
+
.style("position", "relative")
|
14
|
+
item.append("span")
|
15
|
+
.style("background-color", candidate.color)
|
16
|
+
.style("position", "absolute")
|
17
|
+
.style("width", "#{100.0 * candidate.votes / max_votes}%")
|
18
|
+
.style("height", "100%")
|
19
|
+
item.append("span")
|
20
|
+
.style("position", "absolute")
|
21
|
+
.text("#{candidate.name} - #{candidate.votes} votes")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# manual mount of component, usually you would use the react_component view helper for example
|
27
|
+
React.render(React.create_element(ElectionComponent, data: Elections2016), `document.body.querySelector("#visualization")`)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "react/test/utils" # just for mounting manually here, please ignore
|
2
|
+
require "data/harry_potter"
|
3
|
+
|
4
|
+
class HarryPotterComponent
|
5
|
+
include Hyperloop::D3::Mixin
|
6
|
+
|
7
|
+
render_with_selection do |selection, hp_data|
|
8
|
+
svg = selection
|
9
|
+
.attr("height", "400px")
|
10
|
+
.attr("width", "100%")
|
11
|
+
width = svg.style("width").to_i
|
12
|
+
|
13
|
+
bar_size = (400-40-20) / (hp_data.size)
|
14
|
+
|
15
|
+
x = D3.scale_linear.domain(hp_data.map(&:date).minmax).range([200,width-90])
|
16
|
+
y = D3.scale_ordinal.range(hp_data.size.times.map{|i| 40+i*bar_size}.reverse)
|
17
|
+
s = D3.scale_sqrt.domain([0, hp_data.map(&:pages).max]).range([0,50])
|
18
|
+
|
19
|
+
hp_data.each do |book|
|
20
|
+
svg.append("text")
|
21
|
+
.attr("x", x.(book.date))
|
22
|
+
.attr("y", y.(book.title) + bar_size/2)
|
23
|
+
.attr("font-size", s.(book.pages))
|
24
|
+
.text("📖")
|
25
|
+
.attr("text-anchor", "middle")
|
26
|
+
svg.append("text")
|
27
|
+
.attr("x", 0)
|
28
|
+
.attr("y", y.(book.title) + bar_size/2)
|
29
|
+
.text(book.title)
|
30
|
+
end
|
31
|
+
|
32
|
+
axis_bottom = D3.axis_bottom(x)
|
33
|
+
.tick_format(D3.time_format("%Y-%m-%d"))
|
34
|
+
.tick_values(hp_data.map(&:date))
|
35
|
+
svg.append("g")
|
36
|
+
.attr("transform", "translate(0, 380)")
|
37
|
+
.call(axis_bottom)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# manual mount of component, usually you would use the react_component view helper for example
|
42
|
+
React.render(React.create_element(HarryPotterComponent, data: HarryPotterBooks), `document.body.querySelector("#visualization")`)
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "react/test/utils" # just for mounting manually here, please ignore
|
2
|
+
require "data/iphones"
|
3
|
+
|
4
|
+
class IPhonesComponent
|
5
|
+
include Hyperloop::D3::Mixin
|
6
|
+
|
7
|
+
render_with_selection do |selection, i_data|
|
8
|
+
svg = selection
|
9
|
+
.attr("height", "500px")
|
10
|
+
.attr("width", "100%")
|
11
|
+
width = svg.style("width").to_i
|
12
|
+
|
13
|
+
x = D3.scale_linear.domain(i_data.map(&:released).minmax).range([20,width-90]).nice
|
14
|
+
y = D3.scale_log.domain(i_data.map(&:size).minmax).range([380,20])
|
15
|
+
c = D3.scale_ordinal.range(D3.scheme_category_20)
|
16
|
+
|
17
|
+
# If there are multiple points on same date/size combination,
|
18
|
+
# move any duplicates 15px right (or 30px for triplicates etc.)
|
19
|
+
duplicates = Hash.new(0)
|
20
|
+
|
21
|
+
graph_area = svg.append("g")
|
22
|
+
.attr("transform", "translate(60, 20)")
|
23
|
+
graph_area.select_all("circle")
|
24
|
+
.data(i_data).enter
|
25
|
+
.append("circle")
|
26
|
+
.attr("cx"){|d|
|
27
|
+
count = duplicates[[d.released, d.size]]
|
28
|
+
duplicates[[d.released, d.size]] += 1
|
29
|
+
x.(d.released) + 15 * count
|
30
|
+
}
|
31
|
+
.attr("cy"){|d| y.(d.size)}
|
32
|
+
.attr("r", 10)
|
33
|
+
.attr("fill"){|d| c.(d.name)}
|
34
|
+
|
35
|
+
axis_bottom = D3.axis_bottom(x)
|
36
|
+
.tick_format(D3.time_format("%Y-%m-%d"))
|
37
|
+
axis_left = D3.axis_left(y)
|
38
|
+
.tick_values([4,8,16,32,64,128,256])
|
39
|
+
.tick_format{|v| "#{v} GB"}
|
40
|
+
graph_area.call(axis_left)
|
41
|
+
graph_area.append("g").attr("transform", "translate(0, 400)").call(axis_bottom)
|
42
|
+
|
43
|
+
D3.select("#visualization").append("table")
|
44
|
+
.select_all("tr")
|
45
|
+
.data(IPhones).enter
|
46
|
+
.append("tr")
|
47
|
+
.append("td")
|
48
|
+
.text{|d| d.name}
|
49
|
+
.style("background"){|d| c.(d.name)}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# manual mount of component, usually you would use the react_component view helper for example
|
54
|
+
React.render(React.create_element(IPhonesComponent, data: IPhoneVariants), `document.body.querySelector("#visualization")`)
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "react/test/utils" # just for mounting manually here, please ignore
|
2
|
+
require "data/london_population"
|
3
|
+
|
4
|
+
class LondonPopComponent
|
5
|
+
include Hyperloop::D3::Mixin
|
6
|
+
|
7
|
+
render_with_selection do |selection, lp_data|
|
8
|
+
svg = selection
|
9
|
+
.attr("height", "400px")
|
10
|
+
.attr("width", "100%")
|
11
|
+
|
12
|
+
svg.append("g").select_all("rect")
|
13
|
+
.data(lp_data)
|
14
|
+
.enter().append("rect")
|
15
|
+
.attr("width", 30)
|
16
|
+
.attr("height"){|d| d.greater/100_000 }
|
17
|
+
.attr("y"){|d| 200 - d.greater/100_000 }
|
18
|
+
.attr("x"){|d| (d.year-1800)*4 }
|
19
|
+
.attr("fill", "pink")
|
20
|
+
|
21
|
+
svg.append("g").select_all("rect")
|
22
|
+
.data(lp_data)
|
23
|
+
.enter().append("rect")
|
24
|
+
.attr("width", 30)
|
25
|
+
.attr("height"){|d| d.inner/100_000 }
|
26
|
+
.attr("y"){|d| 200 - d.inner/100_000 }
|
27
|
+
.attr("x"){|d| (d.year-1800)*4 }
|
28
|
+
.attr("fill", "steelblue")
|
29
|
+
|
30
|
+
svg.append("g").select_all("circle")
|
31
|
+
.data(lp_data)
|
32
|
+
.enter().append("circle")
|
33
|
+
.attr("fill", "pink")
|
34
|
+
.attr("cx"){|d| 15 + (d.year-1800)*4 }
|
35
|
+
.attr("cy", 300)
|
36
|
+
.attr("r"){|d| (d.greater**0.5)/150.0 }
|
37
|
+
|
38
|
+
svg.append("g").select_all("circle")
|
39
|
+
.data(lp_data)
|
40
|
+
.enter().append("circle")
|
41
|
+
.attr("fill", "steelblue")
|
42
|
+
.attr("cx"){|d| 15 + (d.year-1800)*4 }
|
43
|
+
.attr("cy", 300)
|
44
|
+
.attr("r"){|d| (d.inner**0.5)/150.0 }
|
45
|
+
|
46
|
+
list = D3.select("#visualization").append("table")
|
47
|
+
list.append("tr").append("td").text("Outer London").style("background", "pink")
|
48
|
+
list.append("tr").append("td").text("Inner London").style("background", "steelblue")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# manual mount of component, usually you would use the react_component view helper for example
|
53
|
+
React.render(React.create_element(LondonPopComponent, data: LondonPopulation), `document.body.querySelector("#visualization")`)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "react/test/utils" # just for mounting manually here, please ignore
|
2
|
+
require "data/london_population"
|
3
|
+
|
4
|
+
class LondonPopAreaComponent
|
5
|
+
include Hyperloop::D3::Mixin
|
6
|
+
|
7
|
+
render_with_selection do |selection, lp_data|
|
8
|
+
svg = selection
|
9
|
+
.attr("height", "500px")
|
10
|
+
.attr("width", "100%")
|
11
|
+
width = svg.style("width").to_i
|
12
|
+
|
13
|
+
x = D3.scale_linear.domain([1801, 2011]).range([0, width-60])
|
14
|
+
y = D3.scale_linear.domain([0, 9_000_000]).range([400, 0])
|
15
|
+
|
16
|
+
greater_area = D3.area
|
17
|
+
.x{|d| x.(d.year) }
|
18
|
+
.y0(400)
|
19
|
+
.y1{|d| y.(d.greater)}
|
20
|
+
.curve(D3.curve_natural)
|
21
|
+
|
22
|
+
inner_area = D3.area
|
23
|
+
.x{|d| x.(d.year) }
|
24
|
+
.y0(400)
|
25
|
+
.y1{|d| y.(d.inner)}
|
26
|
+
.curve(D3.curve_natural)
|
27
|
+
|
28
|
+
graph_area = svg.append("g")
|
29
|
+
.attr("transform", "translate(60, 20)")
|
30
|
+
graph_area.append("path")
|
31
|
+
.attr("d", greater_area.(lp_data))
|
32
|
+
.attr("fill", "pink")
|
33
|
+
graph_area.append("path")
|
34
|
+
.attr("d", inner_area.(lp_data))
|
35
|
+
.attr("fill", "steelblue")
|
36
|
+
|
37
|
+
axis_bottom = D3.axis_bottom(x).tick_format(D3.format("d"))
|
38
|
+
axis_left = D3.axis_left(y).tick_format{|d| "#{d/1_000_000}M"}
|
39
|
+
graph_area.call(axis_left)
|
40
|
+
graph_area.append("g").attr("transform", "translate(0, 400)").call(axis_bottom)
|
41
|
+
|
42
|
+
list = D3.select("#visualization").append("table")
|
43
|
+
list.append("tr").append("td").text("Outer London").style("background", "pink")
|
44
|
+
list.append("tr").append("td").text("Inner London").style("background", "steelblue")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# manual mount of component, usually you would use the react_component view helper for example
|
49
|
+
React.render(React.create_element(LondonPopAreaComponent, data: LondonPopulation), `document.body.querySelector("#visualization")`)
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "react/test/utils" # just for mounting manually here, please ignore
|
2
|
+
require "data/man_vs_horse"
|
3
|
+
|
4
|
+
class ManHorseComponent
|
5
|
+
include Hyperloop::D3::Mixin
|
6
|
+
|
7
|
+
render_with_selection do |selection, mh_data|
|
8
|
+
svg = selection
|
9
|
+
.attr("height", "1200px")
|
10
|
+
.attr("width", "100%")
|
11
|
+
width = svg.style("width").to_i
|
12
|
+
|
13
|
+
max_time = mh_data.flat_map{|d| [d.horse_time, d.human_time]}.max
|
14
|
+
min_year = mh_data.map(&:year).min
|
15
|
+
max_year = mh_data.map(&:year).max
|
16
|
+
|
17
|
+
x = D3.scale_linear.domain([0, max_time]).range([0,width-90]).nice
|
18
|
+
y = D3.scale_linear.domain([min_year, max_year+1]).range([0, 1160])
|
19
|
+
c = D3.scale_ordinal.range(D3.scheme_category_10)
|
20
|
+
|
21
|
+
graph_area = svg.append("g")
|
22
|
+
.attr("transform", "translate(60, 20)")
|
23
|
+
|
24
|
+
graph_area.append("g")
|
25
|
+
.select_all("rect")
|
26
|
+
.data(mh_data).enter
|
27
|
+
.append("rect")
|
28
|
+
.attr("x"){|d| 0 }
|
29
|
+
.attr("y"){|d| y.(d.year) }
|
30
|
+
.attr("width"){|d| x.(d.horse_time) }
|
31
|
+
.attr("height"){|d,i| 0.35 * (y.(i+1) - y.(i)) }
|
32
|
+
.attr("fill"){|d| c.("horse") }
|
33
|
+
|
34
|
+
graph_area.append("g")
|
35
|
+
.select_all("rect")
|
36
|
+
.data(mh_data).enter
|
37
|
+
.append("rect")
|
38
|
+
.attr("x"){|d| 0 }
|
39
|
+
.attr("y"){|d| y.(d.year+0.45) }
|
40
|
+
.attr("width"){|d| x.(d.human_time) }
|
41
|
+
.attr("height"){|d,i| 0.35 * (y.(i+1) - y.(i)) }
|
42
|
+
.attr("fill"){|d| c.("man") }
|
43
|
+
|
44
|
+
svg.append("g")
|
45
|
+
.attr("transform", "translate(0, 20)")
|
46
|
+
.select_all("text")
|
47
|
+
.data(mh_data).enter
|
48
|
+
.append("text")
|
49
|
+
.attr("x"){|d| 0 }
|
50
|
+
.attr("y"){|d| y.(d.year+0.5) }
|
51
|
+
.text{|d| (d.winner == "Horse" ? "🐎" : "🏃") + " #{d.year}" }
|
52
|
+
|
53
|
+
axis_bottom = D3.axis_bottom(x)
|
54
|
+
.tick_format{|v| h = (v / 60).floor; m = (v % 60).floor; "%d:%02d" % [h,m] }
|
55
|
+
graph_area.append("g").attr("transform", "translate(0, 1160)").call(axis_bottom)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# manual mount of component, usually you would use the react_component view helper for example
|
60
|
+
React.render(React.create_element(ManHorseComponent, data: ManVsHorse), `document.body.querySelector("#visualization")`)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "hyper-d3"
|
2
|
+
require "data/mtg_modern_colors"
|
3
|
+
|
4
|
+
class ModernColorsComponent
|
5
|
+
include Hyperloop::D3::Mixin
|
6
|
+
|
7
|
+
render_with_selection('DIV') do |selection, colors_data|
|
8
|
+
flex = selection
|
9
|
+
.style("display", "flex")
|
10
|
+
.style("flex-wrap", "wrap")
|
11
|
+
|
12
|
+
colors_data.group_by(&:cmc).sort.each do |cmc, cards|
|
13
|
+
svg = flex.append("svg")
|
14
|
+
.attr("height", "200px")
|
15
|
+
.attr("width", "200px")
|
16
|
+
graph_area = svg
|
17
|
+
.append("g")
|
18
|
+
.attr("transform", "translate(100,100)")
|
19
|
+
graph_area.append("text")
|
20
|
+
.attr("text-anchor", "middle")
|
21
|
+
.attr("y", 10)
|
22
|
+
.text(cmc)
|
23
|
+
.attr("font-size", "30px")
|
24
|
+
|
25
|
+
cards.sort_by!{|c| "wubrgxm".index(c.color)}
|
26
|
+
pie = D3.pie.value(&:count).sort(nil)
|
27
|
+
|
28
|
+
pie.(cards).each do |arc_data|
|
29
|
+
arc = D3.arc
|
30
|
+
.inner_radius(40)
|
31
|
+
.outer_radius(90)
|
32
|
+
.start_angle(arc_data[:start_angle])
|
33
|
+
.end_angle(arc_data[:end_angle])
|
34
|
+
|
35
|
+
color = {
|
36
|
+
w: "white",
|
37
|
+
u: "blue",
|
38
|
+
b: "black",
|
39
|
+
r: "red",
|
40
|
+
g: "green",
|
41
|
+
x: "grey",
|
42
|
+
m: "yellow",
|
43
|
+
}[arc_data[:data].color]
|
44
|
+
|
45
|
+
graph_area.append("path")
|
46
|
+
.attr("d", arc.())
|
47
|
+
.attr("fill", color)
|
48
|
+
.attr("stroke", "black")
|
49
|
+
.attr("stroke-width", "1px")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# manual mount of component, usually you would use the react_component view helper for example
|
56
|
+
React.render(React.create_element(ModernColorsComponent, data: MtgModernColors), `document.body.querySelector("#visualization")`)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "hyper-d3"
|
2
|
+
require "data/mtg_modern_creatures"
|
3
|
+
|
4
|
+
class ModernCreaturesComponent
|
5
|
+
include Hyperloop::D3::Mixin
|
6
|
+
|
7
|
+
render_with_selection do |selection, creatures_data|
|
8
|
+
svg = selection
|
9
|
+
.attr("height", "600px")
|
10
|
+
.attr("width", "600px")
|
11
|
+
|
12
|
+
# Use one scale not two so it's a square
|
13
|
+
min, max = creatures_data.flat_map{|c| [c.power, c.toughness]}.minmax
|
14
|
+
|
15
|
+
pt = D3.scale_linear.domain([min-1, max+1]).range([0, 580])
|
16
|
+
box_size = pt.(1) - pt.(0)
|
17
|
+
c = D3.scale_log
|
18
|
+
.domain([1, creatures_data.map(&:count).max])
|
19
|
+
.range(["rgb(128, 255, 128)", "rgb(128, 128, 255)"])
|
20
|
+
|
21
|
+
graph_area = svg.append("g").attr("transform", "translate(0,0)")
|
22
|
+
|
23
|
+
creatures_data.each do |cards|
|
24
|
+
graph_area.append("rect")
|
25
|
+
.attr("x", pt.(cards.toughness))
|
26
|
+
.attr("y", pt.(cards.power))
|
27
|
+
.attr("height", box_size)
|
28
|
+
.attr("width", box_size)
|
29
|
+
.attr("fill", c.(cards.count))
|
30
|
+
graph_area.append("text")
|
31
|
+
.attr("x", pt.(cards.toughness) + box_size/2)
|
32
|
+
.attr("y", pt.(cards.power) + box_size/2 + 5)
|
33
|
+
.attr("text-anchor", "middle")
|
34
|
+
.text(cards.count)
|
35
|
+
end
|
36
|
+
|
37
|
+
(min..max).each do |v|
|
38
|
+
graph_area.append("text")
|
39
|
+
.attr("x", pt.(v) + box_size/2)
|
40
|
+
.attr("y", pt.(min-1) + box_size/2 + 5)
|
41
|
+
.attr("text-anchor", "middle")
|
42
|
+
.text(v)
|
43
|
+
|
44
|
+
graph_area.append("text")
|
45
|
+
.attr("y", pt.(v) + box_size/2 + 5)
|
46
|
+
.attr("x", pt.(min-1) + box_size/2)
|
47
|
+
.attr("text-anchor", "middle")
|
48
|
+
.text(v)
|
49
|
+
end
|
50
|
+
|
51
|
+
(min..max+1).each do |v|
|
52
|
+
graph_area.append("line")
|
53
|
+
.attr("x1", pt.(min))
|
54
|
+
.attr("x2", pt.(max+1))
|
55
|
+
.attr("y1", pt.(v))
|
56
|
+
.attr("y2", pt.(v))
|
57
|
+
.attr("stroke", "black")
|
58
|
+
|
59
|
+
graph_area.append("line")
|
60
|
+
.attr("y1", pt.(min))
|
61
|
+
.attr("y2", pt.(max+1))
|
62
|
+
.attr("x1", pt.(v))
|
63
|
+
.attr("x2", pt.(v))
|
64
|
+
.attr("stroke", "black")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# manual mount of component, usually you would use the react_component view helper for example
|
70
|
+
React.render(React.create_element(ModernCreaturesComponent, data: MtgModernCreatures), `document.body.querySelector("#visualization")`)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "react/test/utils" # just for mounting manually here, please ignore
|
2
|
+
require "data/olympics_2016_medals"
|
3
|
+
|
4
|
+
class OlympicsMedalsComponent
|
5
|
+
include Hyperloop::D3::Mixin
|
6
|
+
|
7
|
+
render_with_selection do |selection, medals2016_data|
|
8
|
+
height = medals2016_data.size * 24
|
9
|
+
svg = selection
|
10
|
+
.attr("height", "#{height}px")
|
11
|
+
.attr("width", "100%")
|
12
|
+
|
13
|
+
width = svg.style("width").to_i
|
14
|
+
max_medals = medals2016_data.map(&:total).max
|
15
|
+
|
16
|
+
x = D3.scale_linear.domain([0, max_medals]).range([0, width-50])
|
17
|
+
y = D3.scale_linear.domain([0, medals2016_data.size]).range([0, height])
|
18
|
+
|
19
|
+
svg.append("g").attr("transform", "translate(50, 0)")
|
20
|
+
.select_all("rect")
|
21
|
+
.data(medals2016_data)
|
22
|
+
.enter.append("rect")
|
23
|
+
.attr("height", 20)
|
24
|
+
.attr("width"){|d| x.(d.gold)}
|
25
|
+
.attr("x", 0)
|
26
|
+
.attr("y"){|d,i| y.(i)}
|
27
|
+
.attr("fill", "gold")
|
28
|
+
|
29
|
+
svg.append("g").attr("transform", "translate(50, 0)")
|
30
|
+
.select_all("rect")
|
31
|
+
.data(medals2016_data)
|
32
|
+
.enter.append("rect")
|
33
|
+
.attr("height", 20)
|
34
|
+
.attr("width"){|d| x.(d.silver)}
|
35
|
+
.attr("x"){|d| x.(d.gold) }
|
36
|
+
.attr("y"){|d,i| y.(i)}
|
37
|
+
.attr("fill", "silver")
|
38
|
+
|
39
|
+
svg.append("g").attr("transform", "translate(50, 0)")
|
40
|
+
.select_all("rect")
|
41
|
+
.data(medals2016_data)
|
42
|
+
.enter.append("rect")
|
43
|
+
.attr("height", 20)
|
44
|
+
.attr("width"){|d| x.(d.bronze)}
|
45
|
+
.attr("x"){|d| x.(d.gold + d.silver) }
|
46
|
+
.attr("y"){|d,i| y.(i)}
|
47
|
+
.attr("fill", "#CD7F32")
|
48
|
+
|
49
|
+
svg.append("g")
|
50
|
+
.select_all("text")
|
51
|
+
.data(medals2016_data)
|
52
|
+
.enter.append("text")
|
53
|
+
.attr("x", 0)
|
54
|
+
.attr("y"){|d,i| y.(i) + 16}
|
55
|
+
.text{|d| d.acronym}
|
56
|
+
.style("font-size", "20px")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# manual mount of component, usually you would use the react_component view helper for example
|
61
|
+
React.render(React.create_element(OlympicsMedalsComponent, data: Olympics2016Medals), `document.body.querySelector("#visualization")`)
|
62
|
+
|