Svg Clock
use js_sys as js;
use wasm_bindgen::prelude::*;
struct Clock {
date: js::Date,
}
enum Message {
Tick,
}
impl Clock {
fn new() -> Self {
Clock {
date: js::Date::new_0(),
}
}
}
impl draco::Application for Clock {
type Message = Message;
fn update(&mut self, message: Self::Message, _mailbox: &draco::Mailbox<Self::Message>) {
match message {
Message::Tick => {
self.date = js::Date::new_0();
}
}
}
fn view(&self) -> draco::VNode<Self::Message> {
use draco::{html as h, svg as s};
let circle = s::circle()
.cx("100")
.cy("100")
.r("98")
.fill("none")
.stroke("#1a202c");
let line = |rotate: f64, stroke, stroke_width: u32, height: u32| {
s::line()
.x1("100")
.y1("100")
.x2((100 - height).to_string())
.y2("100")
.stroke(stroke)
.stroke_width(stroke_width.to_string())
.stroke_linecap("round")
.transform(format!(
"rotate({} 100 100)",
(rotate * 10.0).round() / 10.0
))
};
let d = &self.date;
let ms = ((((d.get_hours() * 60 + d.get_minutes()) * 60) + d.get_seconds()) * 1000
+ d.get_milliseconds()) as f64;
let subsecond_rotate = 90.0 + ((ms / 1000.0) % 1.0) * 360.0;
let second_rotate = 90.0 + ((ms / 1000.0) % 60.0) * 360.0 / 60.0;
let minute_rotate = 90.0 + ((ms / 1000.0 / 60.0) % 60.0) * 360.0 / 60.0;
let hour_rotate = 90.0 + ((ms / 1000.0 / 60.0 / 60.0) % 12.0) * 360.0 / 12.0;
h::div()
.attribute(
"style",
"display: flex; align-items: center; flex-direction: column;",
)
.with(
s::svg()
.width("400")
.height("400")
.view_box("0 0 200 200")
.with((
circle,
line(subsecond_rotate, "#e2e8f0", 10, 90),
line(hour_rotate, "#2d3748", 4, 50),
line(minute_rotate, "#2d3748", 3, 70),
line(second_rotate, "#e53e3e", 2, 90),
)),
)
.into()
}
}
#[wasm_bindgen(start)]
pub fn start() {
let mailbox = draco::start(Clock::new(), draco::select("main").expect("<main>").into());
mailbox.subscribe_forever(draco::subscription::AnimationFrame::new(), |_| {
Message::Tick
});
}