1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
use super::drawable::Drawable; use super::image::Image; use wasm_bindgen::{JsCast, JsValue}; /// A Canvas is an object on which you can draw. /// Only the main Canvas is displayed (returned by Window::init()). /// /// # Example /// /// ```rust /// use wasm_game_lib::graphics::window::Window; /// use wasm_game_lib::graphics::image::Image; /// use wasm_game_lib::graphics::sprite::Sprite; /// use wasm_game_lib::system::sleep; /// use std::time::Duration; /// /// # async fn test() { /// // Create a sprite to demonstrate how to draw a sprite on the canvas /// let texture = Image::load("https://www.gravatar.com/avatar/419218774d04a581476ea1887a0921e0?s=128&d=identicon&r=PG").await.unwrap(); /// let sprite = Sprite::<u32>::new((0,0), &texture, (150, 150)); /// /// // create the main canvas /// let (window, mut canvas) = Window::init(); /// /// loop { /// canvas.clear(); // clear the canvas at each iteration /// canvas.draw(&sprite); // draw a sprite on the canvas /// // note that canvas.display() is not needed unlike a lot of graphics libraries /// /// // you may want to slow down the loop to keep your game at 60fps /// sleep(Duration::from_millis(16)).await; /// } /// # } /// ``` pub struct Canvas { pub(crate) context: web_sys::CanvasRenderingContext2d, pub(crate) element: web_sys::HtmlCanvasElement } impl Canvas { /// Create a canvas which will not be displayed. /// To create a displayed canvas, see [Window::init()](../window/struct.Window.html#method.init). /// Creating a undisplayed canvas can be useful because a canvas is drawable on another canvas. pub fn new() -> Canvas { let document = web_sys::window().unwrap().document().unwrap(); let element = document .create_element("canvas") .unwrap() .dyn_into::<web_sys::HtmlCanvasElement>() .unwrap(); let context = element .get_context("2d") .unwrap() .unwrap() .dyn_into::<web_sys::CanvasRenderingContext2d>() .unwrap(); Canvas { context, element } } /// Fill a part of the canvas with a color. /// /// Example valid values for the color parameter: /// - "blue", /// - "#241F45", /// - "#aaa" pub fn fill_rect(&mut self, (x, y): (f64, f64), (w, h): (f64, f64), color: &str) { self.context.set_fill_style(&JsValue::from_str(color)); self.context.fill_rect(x, y, w, h); } /// Clear a part of the canvas. pub fn clear_rect(&mut self, (x, y): (f64, f64), (w, h): (f64, f64)) { self.context.clear_rect(x, y, w, h); } /// Clear all the canvas with a transparent black (white). pub fn clear(&mut self) { self.clear_rect( (0.0, 0.0), ( f64::from(self.element.width()), f64::from(self.element.height()), ), ) } /// Clear all the canvas with a visible black. pub fn clear_black(&mut self) { self.fill_rect( (0.0, 0.0), ( f64::from(self.element.width()), f64::from(self.element.height()), ), "black" ); } /// Draw an object implementing the [Drawable trait](../drawable/trait.Drawable.html) on the canvas. /// /// # Example /// /// ```rust /// # use wasm_game_lib::graphics::window::Window; /// # use wasm_game_lib::graphics::image::Image; /// # use wasm_game_lib::graphics::sprite::Sprite; /// # use wasm_game_lib::system::sleep; /// # use std::time::Duration; /// # async fn test() { /// // create a sprite to draw it on the canvas /// let texture = Image::load("https://www.gravatar.com/avatar/419218774d04a581476ea1887a0921e0?s=128&d=identicon&r=PG").await.unwrap(); /// let sprite = Sprite::<u32>::new((0,0), &texture, (150, 150)); /// /// // create the main canvas /// let (window, mut canvas) = Window::init(); /// /// // draw the sprite on the canvas /// canvas.draw(&sprite); /// # } /// ``` /// /// See above for a more complete example. pub fn draw(&mut self, object: &impl Drawable) { object.draw_on_canvas(self); } /// Return the width and the height of a canvas. pub fn get_size(&self) -> (usize, usize) { unimplemented!() } /// Draw an image at a specific position. /// This method is intended to be used inside the [Drawable trait](../drawable/trait.Drawable.html). /// In the main code of your game, you should use a [Sprite](../sprite/struct.Sprite.html) and the [draw](#method.draw) method. pub fn draw_image(&mut self, (x, y): (f64, f64), image: &Image) { self.context .draw_image_with_html_image_element( image.get_html_element(), x, y, ) .unwrap(); } /// Draw a canvas at a specific position. pub fn draw_canvas(&mut self, (x, y): (f64, f64), canvas: &Canvas) { self.context .draw_image_with_html_canvas_element( &canvas.element, x, y, ) .unwrap(); } /// Print text on the canvas. /// The [Text](../text/struct.Text.html) struct is a better way to print text. pub fn fill_text(&mut self, (x, y): (usize, usize), text: &str, max_width: Option<usize>) { if let Some(max_width) = max_width { self.context.fill_text_with_max_width(text, x as f64, y as f64, max_width as f64).unwrap(); } else { self.context.fill_text(text, x as f64, y as f64).unwrap(); } } /// Set the canvas width in pixels pub fn set_width(&mut self, width: u32) { self.element.set_width(width); } /// Set the canvas height in pixels pub fn set_height(&mut self, height: u32) { self.element.set_height(height); } /// Return the actual canvas width in pixels pub fn get_width(&self) -> u32 { self.element.width() } /// Return the actual canvas height in pixels pub fn get_height(&self) -> u32 { self.element.height() } }