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 /// An area series is similar to a line series but use a filled polygon 7 pub struct AreaSeries<DB: DrawingBackend, X: Clone, Y: Clone> { 8 area_style: ShapeStyle, 9 border_style: ShapeStyle, 10 baseline: Y, 11 data: Vec<(X, Y)>, 12 state: u32, 13 _p: std::marker::PhantomData<DB>, 14 } 15 16 impl<DB: DrawingBackend, X: Clone, Y: Clone> AreaSeries<DB, X, Y> { new<S: Into<ShapeStyle>, I: IntoIterator<Item = (X, Y)>>( iter: I, baseline: Y, area_style: S, ) -> Self17 pub fn new<S: Into<ShapeStyle>, I: IntoIterator<Item = (X, Y)>>( 18 iter: I, 19 baseline: Y, 20 area_style: S, 21 ) -> Self { 22 Self { 23 area_style: area_style.into(), 24 baseline, 25 data: iter.into_iter().collect(), 26 state: 0, 27 border_style: (&TRANSPARENT).into(), 28 _p: std::marker::PhantomData, 29 } 30 } 31 border_style<S: Into<ShapeStyle>>(mut self, style: S) -> Self32 pub fn border_style<S: Into<ShapeStyle>>(mut self, style: S) -> Self { 33 self.border_style = style.into(); 34 self 35 } 36 } 37 38 impl<DB: DrawingBackend, X: Clone + 'static, Y: Clone + 'static> Iterator for AreaSeries<DB, X, Y> { 39 type Item = DynElement<'static, DB, (X, Y)>; next(&mut self) -> Option<Self::Item>40 fn next(&mut self) -> Option<Self::Item> { 41 if self.state == 0 { 42 let mut data: Vec<_> = self.data.clone(); 43 44 if !data.is_empty() { 45 data.push((data[data.len() - 1].0.clone(), self.baseline.clone())); 46 data.push((data[0].0.clone(), self.baseline.clone())); 47 } 48 49 self.state = 1; 50 51 Some(Polygon::new(data, self.area_style.clone()).into_dyn()) 52 } else if self.state == 1 { 53 let data: Vec<_> = self.data.clone(); 54 55 self.state = 2; 56 57 Some(PathElement::new(data, self.border_style.clone()).into_dyn()) 58 } else { 59 None 60 } 61 } 62 } 63