1 use crate::element::{DynElement, IntoDynElement, PathElement, Polygon}; 2 use crate::style::colors::TRANSPARENT; 3 use crate::style::ShapeStyle; 4 use plotters_backend::DrawingBackend; 5 6 /** 7 An area series is similar to a line series but uses a filled polygon. 8 It takes an iterator of data points in guest coordinate system 9 and creates appropriate lines and points with the given style. 10 11 # Example 12 13 ``` 14 use plotters::prelude::*; 15 let x_values = [0.0f64, 1., 2., 3., 4.]; 16 let drawing_area = SVGBackend::new("area_series.svg", (300, 200)).into_drawing_area(); 17 drawing_area.fill(&WHITE).unwrap(); 18 let mut chart_builder = ChartBuilder::on(&drawing_area); 19 chart_builder.margin(10).set_left_and_bottom_label_area_size(20); 20 let mut chart_context = chart_builder.build_cartesian_2d(0.0..4.0, 0.0..3.0).unwrap(); 21 chart_context.configure_mesh().draw().unwrap(); 22 chart_context.draw_series(AreaSeries::new(x_values.map(|x| (x, 0.3 * x)), 0., BLACK.mix(0.2))).unwrap(); 23 chart_context.draw_series(AreaSeries::new(x_values.map(|x| (x, 2.5 - 0.05 * x * x)), 0., RED.mix(0.2))).unwrap(); 24 chart_context.draw_series(AreaSeries::new(x_values.map(|x| (x, 2. - 0.1 * x * x)), 0., BLUE.mix(0.2)).border_style(BLUE)).unwrap(); 25 ``` 26 27 The result is a chart with three line series; one of them has a highlighted blue border: 28 29  30 */ 31 pub struct AreaSeries<DB: DrawingBackend, X: Clone, Y: Clone> { 32 area_style: ShapeStyle, 33 border_style: ShapeStyle, 34 baseline: Y, 35 data: Vec<(X, Y)>, 36 state: u32, 37 _p: std::marker::PhantomData<DB>, 38 } 39 40 impl<DB: DrawingBackend, X: Clone, Y: Clone> AreaSeries<DB, X, Y> { 41 /** 42 Creates an area series with transparent border. 43 44 See [`AreaSeries`] for more information and examples. 45 */ new<S: Into<ShapeStyle>, I: IntoIterator<Item = (X, Y)>>( iter: I, baseline: Y, area_style: S, ) -> Self46 pub fn new<S: Into<ShapeStyle>, I: IntoIterator<Item = (X, Y)>>( 47 iter: I, 48 baseline: Y, 49 area_style: S, 50 ) -> Self { 51 Self { 52 area_style: area_style.into(), 53 baseline, 54 data: iter.into_iter().collect(), 55 state: 0, 56 border_style: (&TRANSPARENT).into(), 57 _p: std::marker::PhantomData, 58 } 59 } 60 61 /** 62 Sets the border style of the area series. 63 64 See [`AreaSeries`] for more information and examples. 65 */ border_style<S: Into<ShapeStyle>>(mut self, style: S) -> Self66 pub fn border_style<S: Into<ShapeStyle>>(mut self, style: S) -> Self { 67 self.border_style = style.into(); 68 self 69 } 70 } 71 72 impl<DB: DrawingBackend, X: Clone + 'static, Y: Clone + 'static> Iterator for AreaSeries<DB, X, Y> { 73 type Item = DynElement<'static, DB, (X, Y)>; next(&mut self) -> Option<Self::Item>74 fn next(&mut self) -> Option<Self::Item> { 75 if self.state == 0 { 76 let mut data: Vec<_> = self.data.clone(); 77 78 if !data.is_empty() { 79 data.push((data[data.len() - 1].0.clone(), self.baseline.clone())); 80 data.push((data[0].0.clone(), self.baseline.clone())); 81 } 82 83 self.state = 1; 84 85 Some(Polygon::new(data, self.area_style).into_dyn()) 86 } else if self.state == 1 { 87 let data: Vec<_> = self.data.clone(); 88 89 self.state = 2; 90 91 Some(PathElement::new(data, self.border_style).into_dyn()) 92 } else { 93 None 94 } 95 } 96 } 97