You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:12:02