pub struct Canvas<'a, F>{ /* private fields */ }
Expand description
The Canvas widget provides a means to draw shapes (Lines, Rectangles, Circles, etc.) on a grid.
By default the grid is made of Braille patterns but you may change the marker to use a different
set of symbols. If your terminal or font does not support this unicode block, you will see
unicode replacement characters (�) instead of braille dots. The Braille patterns provide a more
fine grained result (2x4 dots) but you might want to use a simple dot, block, or bar instead by
calling the marker
method if your target environment does not support those symbols,
See Unicode Braille Patterns for more info.
The HalfBlock
marker is useful when you want to draw shapes with a higher resolution than a
CharGrid
but lower than a BrailleGrid
. This grid type supports a foreground and background
color for each terminal cell. This allows for more flexibility than the BrailleGrid
which only
supports a single foreground color for each 2x4 dots cell.
The Canvas widget is used by calling the Canvas::paint
method and passing a closure that
will be used to draw on the canvas. The closure will be passed a Context
object that can be
used to draw shapes on the canvas.
The Context
object provides a Context::draw
method that can be used to draw shapes on
the canvas. The Context::layer
method can be used to save the current state of the canvas
and start a new layer. This is useful if you want to draw multiple shapes on the canvas in
specific order. The Context
object also provides a Context::print
method that can be
used to print text on the canvas. Note that the text is always printed on top of the canvas and
is not affected by the layers.
§Examples
use ratatui::{
style::Color,
widgets::{
canvas::{Canvas, Line, Map, MapResolution, Rectangle},
Block,
},
};
Canvas::default()
.block(Block::bordered().title("Canvas"))
.x_bounds([-180.0, 180.0])
.y_bounds([-90.0, 90.0])
.paint(|ctx| {
ctx.draw(&Map {
resolution: MapResolution::High,
color: Color::White,
});
ctx.layer();
ctx.draw(&Line {
x1: 0.0,
y1: 10.0,
x2: 10.0,
y2: 10.0,
color: Color::White,
});
ctx.draw(&Rectangle {
x: 10.0,
y: 20.0,
width: 10.0,
height: 10.0,
color: Color::Red,
});
});
Implementations§
Source§impl<'a, F> Canvas<'a, F>
impl<'a, F> Canvas<'a, F>
Sourcepub fn block(self, block: Block<'a>) -> Self
pub fn block(self, block: Block<'a>) -> Self
Wraps the canvas with a custom Block
widget.
This is a fluent setter method which must be chained or used as it consumes self
Examples found in repository?
176 fn map_canvas(&self) -> impl Widget + '_ {
177 Canvas::default()
178 .block(Block::bordered().title("World"))
179 .marker(self.marker)
180 .paint(|ctx| {
181 ctx.draw(&Map {
182 color: Color::Green,
183 resolution: MapResolution::High,
184 });
185 ctx.print(self.x, -self.y, "You are here".yellow());
186 })
187 .x_bounds([-180.0, 180.0])
188 .y_bounds([-90.0, 90.0])
189 }
190
191 fn draw_canvas(&self, area: Rect) -> impl Widget + '_ {
192 Canvas::default()
193 .block(Block::bordered().title("Draw here"))
194 .marker(self.marker)
195 .x_bounds([0.0, f64::from(area.width)])
196 .y_bounds([0.0, f64::from(area.height)])
197 .paint(move |ctx| {
198 let points = self
199 .points
200 .iter()
201 .map(|p| {
202 (
203 f64::from(p.x) - f64::from(area.left()),
204 f64::from(area.bottom()) - f64::from(p.y),
205 )
206 })
207 .collect_vec();
208 ctx.draw(&Points {
209 coords: &points,
210 color: Color::White,
211 });
212 })
213 }
214
215 fn pong_canvas(&self) -> impl Widget + '_ {
216 Canvas::default()
217 .block(Block::bordered().title("Pong"))
218 .marker(self.marker)
219 .paint(|ctx| {
220 ctx.draw(&self.ball);
221 })
222 .x_bounds([10.0, 210.0])
223 .y_bounds([10.0, 110.0])
224 }
225
226 fn boxes_canvas(&self, area: Rect) -> impl Widget {
227 let left = 0.0;
228 let right = f64::from(area.width);
229 let bottom = 0.0;
230 let top = f64::from(area.height).mul_add(2.0, -4.0);
231 Canvas::default()
232 .block(Block::bordered().title("Rects"))
233 .marker(self.marker)
234 .x_bounds([left, right])
235 .y_bounds([bottom, top])
236 .paint(|ctx| {
237 for i in 0..=11 {
238 ctx.draw(&Rectangle {
239 x: f64::from(i * i + 3 * i) / 2.0 + 2.0,
240 y: 2.0,
241 width: f64::from(i),
242 height: f64::from(i),
243 color: Color::Red,
244 });
245 ctx.draw(&Rectangle {
246 x: f64::from(i * i + 3 * i) / 2.0 + 2.0,
247 y: 21.0,
248 width: f64::from(i),
249 height: f64::from(i),
250 color: Color::Blue,
251 });
252 }
253 for i in 0..100 {
254 if i % 10 != 0 {
255 ctx.print(f64::from(i) + 1.0, 0.0, format!("{i}", i = i % 10));
256 }
257 if i % 2 == 0 && i % 10 != 0 {
258 ctx.print(0.0, f64::from(i), format!("{i}", i = i % 10));
259 }
260 }
261 })
262 }
More examples
107fn render_map(selected_row: usize, area: Rect, buf: &mut Buffer) {
108 let theme = THEME.traceroute.map;
109 let path: Option<(&Hop, &Hop)> = HOPS.iter().tuple_windows().nth(selected_row);
110 let map = Map {
111 resolution: MapResolution::High,
112 color: theme.color,
113 };
114 Canvas::default()
115 .background_color(theme.background_color)
116 .block(
117 Block::new()
118 .padding(Padding::new(1, 0, 1, 0))
119 .style(theme.style),
120 )
121 .marker(Marker::HalfBlock)
122 // picked to show Australia for the demo as it's the most interesting part of the map
123 // (and the only part with hops ;))
124 .x_bounds([112.0, 155.0])
125 .y_bounds([-46.0, -11.0])
126 .paint(|context| {
127 context.draw(&map);
128 if let Some(path) = path {
129 context.draw(&canvas::Line::new(
130 path.0.location.0,
131 path.0.location.1,
132 path.1.location.0,
133 path.1.location.1,
134 theme.path,
135 ));
136 context.draw(&Points {
137 color: theme.source,
138 coords: &[path.0.location], // sydney
139 });
140 context.draw(&Points {
141 color: theme.destination,
142 coords: &[path.1.location], // perth
143 });
144 }
145 })
146 .render(area, buf);
147}
Sourcepub const fn x_bounds(self, bounds: [f64; 2]) -> Self
pub const fn x_bounds(self, bounds: [f64; 2]) -> Self
Define the viewport of the canvas.
If you were to “zoom” to a certain part of the world you may want to choose different bounds.
This is a fluent setter method which must be chained or used as it consumes self
Examples found in repository?
176 fn map_canvas(&self) -> impl Widget + '_ {
177 Canvas::default()
178 .block(Block::bordered().title("World"))
179 .marker(self.marker)
180 .paint(|ctx| {
181 ctx.draw(&Map {
182 color: Color::Green,
183 resolution: MapResolution::High,
184 });
185 ctx.print(self.x, -self.y, "You are here".yellow());
186 })
187 .x_bounds([-180.0, 180.0])
188 .y_bounds([-90.0, 90.0])
189 }
190
191 fn draw_canvas(&self, area: Rect) -> impl Widget + '_ {
192 Canvas::default()
193 .block(Block::bordered().title("Draw here"))
194 .marker(self.marker)
195 .x_bounds([0.0, f64::from(area.width)])
196 .y_bounds([0.0, f64::from(area.height)])
197 .paint(move |ctx| {
198 let points = self
199 .points
200 .iter()
201 .map(|p| {
202 (
203 f64::from(p.x) - f64::from(area.left()),
204 f64::from(area.bottom()) - f64::from(p.y),
205 )
206 })
207 .collect_vec();
208 ctx.draw(&Points {
209 coords: &points,
210 color: Color::White,
211 });
212 })
213 }
214
215 fn pong_canvas(&self) -> impl Widget + '_ {
216 Canvas::default()
217 .block(Block::bordered().title("Pong"))
218 .marker(self.marker)
219 .paint(|ctx| {
220 ctx.draw(&self.ball);
221 })
222 .x_bounds([10.0, 210.0])
223 .y_bounds([10.0, 110.0])
224 }
225
226 fn boxes_canvas(&self, area: Rect) -> impl Widget {
227 let left = 0.0;
228 let right = f64::from(area.width);
229 let bottom = 0.0;
230 let top = f64::from(area.height).mul_add(2.0, -4.0);
231 Canvas::default()
232 .block(Block::bordered().title("Rects"))
233 .marker(self.marker)
234 .x_bounds([left, right])
235 .y_bounds([bottom, top])
236 .paint(|ctx| {
237 for i in 0..=11 {
238 ctx.draw(&Rectangle {
239 x: f64::from(i * i + 3 * i) / 2.0 + 2.0,
240 y: 2.0,
241 width: f64::from(i),
242 height: f64::from(i),
243 color: Color::Red,
244 });
245 ctx.draw(&Rectangle {
246 x: f64::from(i * i + 3 * i) / 2.0 + 2.0,
247 y: 21.0,
248 width: f64::from(i),
249 height: f64::from(i),
250 color: Color::Blue,
251 });
252 }
253 for i in 0..100 {
254 if i % 10 != 0 {
255 ctx.print(f64::from(i) + 1.0, 0.0, format!("{i}", i = i % 10));
256 }
257 if i % 2 == 0 && i % 10 != 0 {
258 ctx.print(0.0, f64::from(i), format!("{i}", i = i % 10));
259 }
260 }
261 })
262 }
More examples
107fn render_map(selected_row: usize, area: Rect, buf: &mut Buffer) {
108 let theme = THEME.traceroute.map;
109 let path: Option<(&Hop, &Hop)> = HOPS.iter().tuple_windows().nth(selected_row);
110 let map = Map {
111 resolution: MapResolution::High,
112 color: theme.color,
113 };
114 Canvas::default()
115 .background_color(theme.background_color)
116 .block(
117 Block::new()
118 .padding(Padding::new(1, 0, 1, 0))
119 .style(theme.style),
120 )
121 .marker(Marker::HalfBlock)
122 // picked to show Australia for the demo as it's the most interesting part of the map
123 // (and the only part with hops ;))
124 .x_bounds([112.0, 155.0])
125 .y_bounds([-46.0, -11.0])
126 .paint(|context| {
127 context.draw(&map);
128 if let Some(path) = path {
129 context.draw(&canvas::Line::new(
130 path.0.location.0,
131 path.0.location.1,
132 path.1.location.0,
133 path.1.location.1,
134 theme.path,
135 ));
136 context.draw(&Points {
137 color: theme.source,
138 coords: &[path.0.location], // sydney
139 });
140 context.draw(&Points {
141 color: theme.destination,
142 coords: &[path.1.location], // perth
143 });
144 }
145 })
146 .render(area, buf);
147}
Sourcepub const fn y_bounds(self, bounds: [f64; 2]) -> Self
pub const fn y_bounds(self, bounds: [f64; 2]) -> Self
Define the viewport of the canvas.
If you were to “zoom” to a certain part of the world you may want to choose different bounds.
This is a fluent setter method which must be chained or used as it consumes self
Examples found in repository?
176 fn map_canvas(&self) -> impl Widget + '_ {
177 Canvas::default()
178 .block(Block::bordered().title("World"))
179 .marker(self.marker)
180 .paint(|ctx| {
181 ctx.draw(&Map {
182 color: Color::Green,
183 resolution: MapResolution::High,
184 });
185 ctx.print(self.x, -self.y, "You are here".yellow());
186 })
187 .x_bounds([-180.0, 180.0])
188 .y_bounds([-90.0, 90.0])
189 }
190
191 fn draw_canvas(&self, area: Rect) -> impl Widget + '_ {
192 Canvas::default()
193 .block(Block::bordered().title("Draw here"))
194 .marker(self.marker)
195 .x_bounds([0.0, f64::from(area.width)])
196 .y_bounds([0.0, f64::from(area.height)])
197 .paint(move |ctx| {
198 let points = self
199 .points
200 .iter()
201 .map(|p| {
202 (
203 f64::from(p.x) - f64::from(area.left()),
204 f64::from(area.bottom()) - f64::from(p.y),
205 )
206 })
207 .collect_vec();
208 ctx.draw(&Points {
209 coords: &points,
210 color: Color::White,
211 });
212 })
213 }
214
215 fn pong_canvas(&self) -> impl Widget + '_ {
216 Canvas::default()
217 .block(Block::bordered().title("Pong"))
218 .marker(self.marker)
219 .paint(|ctx| {
220 ctx.draw(&self.ball);
221 })
222 .x_bounds([10.0, 210.0])
223 .y_bounds([10.0, 110.0])
224 }
225
226 fn boxes_canvas(&self, area: Rect) -> impl Widget {
227 let left = 0.0;
228 let right = f64::from(area.width);
229 let bottom = 0.0;
230 let top = f64::from(area.height).mul_add(2.0, -4.0);
231 Canvas::default()
232 .block(Block::bordered().title("Rects"))
233 .marker(self.marker)
234 .x_bounds([left, right])
235 .y_bounds([bottom, top])
236 .paint(|ctx| {
237 for i in 0..=11 {
238 ctx.draw(&Rectangle {
239 x: f64::from(i * i + 3 * i) / 2.0 + 2.0,
240 y: 2.0,
241 width: f64::from(i),
242 height: f64::from(i),
243 color: Color::Red,
244 });
245 ctx.draw(&Rectangle {
246 x: f64::from(i * i + 3 * i) / 2.0 + 2.0,
247 y: 21.0,
248 width: f64::from(i),
249 height: f64::from(i),
250 color: Color::Blue,
251 });
252 }
253 for i in 0..100 {
254 if i % 10 != 0 {
255 ctx.print(f64::from(i) + 1.0, 0.0, format!("{i}", i = i % 10));
256 }
257 if i % 2 == 0 && i % 10 != 0 {
258 ctx.print(0.0, f64::from(i), format!("{i}", i = i % 10));
259 }
260 }
261 })
262 }
More examples
107fn render_map(selected_row: usize, area: Rect, buf: &mut Buffer) {
108 let theme = THEME.traceroute.map;
109 let path: Option<(&Hop, &Hop)> = HOPS.iter().tuple_windows().nth(selected_row);
110 let map = Map {
111 resolution: MapResolution::High,
112 color: theme.color,
113 };
114 Canvas::default()
115 .background_color(theme.background_color)
116 .block(
117 Block::new()
118 .padding(Padding::new(1, 0, 1, 0))
119 .style(theme.style),
120 )
121 .marker(Marker::HalfBlock)
122 // picked to show Australia for the demo as it's the most interesting part of the map
123 // (and the only part with hops ;))
124 .x_bounds([112.0, 155.0])
125 .y_bounds([-46.0, -11.0])
126 .paint(|context| {
127 context.draw(&map);
128 if let Some(path) = path {
129 context.draw(&canvas::Line::new(
130 path.0.location.0,
131 path.0.location.1,
132 path.1.location.0,
133 path.1.location.1,
134 theme.path,
135 ));
136 context.draw(&Points {
137 color: theme.source,
138 coords: &[path.0.location], // sydney
139 });
140 context.draw(&Points {
141 color: theme.destination,
142 coords: &[path.1.location], // perth
143 });
144 }
145 })
146 .render(area, buf);
147}
Sourcepub fn paint(self, f: F) -> Self
pub fn paint(self, f: F) -> Self
Store the closure that will be used to draw to the Canvas
This is a fluent setter method which must be chained or used as it consumes self
Examples found in repository?
176 fn map_canvas(&self) -> impl Widget + '_ {
177 Canvas::default()
178 .block(Block::bordered().title("World"))
179 .marker(self.marker)
180 .paint(|ctx| {
181 ctx.draw(&Map {
182 color: Color::Green,
183 resolution: MapResolution::High,
184 });
185 ctx.print(self.x, -self.y, "You are here".yellow());
186 })
187 .x_bounds([-180.0, 180.0])
188 .y_bounds([-90.0, 90.0])
189 }
190
191 fn draw_canvas(&self, area: Rect) -> impl Widget + '_ {
192 Canvas::default()
193 .block(Block::bordered().title("Draw here"))
194 .marker(self.marker)
195 .x_bounds([0.0, f64::from(area.width)])
196 .y_bounds([0.0, f64::from(area.height)])
197 .paint(move |ctx| {
198 let points = self
199 .points
200 .iter()
201 .map(|p| {
202 (
203 f64::from(p.x) - f64::from(area.left()),
204 f64::from(area.bottom()) - f64::from(p.y),
205 )
206 })
207 .collect_vec();
208 ctx.draw(&Points {
209 coords: &points,
210 color: Color::White,
211 });
212 })
213 }
214
215 fn pong_canvas(&self) -> impl Widget + '_ {
216 Canvas::default()
217 .block(Block::bordered().title("Pong"))
218 .marker(self.marker)
219 .paint(|ctx| {
220 ctx.draw(&self.ball);
221 })
222 .x_bounds([10.0, 210.0])
223 .y_bounds([10.0, 110.0])
224 }
225
226 fn boxes_canvas(&self, area: Rect) -> impl Widget {
227 let left = 0.0;
228 let right = f64::from(area.width);
229 let bottom = 0.0;
230 let top = f64::from(area.height).mul_add(2.0, -4.0);
231 Canvas::default()
232 .block(Block::bordered().title("Rects"))
233 .marker(self.marker)
234 .x_bounds([left, right])
235 .y_bounds([bottom, top])
236 .paint(|ctx| {
237 for i in 0..=11 {
238 ctx.draw(&Rectangle {
239 x: f64::from(i * i + 3 * i) / 2.0 + 2.0,
240 y: 2.0,
241 width: f64::from(i),
242 height: f64::from(i),
243 color: Color::Red,
244 });
245 ctx.draw(&Rectangle {
246 x: f64::from(i * i + 3 * i) / 2.0 + 2.0,
247 y: 21.0,
248 width: f64::from(i),
249 height: f64::from(i),
250 color: Color::Blue,
251 });
252 }
253 for i in 0..100 {
254 if i % 10 != 0 {
255 ctx.print(f64::from(i) + 1.0, 0.0, format!("{i}", i = i % 10));
256 }
257 if i % 2 == 0 && i % 10 != 0 {
258 ctx.print(0.0, f64::from(i), format!("{i}", i = i % 10));
259 }
260 }
261 })
262 }
More examples
107fn render_map(selected_row: usize, area: Rect, buf: &mut Buffer) {
108 let theme = THEME.traceroute.map;
109 let path: Option<(&Hop, &Hop)> = HOPS.iter().tuple_windows().nth(selected_row);
110 let map = Map {
111 resolution: MapResolution::High,
112 color: theme.color,
113 };
114 Canvas::default()
115 .background_color(theme.background_color)
116 .block(
117 Block::new()
118 .padding(Padding::new(1, 0, 1, 0))
119 .style(theme.style),
120 )
121 .marker(Marker::HalfBlock)
122 // picked to show Australia for the demo as it's the most interesting part of the map
123 // (and the only part with hops ;))
124 .x_bounds([112.0, 155.0])
125 .y_bounds([-46.0, -11.0])
126 .paint(|context| {
127 context.draw(&map);
128 if let Some(path) = path {
129 context.draw(&canvas::Line::new(
130 path.0.location.0,
131 path.0.location.1,
132 path.1.location.0,
133 path.1.location.1,
134 theme.path,
135 ));
136 context.draw(&Points {
137 color: theme.source,
138 coords: &[path.0.location], // sydney
139 });
140 context.draw(&Points {
141 color: theme.destination,
142 coords: &[path.1.location], // perth
143 });
144 }
145 })
146 .render(area, buf);
147}
Sourcepub const fn background_color(self, color: Color) -> Self
pub const fn background_color(self, color: Color) -> Self
Change the background Color
of the entire canvas
This is a fluent setter method which must be chained or used as it consumes self
Examples found in repository?
107fn render_map(selected_row: usize, area: Rect, buf: &mut Buffer) {
108 let theme = THEME.traceroute.map;
109 let path: Option<(&Hop, &Hop)> = HOPS.iter().tuple_windows().nth(selected_row);
110 let map = Map {
111 resolution: MapResolution::High,
112 color: theme.color,
113 };
114 Canvas::default()
115 .background_color(theme.background_color)
116 .block(
117 Block::new()
118 .padding(Padding::new(1, 0, 1, 0))
119 .style(theme.style),
120 )
121 .marker(Marker::HalfBlock)
122 // picked to show Australia for the demo as it's the most interesting part of the map
123 // (and the only part with hops ;))
124 .x_bounds([112.0, 155.0])
125 .y_bounds([-46.0, -11.0])
126 .paint(|context| {
127 context.draw(&map);
128 if let Some(path) = path {
129 context.draw(&canvas::Line::new(
130 path.0.location.0,
131 path.0.location.1,
132 path.1.location.0,
133 path.1.location.1,
134 theme.path,
135 ));
136 context.draw(&Points {
137 color: theme.source,
138 coords: &[path.0.location], // sydney
139 });
140 context.draw(&Points {
141 color: theme.destination,
142 coords: &[path.1.location], // perth
143 });
144 }
145 })
146 .render(area, buf);
147}
Sourcepub const fn marker(self, marker: Marker) -> Self
pub const fn marker(self, marker: Marker) -> Self
Change the type of points used to draw the shapes.
By default the Braille
patterns are used as they provide a more fine grained result,
but you might want to use the simple Dot
or Block
instead if the targeted terminal
does not support those symbols.
The HalfBlock
marker is useful when you want to draw shapes with a higher resolution
than with a grid of characters (e.g. with Block
or Dot
) but lower than with
Braille
. This grid type supports a foreground and background color for each terminal
cell. This allows for more flexibility than the BrailleGrid
which only supports a single
foreground color for each 2x4 dots cell.
§Examples
use ratatui::{symbols, widgets::canvas::Canvas};
Canvas::default()
.marker(symbols::Marker::Braille)
.paint(|ctx| {});
Canvas::default()
.marker(symbols::Marker::HalfBlock)
.paint(|ctx| {});
Canvas::default()
.marker(symbols::Marker::Dot)
.paint(|ctx| {});
Canvas::default()
.marker(symbols::Marker::Block)
.paint(|ctx| {});
Examples found in repository?
176 fn map_canvas(&self) -> impl Widget + '_ {
177 Canvas::default()
178 .block(Block::bordered().title("World"))
179 .marker(self.marker)
180 .paint(|ctx| {
181 ctx.draw(&Map {
182 color: Color::Green,
183 resolution: MapResolution::High,
184 });
185 ctx.print(self.x, -self.y, "You are here".yellow());
186 })
187 .x_bounds([-180.0, 180.0])
188 .y_bounds([-90.0, 90.0])
189 }
190
191 fn draw_canvas(&self, area: Rect) -> impl Widget + '_ {
192 Canvas::default()
193 .block(Block::bordered().title("Draw here"))
194 .marker(self.marker)
195 .x_bounds([0.0, f64::from(area.width)])
196 .y_bounds([0.0, f64::from(area.height)])
197 .paint(move |ctx| {
198 let points = self
199 .points
200 .iter()
201 .map(|p| {
202 (
203 f64::from(p.x) - f64::from(area.left()),
204 f64::from(area.bottom()) - f64::from(p.y),
205 )
206 })
207 .collect_vec();
208 ctx.draw(&Points {
209 coords: &points,
210 color: Color::White,
211 });
212 })
213 }
214
215 fn pong_canvas(&self) -> impl Widget + '_ {
216 Canvas::default()
217 .block(Block::bordered().title("Pong"))
218 .marker(self.marker)
219 .paint(|ctx| {
220 ctx.draw(&self.ball);
221 })
222 .x_bounds([10.0, 210.0])
223 .y_bounds([10.0, 110.0])
224 }
225
226 fn boxes_canvas(&self, area: Rect) -> impl Widget {
227 let left = 0.0;
228 let right = f64::from(area.width);
229 let bottom = 0.0;
230 let top = f64::from(area.height).mul_add(2.0, -4.0);
231 Canvas::default()
232 .block(Block::bordered().title("Rects"))
233 .marker(self.marker)
234 .x_bounds([left, right])
235 .y_bounds([bottom, top])
236 .paint(|ctx| {
237 for i in 0..=11 {
238 ctx.draw(&Rectangle {
239 x: f64::from(i * i + 3 * i) / 2.0 + 2.0,
240 y: 2.0,
241 width: f64::from(i),
242 height: f64::from(i),
243 color: Color::Red,
244 });
245 ctx.draw(&Rectangle {
246 x: f64::from(i * i + 3 * i) / 2.0 + 2.0,
247 y: 21.0,
248 width: f64::from(i),
249 height: f64::from(i),
250 color: Color::Blue,
251 });
252 }
253 for i in 0..100 {
254 if i % 10 != 0 {
255 ctx.print(f64::from(i) + 1.0, 0.0, format!("{i}", i = i % 10));
256 }
257 if i % 2 == 0 && i % 10 != 0 {
258 ctx.print(0.0, f64::from(i), format!("{i}", i = i % 10));
259 }
260 }
261 })
262 }
More examples
107fn render_map(selected_row: usize, area: Rect, buf: &mut Buffer) {
108 let theme = THEME.traceroute.map;
109 let path: Option<(&Hop, &Hop)> = HOPS.iter().tuple_windows().nth(selected_row);
110 let map = Map {
111 resolution: MapResolution::High,
112 color: theme.color,
113 };
114 Canvas::default()
115 .background_color(theme.background_color)
116 .block(
117 Block::new()
118 .padding(Padding::new(1, 0, 1, 0))
119 .style(theme.style),
120 )
121 .marker(Marker::HalfBlock)
122 // picked to show Australia for the demo as it's the most interesting part of the map
123 // (and the only part with hops ;))
124 .x_bounds([112.0, 155.0])
125 .y_bounds([-46.0, -11.0])
126 .paint(|context| {
127 context.draw(&map);
128 if let Some(path) = path {
129 context.draw(&canvas::Line::new(
130 path.0.location.0,
131 path.0.location.1,
132 path.1.location.0,
133 path.1.location.1,
134 theme.path,
135 ));
136 context.draw(&Points {
137 color: theme.source,
138 coords: &[path.0.location], // sydney
139 });
140 context.draw(&Points {
141 color: theme.destination,
142 coords: &[path.1.location], // perth
143 });
144 }
145 })
146 .render(area, buf);
147}
Trait Implementations§
Source§impl<F> WidgetRef for Canvas<'_, F>
impl<F> WidgetRef for Canvas<'_, F>
Source§fn render_ref(&self, area: Rect, buf: &mut Buffer)
fn render_ref(&self, area: Rect, buf: &mut Buffer)
unstable-widget-ref
only.impl<'a, F> StructuralPartialEq for Canvas<'a, F>
Auto Trait Implementations§
impl<'a, F> Freeze for Canvas<'a, F>where
F: Freeze,
impl<'a, F> RefUnwindSafe for Canvas<'a, F>where
F: RefUnwindSafe,
impl<'a, F> Send for Canvas<'a, F>where
F: Send,
impl<'a, F> Sync for Canvas<'a, F>where
F: Sync,
impl<'a, F> Unpin for Canvas<'a, F>where
F: Unpin,
impl<'a, F> UnwindSafe for Canvas<'a, F>where
F: UnwindSafe,
Blanket Implementations§
Source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
D: AdaptFrom<S, Swp, Dwp, T>,
impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
D: AdaptFrom<S, Swp, Dwp, T>,
Source§fn adapt_into_using<M>(self, method: M) -> Dwhere
M: TransformMatrix<T>,
fn adapt_into_using<M>(self, method: M) -> Dwhere
M: TransformMatrix<T>,
Source§fn adapt_into(self) -> D
fn adapt_into(self) -> D
Source§impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
Source§fn arrays_from(colors: C) -> T
fn arrays_from(colors: C) -> T
Source§impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
Source§fn arrays_into(self) -> C
fn arrays_into(self) -> C
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
Source§type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
parameters
when converting.Source§fn cam16_into_unclamped(
self,
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> T
fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T
self
into C
, using the provided parameters.Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
Source§fn components_from(colors: C) -> T
fn components_from(colors: C) -> T
Source§impl<T> FromAngle<T> for T
impl<T> FromAngle<T> for T
Source§fn from_angle(angle: T) -> T
fn from_angle(angle: T) -> T
angle
.Source§impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
Source§fn from_stimulus(other: U) -> T
fn from_stimulus(other: U) -> T
other
into Self
, while performing the appropriate scaling,
rounding and clamping.Source§impl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
impl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
Source§fn into_angle(self) -> U
fn into_angle(self) -> U
T
.Source§impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
Source§type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
parameters
when converting.Source§fn into_cam16_unclamped(
self,
parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>,
) -> T
fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T
self
into C
, using the provided parameters.Source§impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
Source§fn into_color(self) -> U
fn into_color(self) -> U
Source§impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
Source§fn into_color_unclamped(self) -> U
fn into_color_unclamped(self) -> U
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoStimulus<T> for T
impl<T> IntoStimulus<T> for T
Source§fn into_stimulus(self) -> T
fn into_stimulus(self) -> T
self
into T
, while performing the appropriate scaling,
rounding and clamping.Source§impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
Source§type Error = <C as TryFromComponents<T>>::Error
type Error = <C as TryFromComponents<T>>::Error
try_into_colors
fails to cast.Source§fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
Source§impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
Source§fn try_into_color(self) -> Result<U, OutOfBounds<U>>
fn try_into_color(self) -> Result<U, OutOfBounds<U>>
OutOfBounds
error is returned which contains
the unclamped color. Read more