fdaudens HF Staff commited on
Commit
39f8822
·
verified ·
1 Parent(s): ea08229

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +133 -82
index.html CHANGED
@@ -21,19 +21,21 @@
21
  background-color: white;
22
  border-radius: 10px;
23
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
24
- padding: 20px;
25
  }
26
 
27
  h1 {
28
  text-align: center;
29
  color: #2c3e50;
30
  margin-bottom: 10px;
 
31
  }
32
 
33
  .subtitle {
34
  text-align: center;
35
  color: #7f8c8d;
36
  margin-bottom: 30px;
 
37
  }
38
 
39
  .controls {
@@ -42,63 +44,102 @@
42
  gap: 15px;
43
  margin-bottom: 25px;
44
  align-items: center;
45
- padding: 15px;
46
  background-color: #f8f9fa;
47
  border-radius: 8px;
 
48
  }
49
 
50
  .filter-buttons {
51
  display: flex;
52
  flex-wrap: wrap;
53
- gap: 8px;
54
  margin-right: auto;
55
  }
56
 
57
  .filter-btn {
58
- padding: 8px 12px;
59
  border: none;
60
- border-radius: 20px;
61
  cursor: pointer;
62
  font-weight: 600;
63
  transition: all 0.3s;
64
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
 
 
 
 
 
 
 
 
65
  }
66
 
67
  .filter-btn:hover {
68
- opacity: 0.8;
69
  transform: translateY(-2px);
 
70
  }
71
 
72
  .filter-btn.active {
73
  transform: scale(1.05);
74
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
75
  }
76
 
77
  .year-controls {
78
  display: flex;
79
  align-items: center;
80
- gap: 10px;
 
 
 
 
81
  }
82
 
83
  .year-slider {
84
- width: 200px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  }
86
 
87
  .play-btn {
88
  background-color: #2ecc71;
89
  color: white;
90
  border: none;
91
- padding: 8px 16px;
92
- border-radius: 4px;
93
  cursor: pointer;
94
  transition: all 0.3s;
95
  display: flex;
96
  align-items: center;
97
- gap: 5px;
 
 
98
  }
99
 
100
  .play-btn:hover {
101
  background-color: #27ae60;
 
 
102
  }
103
 
