Leveraging JS from Yew to animate component #2136
Replies: 5 comments
-
I forgot to mention, here's my Cargo: # ...
[dependencies]
anyhow = "1"
console_error_panic_hook = "0.1.6"
wasm-bindgen = "=0.2.74"
wee_alloc = "0.4.5"
ybc = "0.2"
yew = "0.18" |
Beta Was this translation helpful? Give feedback.
-
So I made another @voidpumpkin, by creating a separate Component, e.g. :
use yew::{html, Callback, Component, ComponentLink, MouseEvent, Properties};
use wasm_bindgen::prelude::*;
#[derive(Debug, Properties, Clone, PartialEq)]
pub struct Props {
pub id: String,
#[prop_or_default]
pub label: String,
#[prop_or_default]
pub callback: Callback<MouseEvent>,
}
pub struct Button {
props: Props,
link: ComponentLink<Self>,
animation: Option<Animate>,
}
pub enum Msg {
OnMouseEnter,
OnMouseLeave,
}
impl Component for Button {
type Message = Msg;
type Properties = Props;
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
Self {
props,
link,
animation: None,
}
}
fn update(&mut self, msg: Self::Message) -> yew::ShouldRender {
match msg {
Msg::OnMouseEnter => {
if self.animation.is_none() {
self.animation = Some(Animate::new(String::from("fetch-button")));
}
self.animation.as_ref().unwrap().enter();
true
}
Msg::OnMouseLeave => {
self.animation.as_ref().unwrap().leave();
true
}
}
}
fn change(&mut self, props: Self::Properties) -> yew::ShouldRender {
if self.props != props {
self.props = props;
true
} else {
false
}
}
fn view(&self) -> yew::Html {
let onclick = &self.props.callback;
let onmouseenter = self.link.callback(|_| Msg::OnMouseEnter);
let onmouseleave = self.link.callback(|_| Msg::OnMouseLeave);
html! {
<button
id={self.props.id.clone()}
onclick=onclick
onmouseenter=onmouseenter
onmouseleave=onmouseleave>{ &self.props.label }</button>
}
}
fn destroy(&mut self) {
js_log("on destroy".into());
self.animation.as_ref().unwrap().destroy();
self.animation = None;
}
}
#[wasm_bindgen(module = "/src/animations.js")]
extern "C" {
type Animate;
#[wasm_bindgen(constructor)]
fn new(id: String) -> Animate;
#[wasm_bindgen(method)]
fn enter(this: &Animate);
#[wasm_bindgen(method)]
fn leave(this: &Animate);
#[wasm_bindgen(method)]
fn destroy(this: &Animate);
}
impl std::fmt::Debug for Animate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Animate").field("obj", &self.obj).finish()
}
}
#[wasm_bindgen(inline_js = "export function js_log(message) { console.log(message); }")]
extern "C" {
fn js_log(message: String);
}
export class Animate {
constructor(id) {
this._id = id
this._tween = TweenMax.to(`#${id}`, .3, { css:{ "filter": "drop-shadow(0 0 0.75rem black)"} })
this._tween.pause()
}
enter() {
console.log("on mouse enter")
this._tween.play()
}
leave() {
console.log("on mouse leave")
this._tween.reverse()
}
destroy() {
console.log("on JS destroy")
gsap.killTweensOf(`#${this._id}`)
this._tween = undefined
this._id = undefined
}
} and then use it somewhere in the code, e.g.: impl Component for Widget {
// ...
fn view(&self) -> yew::Html {
let onclick = self.link.callback(|_| Msg::List);
html! {
<super::button::Button
id="fetch-button"
callback=onclick
label={self.props.title.clone()}
/>
}
}
} |
Beta Was this translation helpful? Give feedback.
-
If somebody know how to track potential memory leaks in Chrome developer tool, I'd interested to try. |
Beta Was this translation helpful? Give feedback.
-
Alright there's actually no need for a trick in if self.animation.is_none() {
self.animation = Some(Animate::new(String::from("fetch-button")));
}
I'm very new to Yew so what I should have done is: fn rendered(&mut self, first_render: bool) {
if first_render {
self.animation = Some(Animate::new(self.props.id.clone()));
}
} 👌 |
Beta Was this translation helpful? Give feedback.
-
pog bro thx sm |
Beta Was this translation helpful? Give feedback.
-
Ok so here is a quick and dirty sample on how to leverage JS to animate your component.
Component
trait and drive JS animation from Rust:fn view(...)
you conditionally returns differenthtml
, then you will need to manually clean your references on JS side: once again, you can expose the appropriate JS method from Rust e.g. :Here's a small video:
js-rust-animations.mov
Have fun 🎉
Beta Was this translation helpful? Give feedback.
All reactions