mod private
{
use crate::*;
use crate::web::*;
pub use web_sys::
{
Element,
HtmlCanvasElement,
wasm_bindgen::
{
JsCast,
closure::Closure,
},
};
pub use dom::Error;
pub fn retrieve() -> Result< HtmlCanvasElement, Error >
{
let window = web_sys::window().ok_or( Error::CanvasRetrievingError( "Failed to get window" ) )?;
let document = window.document().ok_or( Error::CanvasRetrievingError( "Failed to get document" ) )?;
if let Some( canvas ) = document.get_element_by_id( "canvas" )
{
return canvas.dyn_into::< HtmlCanvasElement >().map_err( |_| Error::CanvasRetrievingError( "DOM Element with id `canvas` exist, but it's not canvas" ) );
}
if let Some( canvas ) = document.get_elements_by_class_name( "canvas" ).item( 0 )
{
return canvas.dyn_into::< HtmlCanvasElement >().map_err( |_| Error::CanvasRetrievingError( "DOM Element with class `canvas` exist, but it's not canvas" ) );
}
return Err( Error::CanvasRetrievingError( "Canvas was not found" ) )
}
pub fn make() -> Result< HtmlCanvasElement, Error >
{
let window = web_sys::window().ok_or( Error::CanvasRetrievingError( "Failed to get window" ) )?;
let document = window.document().ok_or( Error::CanvasRetrievingError( "Failed to get document" ) )?;
let canvas = document.create_element( "canvas" ).map_err( |_| Error::CanvasRetrievingError( "Failed to create a new canvas" ) )?;
let canvas : HtmlCanvasElement = canvas.dyn_into().map_err( |_| Error::CanvasRetrievingError( "Failed to create a new canvas" ) )?;
canvas.class_list().add_1( "canvas" ).map_err( |_| Error::CanvasRetrievingError( "Failed to assign a class to the canvas" ) )?;
document.body()
.ok_or( Error::CanvasRetrievingError( "Failed to get body of the document" ) )?
.append_child( &canvas )
.map_err( |_| Error::CanvasRetrievingError( "Failed to append canvas to the document" ) )?;
canvas.style().set_property( "width", "100%" ).map_err( |_| Error::CanvasRetrievingError( "Failed to set css width of canvas" ) )?;
canvas.style().set_property( "height", "100%" ).map_err( |_| Error::CanvasRetrievingError( "Failed to set css height of canvas" ) )?;
canvas.style().set_property( "display", "block" ).map_err( |_| Error::CanvasRetrievingError( "Failed to set css display of canvas" ) )?;
if let Some( parent ) = canvas.parent_element()
{
resize_canvas( &canvas, &parent );
let _canvas = canvas.clone();
let closure = Closure::wrap( Box::new( move ||
{
resize_canvas( &_canvas, &parent );
}) as Box< dyn Fn() > );
window
.add_event_listener_with_callback( "resize", closure.as_ref().unchecked_ref() )
.map_err( | e | Error::BindgenError( "Cant bind resize", format!( "{:?}", e ) ) )?;
closure.forget();
}
else
{
web_sys::console::log_1( &"Canvas has no parent, skipping resize.".into() );
}
Ok( canvas )
}
pub fn retrieve_or_make() -> Result< HtmlCanvasElement, Error >
{
if let Ok( canvas ) = retrieve()
{
return Ok( canvas );
}
make()
}
fn resize_canvas( canvas: &HtmlCanvasElement, parent: &Element )
{
let width = parent.client_width() as u32;
let height = parent.client_height() as u32;
canvas.set_width( width );
canvas.set_height( height );
}
pub fn remove_dpr_scaling( canvas: &HtmlCanvasElement )
{
let width = canvas.width();
let height = canvas.height();
let dpr = web_sys::window().expect( "Should have a window" ).device_pixel_ratio();
let css_width = format!( "{}px", width as f64 / dpr );
let css_height = format!( "{}px", height as f64 / dpr );
canvas.style().set_property( "width", &css_width ).unwrap();
canvas.style().set_property( "height", &css_height ).unwrap();
}
}
crate::mod_interface!
{
own use
{
Error,
HtmlCanvasElement,
retrieve,
make,
retrieve_or_make,
remove_dpr_scaling
};
}