@@ -3,12 +3,16 @@ use plotters::prelude::*;
3
3
use std:: fs:: File ;
4
4
use std:: io:: BufReader ;
5
5
6
+ use chrono:: NaiveDate ;
7
+ use std:: str:: FromStr ;
8
+
6
9
#[ derive( serde_derive:: Deserialize ) ]
7
10
struct DailyData {
11
+ date : String ,
8
12
#[ serde( default ) ]
9
- new_cases : f64 ,
13
+ new_cases_smoothed_per_million : f64 ,
10
14
#[ serde( default ) ]
11
- total_cases : f64 ,
15
+ total_cases_per_million : f64 ,
12
16
}
13
17
14
18
#[ derive( serde_derive:: Deserialize ) ]
@@ -18,65 +22,68 @@ struct CountryData {
18
22
19
23
fn main ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
20
24
let root =
21
- SVGBackend :: new ( "plotters-doc-data/ tick_control.svg ", ( 1024 , 768 ) ) . into_drawing_area ( ) ;
25
+ BitMapBackend :: gif ( "/tmp/ tick_control.gif ", ( 800 , 600 ) , 100 ) ? . into_drawing_area ( ) ;
22
26
23
- root . fill ( & WHITE ) ? ;
27
+ for a in 0 .. 200 {
24
28
25
- let ( upper , lower ) = root. split_vertically ( 750 ) ;
29
+ root. fill ( & WHITE ) ? ;
26
30
27
- lower. titled (
28
- "Data Source: https://covid.ourworldindata.org/data/owid-covid-data.json" ,
29
- ( "sans-serif" , 10 ) . into_font ( ) . color ( & BLACK . mix ( 0.5 ) ) ,
30
- ) ?;
31
31
32
- let mut chart = ChartBuilder :: on ( & upper)
33
- . caption ( "World COVID-19 Cases" , ( "sans-serif" , ( 5 ) . percent_height ( ) ) )
34
- . set_label_area_size ( LabelAreaPosition :: Left , ( 8 ) . percent ( ) )
35
- . set_label_area_size ( LabelAreaPosition :: Bottom , ( 4 ) . percent ( ) )
36
- . margin ( ( 1 ) . percent ( ) )
37
- . build_cartesian_2d (
38
- ( 20u32 ..5000_0000u32 )
39
- . log_scale ( )
40
- . with_key_points ( vec ! [ 50 , 100 , 1000 , 10000 , 100000 , 1000000 , 10000000 ] ) ,
41
- ( 0u32 ..50_0000u32 )
42
- . log_scale ( )
43
- . with_key_points ( vec ! [ 10 , 50 , 100 , 1000 , 10000 , 100000 , 200000 ] ) ,
44
- ) ?;
32
+ let mut chart = ChartBuilder :: on ( & root)
33
+ . set_label_area_size ( LabelAreaPosition :: Left , ( 8 ) . percent ( ) )
34
+ . set_label_area_size ( LabelAreaPosition :: Bottom , ( 6 ) . percent ( ) )
35
+ . margin ( ( 1 ) . percent ( ) )
36
+ . build_cartesian_3d (
37
+ ( 20u32 ..10_0000u32 )
38
+ . log_scale ( )
39
+ . with_key_points ( vec ! [ 50 , 100 , 200 , 500 , 1000 , 10000 ] ) ,
40
+ ( 0u32 ..1000u32 )
41
+ . log_scale ( )
42
+ . with_key_points ( vec ! [ 2 , 5 , 10 , 20 , 50 , 100 , 200 ] ) ,
43
+ NaiveDate :: from_ymd ( 2020 , 1 , 1 ) ..NaiveDate :: from_ymd ( 2020 , 9 , 5 ) ,
44
+ ) ?;
45
+
46
+ chart. with_projection ( |mut pb| {
47
+ pb. yaw = ( 1.57 - a as f64 / 100.0 * 1.57 ) . abs ( ) ;
48
+ pb. into_matrix ( )
49
+ } ) ;
50
+
51
+ chart
52
+ . configure_axes ( )
53
+ . draw ( ) ?;
45
54
46
- chart
47
- . configure_mesh ( )
48
- . x_desc ( "Total Cases" )
49
- . y_desc ( "New Cases" )
50
- . draw ( ) ?;
55
+ let data: std:: collections:: HashMap < String , CountryData > = serde_json:: from_reader (
56
+ BufReader :: new ( File :: open ( "plotters-doc-data/covid-data.json" ) ?) ,
57
+ ) ?;
51
58
52
- let data: std:: collections:: HashMap < String , CountryData > = serde_json:: from_reader (
53
- BufReader :: new ( File :: open ( "plotters-doc-data/covid-data.json" ) ?) ,
54
- ) ?;
59
+ for ( idx, & series) in [ "USA" , "CHN" ]
60
+ . iter ( )
61
+ . enumerate ( )
62
+ {
63
+ let color = Palette99 :: pick ( idx) . mix ( 1.0 ) ;
64
+ chart
65
+ . draw_series ( LineSeries :: new (
66
+ data[ series] . data . iter ( ) . map (
67
+ |DailyData {
68
+ date,
69
+ new_cases_smoothed_per_million,
70
+ total_cases_per_million,
71
+ ..
72
+ } | ( * total_cases_per_million as u32 , * new_cases_smoothed_per_million as u32 , chrono:: NaiveDate :: from_str ( date) . unwrap ( ) , ) ,
73
+ ) ,
74
+ color. stroke_width ( 1 ) ,
75
+ ) ) ?
76
+ . label ( series)
77
+ . legend ( move |( x, y) | Rectangle :: new ( [ ( x, y - 5 ) , ( x + 10 , y + 5 ) ] , color. filled ( ) ) ) ;
78
+ }
55
79
56
- for ( idx, & series) in [ "CHN" , "USA" , "RUS" , "JPN" , "DEU" , "IND" , "OWID_WRL" ]
57
- . iter ( )
58
- . enumerate ( )
59
- {
60
- let color = Palette99 :: pick ( idx) . mix ( 0.9 ) ;
61
80
chart
62
- . draw_series ( LineSeries :: new (
63
- data[ series] . data . iter ( ) . map (
64
- |& DailyData {
65
- new_cases,
66
- total_cases,
67
- ..
68
- } | ( total_cases as u32 , new_cases as u32 ) ,
69
- ) ,
70
- color. stroke_width ( 3 ) ,
71
- ) ) ?
72
- . label ( series)
73
- . legend ( move |( x, y) | Rectangle :: new ( [ ( x, y - 5 ) , ( x + 10 , y + 5 ) ] , color. filled ( ) ) ) ;
74
- }
81
+ . configure_series_labels ( )
82
+ . border_style ( & BLACK )
83
+ . draw ( ) ?;
75
84
76
- chart
77
- . configure_series_labels ( )
78
- . border_style ( & BLACK )
79
- . draw ( ) ?;
85
+ root. present ( ) ?;
86
+ }
80
87
81
88
Ok ( ( ) )
82
89
}
0 commit comments