具有输入范围的 HTML 音频可访问性

Posted

技术标签:

【中文标题】具有输入范围的 HTML 音频可访问性【英文标题】:HTML Audio accessibility with Input Range 【发布时间】:2019-08-18 23:02:17 【问题描述】:

最小问题示例:https://codepen.io/sidouglas/pen/LYPZaOG

当输入范围聚焦时,Chrome Vox 或 Mac 的 Voice over - valuetext 的每个值都会连续读出。

<input
 ...
  v-bind:aria-valuemax="valueMax"
  v-bind:aria-valuenow="valueNow"
  v-bind:aria-valuetext="currentTime + ' of ' + totalDuration"
  ...
/>

将此与非常易于访问的 https://plyr.io/#audio 组件进行对比 - 当聚焦时,它会继续更新其 aria 值,但只会向屏幕阅读器宣布两次。

有人知道 plyr 是怎么做到的吗?

new Vue(
  el: '#range',
  data: 
    valueMax:100,
    duration:100,
    current:0,
    totalDuration:'1:40'
  ,
  computed:
    currentTime: function() 
      return this.convertTime(this.current);
    ,
     valueNow() 
      return Math.round(this.current);
    ,
  ,
  methods: 
    convertTime(time) 
      const minutes = Math.floor(time / 60);
      const seconds = time - (minutes * 60);
      return `$minutes:$seconds.toFixed(0).toString().padStart(2, '0')`;
    ,
  ,
  mounted: function()
   var self = this;
   setInterval(function()
     self.current = Number(self.current) + 1;
     if(self.current >= self.valueMax)
        self.current = 0;
     
    ,2000);
  ,
);
.audio-file-player__slider-range
  border:1px solid red;
  width:100%;


.audio-file-player__slider-range:focus 
  box-shadow: 0 0 10px blue;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="range">
  <input
         aria-label="Seek"
         aria-valuemin="0"
         autocomplete="off"
         class="audio-file-player__slider-range u-color-gray-111111 u-width-100"
         min="0"
         role="slider"
         step="1"
         type="range"
         v-bind:aria-valuemax="valueMax"
         v-bind:aria-valuenow="valueNow"
         v-bind:aria-valuetext="currentTime + ' of ' + totalDuration"
         v-bind:max="duration"
         v-model="current"
         />
  <p>current:  current </p>
  <p>aria-valuenow:  valueNow </p>
  <p>aria-valuetext:  currentTime + ' of ' + totalDuration </p>
</div>

【问题讨论】:

除了it repeats there too,我不知道 plyr 正在做什么。不总是。不知道为什么有时它重复的次数更少。 嗯。我不明白——但你是对的——这不是一次很棒的经历。看来我得用 Vue 卷起袖子了。 【参考方案1】:

对于遇到此问题的任何人,简单的解决方案是使用 aria-valuetext 覆盖该值。

当项目播放时,我会将aria-valuetext 设置为“当前:currentTime,剩余:remainingTime第一次获得焦点

然后在播放项目时不要更新时间(不理会aria-valuetext)。

然后当播放暂停/停止时,再次更改aria-valuetext 以反映当前时间。

最后,当有人使用箭头键进行搜索时,我会以 200 毫秒的速度更新当前时间。

您可以决定是在播放时执行此操作,还是仅在不播放时执行此操作,因为我不确定在信息与中断方面哪个是最佳解决方案。

我倾向于在玩游戏时不更新,因为如果您将其设为可聚焦,用户总是可以切换到当前时间。

通过这样做,您可以确保它不会干扰播放音乐或宣布 200 个不同的时间。

plyr.io 理论 - 一开始我也重复了,然后我改变了我的播报速度设置。我相信有些人这样做而有些人没有收到通知的原因是他们更新当前时间的速度(看起来每秒 3-4 次),我认为这种重复如此之快以至于屏幕阅读器决定不混淆拥有它的用户。只是一个理论,但我最好的猜测,因为他们没有做任何我能看到的聪明事情。

【讨论】:

【参考方案2】:

将您的歌曲路径转换为计算属性,然后获取其 currentTime。如下:

<template>
  <div>
    <h3>Audio Player Test</h3>

    <audio
      ref="myMusic"
      src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"
      @timeupdate="onTimeUpdateListener"
    ></audio>
    currentTime
    <button @click="play">Play</button>
    <button @click="pause">Pause</button>
  </div>
</template>
data() 
    return 
      songCurrent: 0,
      currentTime: "00:00" // The initial current time
    ;
,
computed: 
    song() 
      return this.$refs.myMusic;
    

methods: 
    play() 
      this.song.play();
    ,
    pause() 
      this.song.pause();
    ,
    onTimeUpdateListener: function() 
      // Update current time
      this.currentTime = this.$refs.myMusic.currentTime;
    
  

【讨论】:

以上是关于具有输入范围的 HTML 音频可访问性的主要内容,如果未能解决你的问题,请参考以下文章

可访问性标签 storekit 用户输入

带有可访问性工具的直接输入区域

如何处理 HTML 中可访问性的语义符号?

HTML5:可能有两个输入的滑块?

具有可访问性的 UITableViewCell 中的 UICollectionView

带有角色按钮的锚链接内图像的可访问性:可点击元素必须是可聚焦的并且应该具有交互式语义