nationtech-website/src/components/background.rs

154 lines
5.5 KiB
Rust

use std::cell::RefCell;
use std::rc::Rc;
use leptos::html::Canvas;
use leptos::*;
use wasm_bindgen::prelude::Closure;
use wasm_bindgen::JsCast;
use wasm_bindgen::JsValue;
use web_sys::window;
use crate::space_colonization::Node;
use crate::space_colonization::Point;
use crate::space_colonization::SpaceColonization;
#[component]
pub fn Background(cx: Scope, class: &'static str) -> impl IntoView {
let canvas = create_node_ref::<Canvas>(cx);
canvas.on_load(cx, move |_| {
let canvas = canvas.get().expect("canvas is mounted");
let canvas_parent = canvas.parent_element().unwrap();
let width = canvas_parent.client_width();
let height = canvas_parent.client_height();
let window_width = u32::try_from(width).unwrap();
let window_height = u32::try_from(height).unwrap();
canvas.set_width(window_width);
canvas.set_height(window_height);
let context = canvas
.get_context("2d")
.ok()
.flatten()
.expect("canvas to have context")
.unchecked_into::<web_sys::CanvasRenderingContext2d>();
log!("context = {:#?}", context);
context.set_stroke_style(&JsValue::from("white"));
let context_to_render = context.clone();
// let render_node_fn : 'a Fn(&Node, &Node) = |n: &Node, child: &Node| {
let render_node_fn = move |n: &Node, child: &Node| {
context_to_render.move_to(n.position.x.into(), n.position.y.into());
context_to_render.line_to(child.position.x.into(), child.position.y.into());
};
let mut sc = SpaceColonization::new(
width.try_into().unwrap(),
height.try_into().unwrap(),
render_node_fn,
);
let nodes = Rc::new(RefCell::new(Vec::new()));
{
let mut nodesMut = nodes.borrow_mut();
nodesMut.push(Node::new(Point::new((
(window_width / 3) as i32,
(window_height / 3) as i32,
))));
nodesMut.push(Node::new(Point::new((
(window_width / 2) as i32,
(window_height / 3) as i32,
))));
nodesMut.push(Node::new(Point::new((
(window_width / 3) as i32,
(window_height / 2) as i32,
))));
nodesMut.push(Node::new(Point::new((
(window_width - 200) as i32,
(window_height / 3) as i32,
))));
nodesMut.push(Node::new(Point::new((
(window_width - 100) as i32,
(window_height - 100) as i32,
))));
}
// TODO Resize on window resize
log!(
"TODO resize on window resize canvas parent size = {} {}",
canvas_parent.client_width(),
canvas_parent.client_height()
);
context.set_stroke_style(&JsValue::from("white"));
context.set_fill_style(&JsValue::from("yellow"));
log!("About to render nodes");
let start_time = window().unwrap().performance().unwrap().now();
context.begin_path();
/*
let render_node_fn = |n: &Node, child: &Node| {
context.move_to(n.position.x.into(), n.position.y.into());
context.line_to(child.position.x.into(), child.position.y.into());
};
*/
// let render_id = window().unwrap().performance().unwrap().now();
// sc.render_all_nodes(&nodes.borrow(), render_id, render_node_fn);
context.stroke();
let end_time = window().unwrap().performance().unwrap().now();
log!(
"Rendering nodes and {} attractors took {}",
sc.attractors.size(),
end_time - start_time
);
let context = context.clone();
let closure = Closure::<dyn FnMut(_)>::new(move |_: web_sys::MouseEvent| {
let start_time = window().unwrap().performance().unwrap().now();
{
let mut nodesMut = nodes.borrow_mut();
sc.grow(&mut nodesMut);
}
// let render_id = window().unwrap().performance().unwrap().now();
// context.begin_path();
// sc.render_nodes(&nodes.borrow(), render_id, render_node_fn);
/*
context.set_fill_style(&JsValue::from("magenta"));
for a in sc.attractors.iter().filter(|a| a.dead) {
context.fill_rect(a.position.x.into(), a.position.y.into(), 5.0, 5.0);
}
context.set_fill_style(&JsValue::from("red"));
for a in sc.attractors.iter().filter(|a| !a.dead) {
context.fill_rect(a.position.x.into(), a.position.y.into(), 5.0, 5.0);
}
*/
context.stroke();
let end_time = window().unwrap().performance().unwrap().now();
log!(
"Rendering nodes and {} attractors took {}",
sc.attractors.size(),
end_time - start_time
);
});
let window = window().unwrap();
window
.set_interval_with_callback_and_timeout_and_arguments_0(
closure.as_ref().unchecked_ref(),
30,
)
.unwrap();
// window
// .add_event_listener_with_callback(
// "click",
// closure.as_ref().unchecked_ref(),
// )
// .unwrap();
closure.forget();
});
let class = format!("canvas {}", class);
view! { cx,
<div class={class}>
<canvas node_ref=canvas></canvas>
</div>
}
}