Vaadin中捕获audio标签timeupdate事件并获取currentTime的问题
问题原因与解决方案
问题核心
你自定义的Vaadin Audio组件能捕获timeupdate事件,但拿不到播放当前时间,原因是:
currentTime是DOM元素的JS属性(property),而非HTML标签属性(attribute),Vaadin不会自动同步这类动态属性到服务端,所以getAttribute("currentTime")肯定拿不到值。- 单独用
executeJs能拿到值,但它是异步操作,没法在事件监听器的构造方法里同步获取结果。
解决方法
让客户端在触发timeupdate事件时,直接把currentTime作为参数传给服务端,不用再从元素上读取。具体修改如下:
1. 修改事件注解,指定传递参数
在TimeUpdateEvent的@DomEvent注解里添加detail配置,告诉Vaadin客户端要把currentTime打包进事件详情。
2. 在事件构造方法中接收参数
用@EventData注解直接注入传递过来的currentTime值,无需再手动读取元素属性。
3. 修正stop方法(可选)
原生audio元素没有stop()方法,改用pause()+重置currentTime到0来实现停止功能。
修改后的完整代码
@Tag("audio") public class Audio extends Component implements HasSize { private static final long serialVersionUID = 1L; private static final PropertyDescriptor<String, String> srcDescriptor = PropertyDescriptors .attributeWithDefault("src", ""); public Audio() { super(); getElement().setProperty("controls", true); } public Audio(String src) { setSrc(src); getElement().setProperty("controls", true); } public String getSrc() { return get(srcDescriptor); } public void setSrc(String src) { set(srcDescriptor, src); } public void setSrc(final AbstractStreamResource resource) { getElement().setAttribute("src", resource); } public void play() { getElement().callJsFunction("play"); } public void stop() { // 原生audio无stop方法,改用暂停+重置播放进度 getElement().callJsFunction("pause"); getElement().setProperty("currentTime", 0); } // 配置DomEvent,让客户端传递currentTime作为事件详情 @DomEvent(value = "timeupdate", detail = "event.target.currentTime") public static class TimeUpdateEvent extends ComponentEvent<Audio> { private final double progress; // 通过@EventData接收客户端传来的currentTime public TimeUpdateEvent(Audio audio, boolean fromClient, @EventData("event.detail") double currentTime) { super(audio, fromClient); this.progress = currentTime; } public Audio getAudio() { return (Audio) this.source; } public double getProgress() { return this.progress; } } public Registration addTimeUpdateListener(ComponentEventListener<Audio.TimeUpdateEvent> listener) { return addListener(Audio.TimeUpdateEvent.class, listener); } }
关键说明
@DomEvent的detail参数:用JS表达式event.target.currentTime获取当前播放时间,Vaadin会自动把这个值作为event.detail发送到服务端。@EventData("event.detail"):直接从事件详情中取出传递过来的时间值,同步获取,不需要异步操作。- 停止功能修正:贴合原生audio API的实现逻辑,避免调用不存在的
stop()方法导致报错。
内容的提问来源于stack exchange,提问作者padmalcom
相关产品推荐
相关产品推荐

