diff options
author | 2023-06-09 11:03:52 -0700 | |
---|---|---|
committer | 2023-06-09 11:03:52 -0700 | |
commit | 290b47f312471db74e8b149e0f78df3891456208 (patch) | |
tree | 4b607558433676d2683ee471ae52fbf28024c6f1 /examples/loading_spinners | |
parent | 9d69af10ccb4317f01bff32e2e1e58d498b2fc89 (diff) | |
download | iced-290b47f312471db74e8b149e0f78df3891456208.tar.gz iced-290b47f312471db74e8b149e0f78df3891456208.tar.bz2 iced-290b47f312471db74e8b149e0f78df3891456208.zip |
refactor: remove unnecessary canvas complexity
Diffstat (limited to 'examples/loading_spinners')
-rw-r--r-- | examples/loading_spinners/src/circular.rs | 187 |
1 files changed, 67 insertions, 120 deletions
diff --git a/examples/loading_spinners/src/circular.rs b/examples/loading_spinners/src/circular.rs index 4e7bdc18..55363de1 100644 --- a/examples/loading_spinners/src/circular.rs +++ b/examples/loading_spinners/src/circular.rs @@ -5,7 +5,7 @@ use iced::advanced::widget::tree::{self, Tree}; use iced::advanced::{Clipboard, Layout, Renderer, Shell, Widget}; use iced::event; use iced::time::Instant; -use iced::widget::canvas::{self, Cursor, Program}; +use iced::widget::canvas; use iced::window::{self, RedrawRequest}; use iced::{Background, Color, Element, Rectangle}; use iced::{Event, Length, Point, Size, Vector}; @@ -15,8 +15,6 @@ use super::easing::{self, Easing}; use std::f32::consts::PI; use std::time::Duration; -type R<Theme> = iced::Renderer<Theme>; - const MIN_RADIANS: f32 = PI / 8.0; const WRAP_RADIANS: f32 = 2.0 * PI - PI / 4.0; const BASE_ROTATION_SPEED: u32 = u32::MAX / 80; @@ -98,7 +96,7 @@ where } #[derive(Clone, Copy)] -enum State { +enum Animation { Expanding { start: Instant, progress: f32, @@ -113,7 +111,7 @@ enum State { }, } -impl Default for State { +impl Default for Animation { fn default() -> Self { Self::Expanding { start: Instant::now(), @@ -124,7 +122,7 @@ impl Default for State { } } -impl State { +impl Animation { fn next(&self, additional_rotation: u32, now: Instant) -> Self { match self { Self::Expanding { rotation, .. } => Self::Contracting { @@ -224,7 +222,14 @@ impl State { } } -impl<'a, Message, Theme> Widget<Message, R<Theme>> for Circular<'a, Theme> +#[derive(Default)] +struct State { + animation: Animation, + cache: canvas::Cache, +} + +impl<'a, Message, Theme> Widget<Message, iced::Renderer<Theme>> + for Circular<'a, Theme> where Message: 'a + Clone, Theme: StyleSheet, @@ -271,12 +276,13 @@ where let state = tree.state.downcast_mut::<State>(); if let Event::Window(window::Event::RedrawRequested(now)) = event { - *state = state.timed_transition( + state.animation = state.animation.timed_transition( self.cycle_duration, self.rotation_duration, now, ); + state.cache.clear(); shell.request_redraw(RedrawRequest::At( now + Duration::from_millis(1000 / FRAME_RATE), )); @@ -288,42 +294,76 @@ where fn draw( &self, tree: &Tree, - renderer: &mut R<Theme>, + renderer: &mut iced::Renderer<Theme>, theme: &Theme, _style: &renderer::Style, layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, ) { - let bounds = layout.bounds(); let state = tree.state.downcast_ref::<State>(); + let bounds = layout.bounds(); + let custom_style = + <Theme as StyleSheet>::appearance(theme, &self.style); + + let geometry = state.cache.draw(renderer, bounds.size(), |frame| { + let track_radius = frame.width() / 2.0 - self.bar_height; + let track_path = canvas::Path::circle(frame.center(), track_radius); + + frame.stroke( + &track_path, + canvas::Stroke::default() + .with_color(custom_style.track_color) + .with_width(self.bar_height), + ); + + let mut builder = canvas::path::Builder::new(); + + let start = state.animation.rotation() * 2.0 * PI; + + match state.animation { + Animation::Expanding { progress, .. } => { + builder.arc(canvas::path::Arc { + center: frame.center(), + radius: track_radius, + start_angle: start, + end_angle: start + + MIN_RADIANS + + WRAP_RADIANS * (self.easing.y_at_x(progress)), + }); + } + Animation::Contracting { progress, .. } => { + builder.arc(canvas::path::Arc { + center: frame.center(), + radius: track_radius, + start_angle: start + + WRAP_RADIANS * (self.easing.y_at_x(progress)), + end_angle: start + MIN_RADIANS + WRAP_RADIANS, + }); + } + } + + let bar_path = builder.build(); + + frame.stroke( + &bar_path, + canvas::Stroke::default() + .with_color(custom_style.bar_color) + .with_width(self.bar_height), + ); + }); renderer.with_translation( Vector::new(bounds.x, bounds.y), |renderer| { - canvas::Renderer::draw( - renderer, - <StateWithStyle<Theme> as Program<Message, R<Theme>>>::draw( - &StateWithStyle { - state, - style: &self.style, - bar_height: self.bar_height, - easing: self.easing, - }, - &(), - renderer, - theme, - bounds, - Cursor::Unavailable, - ), - ); + renderer.draw_primitive(geometry.0); }, ); } } impl<'a, Message, Theme> From<Circular<'a, Theme>> - for Element<'a, Message, R<Theme>> + for Element<'a, Message, iced::Renderer<Theme>> where Message: Clone + 'a, Theme: StyleSheet + 'a, @@ -375,96 +415,3 @@ impl StyleSheet for iced::Theme { } } } - -struct StateWithStyle<'a, Theme> -where - Theme: StyleSheet, -{ - state: &'a State, - style: &'a <Theme as StyleSheet>::Style, - easing: &'a Easing, - bar_height: f32, -} - -impl<'a, Message, Theme> Program<Message, iced::Renderer<Theme>> - for StateWithStyle<'a, Theme> -where - Theme: StyleSheet, -{ - type State = (); - - fn update( - &self, - _state: &mut Self::State, - _event: canvas::Event, - _bounds: Rectangle, - _cursor: canvas::Cursor, - ) -> (canvas::event::Status, Option<Message>) { - (canvas::event::Status::Ignored, None) - } - - fn draw( - &self, - _state: &Self::State, - renderer: &iced::Renderer<Theme>, - theme: &Theme, - bounds: Rectangle, - _cursor: canvas::Cursor, - ) -> Vec<canvas::Geometry> { - let mut frame = canvas::Frame::new(renderer, bounds.size()); - let custom_style = <Theme as StyleSheet>::appearance(theme, self.style); - let track_radius = frame.width() / 2.0 - self.bar_height; - - if let Some(Background::Color(color)) = custom_style.background { - let background_path = - canvas::Path::circle(frame.center(), track_radius); - frame.fill(&background_path, color); - } - - let track_path = canvas::Path::circle(frame.center(), track_radius); - - frame.stroke( - &track_path, - canvas::Stroke::default() - .with_color(custom_style.track_color) - .with_width(self.bar_height), - ); - - let mut builder = canvas::path::Builder::new(); - - let start = self.state.rotation() * 2.0 * PI; - - match self.state { - State::Expanding { progress, .. } => { - builder.arc(canvas::path::Arc { - center: frame.center(), - radius: track_radius, - start_angle: start, - end_angle: start - + MIN_RADIANS - + WRAP_RADIANS * (self.easing.y_at_x(*progress)), - }); - } - State::Contracting { progress, .. } => { - builder.arc(canvas::path::Arc { - center: frame.center(), - radius: track_radius, - start_angle: start - + WRAP_RADIANS * (self.easing.y_at_x(*progress)), - end_angle: start + MIN_RADIANS + WRAP_RADIANS, - }); - } - } - - let bar_path = builder.build(); - - frame.stroke( - &bar_path, - canvas::Stroke::default() - .with_color(custom_style.bar_color) - .with_width(self.bar_height), - ); - - vec![frame.into_geometry()] - } -} |