如何用web-sys和js-sys复刻JS鼠标跟随对象动画?
鼠标跟随动画的Rust复刻实现指南
原JavaScript参考代码
window.onpointermove = event => { const { clientX, clientY } = event; blob.animate({ left: `${clientX}px`, top: `${clientY}px` }, { duration: 3000, fill: "forwards" }); }
问题分析
你当前的Rust代码存在两个核心问题:
- 错误地用字符串构造关键帧对象:
JsValue::from_str生成的是字符串而非JS对象,不符合KeyframeEffect的参数要求 - 对动画配置的理解有误:时长(duration)和填充模式(fill)是
KeyframeEffect的属性,而非依赖AnimationTimeline
正确实现示例
use web_sys::{MouseEvent, Element, KeyframeEffect, Animation}; use js_sys::{Object, Reflect}; fn animate_blob_to_follow_mouse(event: MouseEvent, blob: Element) { let client_x = event.client_x(); let client_y = event.client_y(); // 构造单个关键帧对象(对应JS中的{left: 'xpx', top: 'ypx'}) let keyframe = Object::new(); Reflect::set(&keyframe, &"left".into(), &format!("{}px", client_x).into()).unwrap(); Reflect::set(&keyframe, &"top".into(), &format!("{}px", client_y).into()).unwrap(); // 将关键帧放入数组 let keyframes = js_sys::Array::new(); keyframes.push(&keyframe); // 构造动画配置选项对象 let effect_options = Object::new(); Reflect::set(&effect_options, &"duration".into(), &3000.into()).unwrap(); Reflect::set(&effect_options, &"fill".into(), &"forwards".into()).unwrap(); // 创建KeyframeEffect let effect = KeyframeEffect::new_with_opt_element_and_keyframes_and_options( Some(&blob), Some(keyframes.as_ref()), Some(&effect_options) ).unwrap(); // 取消旧动画避免叠加,再播放新动画 if let Some(existing_anim) = blob.get_animation() { existing_anim.cancel().unwrap(); } let animation = Animation::new_with_effect_and_timeline(Some(&effect), None).unwrap(); animation.play().unwrap(); }
关键修正说明
- 使用
js_sys::Object配合Reflect::set构建标准JS对象,替代字符串转义的错误方式,满足KeyframeEffect的参数类型要求 - 通过
KeyframeEffect的第三个参数传入配置对象,直接设置duration和fill,和原JavaScript逻辑完全对齐 - 添加旧动画取消逻辑,防止鼠标频繁移动时多个动画叠加导致的行为异常
内容的提问来源于stack exchange,提问作者financial_physician
相关产品推荐
相关产品推荐