104
  .play-btn.playing {
@@ -107,36 +148,43 @@
107
 
108
  .year-display {
109
  font-weight: bold;
110
- min-width: 60px;
111
  text-align: center;
112
- font-size: 16px;
 
 
 
 
 
113
  }
114
 
115
  .chart-container {
116
  width: 100%;
117
- height: 600px;
118
  position: relative;
119
  border-radius: 8px;
120
  overflow: hidden;
121
  background-color: white;
122
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
 
123
  }
124
 
125
  .tooltip {
126
  position: absolute;
127
- padding: 12px;
128
- background: rgba(0, 0, 0, 0.85);
129
  color: white;
130
- border-radius: 5px;
131
  pointer-events: none;
132
- text-align: center;
133
  opacity: 0;
134
  transition: opacity 0.2s;
135
  font-size: 14px;
136
  z-index: 10;
137
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
138
- max-width: 220px;
139
- line-height: 1.4;
 
140
  }
141
 
142
  .tooltip:after {
@@ -147,7 +195,7 @@
147
  margin-left: -8px;
148
  border-width: 8px;
149
  border-style: solid;
150
- border-color: rgba(0, 0, 0, 0.85) transparent transparent transparent;
151
  }
152
 
153
  .loading {
@@ -175,20 +223,28 @@
175
  .axis-label {
176
  font-size: 12px;
177
  fill: #555;
178
- }
179
-
180
- .legend {
181
- font-size: 12px;
182
  }
183
 
184
  .disclaimer {
185
  text-align: center;
186
- font-size: 12px;
187
  color: #7f8c8d;
188
- margin-top: 15px;
 
 
 
 
 
 
 
189
  }
190
 
191
  @media (max-width: 768px) {
 
 
 
 
192
  .controls {
193
  flex-direction: column;
194
  align-items: stretch;
@@ -201,11 +257,24 @@
201
  }
202
 
203
  .year-controls {
204
- justify-content: center;
 
 
 
 
 
205
  }
206
 
207
  .chart-container {
208
- height: 450px;
 
 
 
 
 
 
 
 
209
  }
210
  }
211
  </style>
@@ -237,25 +306,25 @@
237
  </div>
238
 
239
  <div class="tooltip" id="tooltip"></div>
240
- <p class="disclaimer">Note: For countries missing region data in their year, we use the region from their latest available data</p>
241
  </div>
242
 
243
  <script>
244
  // Configuration
245
  const config = {
246
- margin: { top: 50, right: 40, bottom: 70, left: 80 },
247
  minBubbleSize: 3,
248
- maxBubbleSize: 40,
249
  animationDuration: 500,
250
  playInterval: 800,
251
  regions: {
252
- "Africa": { color: "#e74c3c" },
253
- "Asia": { color: "#3498db" },
254
- "Europe": { color: "#2ecc71" },
255
- "North America": { color: "#f1c40f" },
256
- "Oceania": { color: "#9b59b6" },
257
- "South America": { color: "#1abc9c" },
258
- "Antarctica": { color: "#95a5a6" }
259
  }
260
  };
261
 
@@ -393,11 +462,11 @@
393
  // Create region buttons
394
  dom.regionButtons.selectAll("*").remove();
395
 
396
- Object.entries(config.regions).forEach(([region, { color }]) => {
397
  const btn = dom.regionButtons.append("button")
398
  .attr("class", "filter-btn active")
399
  .style("background-color", color)
400
- .text(region)
401
  .on("click", function() {
402
  const isActive = d3.select(this).classed("active");
403
  d3.select(this).classed("active", !isActive);
@@ -488,23 +557,22 @@
488
  chartGroup.append("text")
489
  .attr("class", "axis-label")
490
  .attr("x", innerWidth / 2)
491
- .attr("y", innerHeight + 40)
492
  .text("GDP per capita (PPP, constant 2021 international $)");
493
 
494
  chartGroup.append("text")
495
  .attr("class", "axis-label")
496
  .attr("transform", "rotate(-90)")
497
  .attr("x", -innerHeight / 2)
498
- .attr("y", -40)
499
  .text("Life Expectancy (years)");
500
 
501
  // Add title
502
  chartGroup.append("text")
 
503
  .attr("x", innerWidth / 2)
504
- .attr("y", -20)
505
  .attr("text-anchor", "middle")
506
- .style("font-size", "16px")
507
- .style("font-weight", "bold")
508
  .text("Life Expectancy vs. GDP per capita");
509
 
510
  // Add year display on chart
@@ -513,30 +581,11 @@
513
  .attr("x", innerWidth - 10)
514
  .attr("y", -10)
515
  .attr("text-anchor", "end")
516
- .style("font-size", "24px")
517
  .style("font-weight", "bold")
518
- .style("fill", "#444")
 
519
  .text(state.currentYear);
520
-
521
- // Add legend
522
- const legend = state.svg.append("g")
523
- .attr("class", "legend")
524
- .attr("transform", `translate(${width - config.margin.right - 150}, ${config.margin.top})`);
525
-
526
- Object.entries(config.regions).forEach(([region, {color}], i) => {
527
- const legendItem = legend.append("g")
528
- .attr("transform", `translate(0, ${i * 20})`);
529
-
530
- legendItem.append("circle")
531
- .attr("r", 5)
532
- .attr("fill", color);
533
-
534
- legendItem.append("text")
535
- .attr("x", 10)
536
- .attr("y", 5)
537
- .style("font-size", "10px")
538
- .text(region);
539
- });
540
  }
541
 
542
  // Update chart with current data
@@ -615,12 +664,14 @@
615
  .on("mouseover", function(event, d) {
616
  dom.tooltip.style("opacity", 1)
617
  .html(`
618
- <strong>${d.entity}</strong><br>
619
- Year: ${d.year}<br>
620
- Region: ${d.region}<br>
621
- Life Expectancy: ${d.lifeExpectancy.toFixed(1)} years<br>
622
- GDP per capita: $${d.gdpPerCapita.toLocaleString('en-US', {maximumFractionDigits: 0})}<br>
623
- Population: ${d3.format(",.0f")(d.population)}
 
 
624
  `)
625
  .style("left", (event.pageX + 10) + "px")
626
  .style("top", (event.pageY - 10) + "px");
@@ -632,11 +683,11 @@
632
  newCircles.append("circle")
633
  .attr("r", 0)
634
  .attr("fill", d => config.regions[d.region] ? config.regions[d.region].color : "#95a5a6")
635
- .attr("opacity", 0.7)
636
- .transition(t)
637
- .attr("r", d => state.size(d.population))
638
  .attr("stroke", "#fff")
639
- .attr("stroke-width", 1);
 
 
640
 
641
  // Update existing bubbles
642
  circles.transition(t)
 
21
  background-color: white;
22
  border-radius: 10px;
23
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
24
+ padding: 30px;
25
  }
26
 
27
  h1 {
28
  text-align: center;
29
  color: #2c3e50;
30
  margin-bottom: 10px;
31
+ font-size: 2.2em;
32
  }
33
 
34
  .subtitle {
35
  text-align: center;
36
  color: #7f8c8d;
37
  margin-bottom: 30px;
38
+ font-size: 1.1em;
39
  }
40
 
41
  .controls {
 
44
  gap: 15px;
45
  margin-bottom: 25px;
46
  align-items: center;
47
+ padding: 20px;
48
  background-color: #f8f9fa;
49
  border-radius: 8px;
50
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.08);
51
  }
52
 
53
  .filter-buttons {
54
  display: flex;
55
  flex-wrap: wrap;
56
+ gap: 10px;
57
  margin-right: auto;
58
  }
59
 
60
  .filter-btn {
61
+ padding: 8px 16px;
62
  border: none;
63
+ border-radius: 25px;
64
  cursor: pointer;
65
  font-weight: 600;
66
  transition: all 0.3s;
67
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
68
+ font-size: 0.9em;
69
+ display: flex;
70
+ align-items: center;
71
+ }
72
+
73
+ .filter-btn i {
74
+ margin-right: 5px;
75
+ font-size: 0.9em;
76
  }
77
 
78
  .filter-btn:hover {
79
+ opacity: 0.9;
80
  transform: translateY(-2px);
81
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
82
  }
83
 
84
  .filter-btn.active {
85
  transform: scale(1.05);
86
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
87
  }
88
 
89
  .year-controls {
90
  display: flex;
91
  align-items: center;
92
+ gap: 15px;
93
+ background-color: rgba(255, 255, 255, 0.8);
94
+ padding: 10px 15px;
95
+ border-radius: 30px;
96
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
97
  }
98
 
99
  .year-slider {
100
+ width: 250px;
101
+ -webkit-appearance: none;
102
+ height: 6px;
103
+ background: #e0e0e0;
104
+ border-radius: 5px;
105
+ outline: none;
106
+ }
107
+
108
+ .year-slider::-webkit-slider-thumb {
109
+ -webkit-appearance: none;
110
+ appearance: none;
111
+ width: 18px;
112
+ height: 18px;
113
+ border-radius: 50%;
114
+ background: #3498db;
115
+ cursor: pointer;
116
+ transition: all 0.2s;
117
+ }
118
+
119
+ .year-slider::-webkit-slider-thumb:hover {
120
+ background: #2980b9;
121
+ transform: scale(1.1);
122
  }
123
 
124
  .play-btn {
125
  background-color: #2ecc71;
126
  color: white;
127
  border: none;
128
+ padding: 10px 20px;
129
+ border-radius: 30px;
130
  cursor: pointer;
131
  transition: all 0.3s;
132
  display: flex;
133
  align-items: center;
134
+ gap: 8px;
135
+ font-weight: 600;
136
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
137
  }
138
 
139
  .play-btn:hover {
140
  background-color: #27ae60;
141
+ transform: translateY(-2px);
142
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
143
  }
144
 
145
  .play-btn.playing {
 
148
 
149
  .year-display {
150
  font-weight: bold;
151
+ min-width: 50px;
152
  text-align: center;
153
+ font-size: 1.1em;
154
+ color: #2c3e50;
155
+ background-color: #f8f9fa;
156
+ padding: 5px 10px;
157
+ border-radius: 20px;
158
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
159
  }
160
 
161
  .chart-container {
162
  width: 100%;
163
+ height: 650px;
164
  position: relative;
165
  border-radius: 8px;
166
  overflow: hidden;
167
  background-color: white;
168
+ box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
169
+ border: 1px solid #eee;
170
  }
171
 
172
  .tooltip {
173
  position: absolute;
174
+ padding: 15px;
175
+ background: rgba(0, 0, 0, 0.9);
176
  color: white;
177
+ border-radius: 8px;
178
  pointer-events: none;
179
+ text-align: left;
180
  opacity: 0;
181
  transition: opacity 0.2s;
182
  font-size: 14px;
183
  z-index: 10;
184
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
185
+ max-width: 240px;
186
+ line-height: 1.5;
187
+ backdrop-filter: blur(2px);
188
  }
189
 
190
  .tooltip:after {
 
195
  margin-left: -8px;
196
  border-width: 8px;
197
  border-style: solid;
198
+ border-color: rgba(0, 0, 0, 0.9) transparent transparent transparent;
199
  }
200
 
201
  .loading {
 
223
  .axis-label {
224
  font-size: 12px;
225
  fill: #555;
226
+ font-weight: 500;
 
 
 
227
  }
228
 
229
  .disclaimer {
230
  text-align: center;
231
+ font-size: 13px;
232
  color: #7f8c8d;
233
+ margin-top: 20px;
234
+ line-height: 1.5;
235
+ }
236
+
237
+ .chart-title {
238
+ font-size: 14px;
239
+ font-weight: bold;
240
+ fill: #444;
241
  }
242
 
243
  @media (max-width: 768px) {
244
+ .container {
245
+ padding: 15px;
246
+ }
247
+
248
  .controls {
249
  flex-direction: column;
250
  align-items: stretch;
 
257
  }
258
 
259
  .year-controls {
260
+ width: 100%;
261
+ justify-content: space-between;
262
+ }
263
+
264
+ .year-slider {
265
+ width: 100%;
266
  }
267
 
268
  .chart-container {
269
+ height: 500px;
270
+ }
271
+
272
+ h1 {
273
+ font-size: 1.8em;
274
+ }
275
+
276
+ .subtitle {
277
+ font-size: 1em;
278
  }
279
  }
280
  </style>
 
306
  </div>
307
 
308
  <div class="tooltip" id="tooltip"></div>
309
+ <p class="disclaimer">Note: For countries missing region data in their year, we use the region from their latest available data.<br>Some countries/territories may not have complete indicator coverage for all years.</p>
310
  </div>
311
 
312
  <script>
313
  // Configuration
314
  const config = {
315
+ margin: { top: 60, right: 60, bottom: 80, left: 90 },
316
  minBubbleSize: 3,
317
+ maxBubbleSize: 45,
318
  animationDuration: 500,
319
  playInterval: 800,
320
  regions: {
321
+ "Africa": { color: "#e74c3c", icon: "globe-africa" },
322
+ "Asia": { color: "#3498db", icon: "globe-asia" },
323
+ "Europe": { color: "#2ecc71", icon: "globe-europe" },
324
+ "North America": { color: "#f1c40f", icon: "globe-americas" },
325
+ "Oceania": { color: "#9b59b6", icon: "map-marked-alt" },
326
+ "South America": { color: "#1abc9c", icon: "map-marked-alt" },
327
+ "Antarctica": { color: "#95a5a6", icon: "snowflake" }
328
  }
329
  };
330
 
 
462
  // Create region buttons
463
  dom.regionButtons.selectAll("*").remove();
464
 
465
+ Object.entries(config.regions).forEach(([region, { color, icon }]) => {
466
  const btn = dom.regionButtons.append("button")
467
  .attr("class", "filter-btn active")
468
  .style("background-color", color)
469
+ .html(`<i class="fas fa-${icon}"></i> ${region}`)
470
  .on("click", function() {
471
  const isActive = d3.select(this).classed("active");
472
  d3.select(this).classed("active", !isActive);
 
557
  chartGroup.append("text")
558
  .attr("class", "axis-label")
559
  .attr("x", innerWidth / 2)
560
+ .attr("y", innerHeight + 50)
561
  .text("GDP per capita (PPP, constant 2021 international $)");
562
 
563
  chartGroup.append("text")
564
  .attr("class", "axis-label")
565
  .attr("transform", "rotate(-90)")
566
  .attr("x", -innerHeight / 2)
567
+ .attr("y", -50)
568
  .text("Life Expectancy (years)");
569
 
570
  // Add title
571
  chartGroup.append("text")
572
+ .attr("class", "chart-title")
573
  .attr("x", innerWidth / 2)
574
+ .attr("y", -30)
575
  .attr("text-anchor", "middle")
 
 
576
  .text("Life Expectancy vs. GDP per capita");
577
 
578
  // Add year display on chart
 
581
  .attr("x", innerWidth - 10)
582
  .attr("y", -10)
583
  .attr("text-anchor", "end")
584
+ .style("font-size", "28px")
585
  .style("font-weight", "bold")
586
+ .style("fill", "#2c3e50")
587
+ .style("opacity", 0.9)
588
  .text(state.currentYear);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
589
  }
590
 
591
  // Update chart with current data
 
664
  .on("mouseover", function(event, d) {
665
  dom.tooltip.style("opacity", 1)
666
  .html(`
667
+ <div style="margin-bottom: 5px; font-size: 16px; font-weight: bold; color: ${config.regions[d.region].color}">
668
+ <i class="fas fa-${config.regions[d.region].icon}" style="margin-right: 5px;"></i>${d.entity}
669
+ </div>
670
+ <div><strong>Year:</strong> ${d.year}</div>
671
+ <div><strong>Region:</strong> ${d.region}</div>
672
+ <div><strong>Life Expectancy:</strong> ${d.lifeExpectancy.toFixed(1)} years</div>
673
+ <div><strong>GDP per capita:</strong> $${d.gdpPerCapita.toLocaleString('en-US', {maximumFractionDigits: 0})}</div>
674
+ <div><strong>Population:</strong> ${d3.format(",.0f")(d.population)}</div>
675
  `)
676
  .style("left", (event.pageX + 10) + "px")
677
  .style("top", (event.pageY - 10) + "px");
 
683
  newCircles.append("circle")
684
  .attr("r", 0)
685
  .attr("fill", d => config.regions[d.region] ? config.regions[d.region].color : "#95a5a6")
686
+ .attr("opacity", 0.8)
 
 
687
  .attr("stroke", "#fff")
688
+ .attr("stroke-width", 1.5)
689
+ .transition(t)
690
+ .attr("r", d => state.size(d.population));
691
 
692
  // Update existing bubbles
693
  circles.transition(t)