用空闲时间做了一个小程序-文字转语音2.0(语音播放进度条)

发布于:2025-03-30 ⋅ 阅读:(33) ⋅ 点赞:(0)

一直在摸鱼中赚钱的大家好呀~

上篇文章讲到了获取语音时长遇到的一些问题和楼主的解决方案,这篇文章就接着上文继续往下实现语音播放进度的解决方案。这篇文章会讲到播放进度条的实现,希望这篇文章可以给更多的鱼友们(没错就是你们)的解决一些开发中遇到的问题或者启发,也希望楼主的小程序有更多的鱼友加入。

接上篇文章,先来看下知名UI设计师设计的UI图。

在这里插入图片描述
在这里插入图片描述

既然要实现语音的播放进度,那在整个过程中我们需要记录这么几个信息:

  • 语音时长 (上篇文章已经获取)
  • 语音是否正在播放
  • 语音当前播放的位置

在官方文档中有几个监听事件:onPlay: 监听音频播放事件。
onPause: 监听音频暂停事件。
onStop: 监听音频停止事件。

他会在调用了play,触发onPlay监听事件,在这个事件中变更播放的状态。同样也要在触发onPauseonStop这两个监听事件的时候变更播放的状态。

在官方文档中有一个监听事件:onTimeUpdate: 监听音频播放进度更新事件。他会在音频播放的过程中不断的触发,我们可以在这个事件中调用audio.currentTime获取到当前音频播放的位置。

这些都比较简单,贴下部分实现代码:

const { url } = this.data.info
const audio = wx.createInnerAudioContext('audio')
audio.src = url
audio.onCanplay(() => {
    audio.duration;
    setTimeout(() => {
      const duration = audio.duration
      this.setData({ duration, durationText: Math.ceil(duration) + 's' })
    }, 10000)
})
audio.onPlay(() => this.setData({ playing: true }))
audio.onTimeUpdate(() => this.setData({ currentTime: audio.currentTime }))
const stop = () => {
    this.setData({ currentTime: audio.duration })
    setTimeout(() => {
      this.setData({ playing: false, currentTime: 0 })
    }, 300)
}
audio.onPause(() => this.setData({ playing: false}))
audio.onEnded(stop)
audio.onStop(stop)
audio.onError(() => {
    this.setData({ status: 0 })
    wx.showToast({ title: '语音已失效!', icon: 'none', duration: 3000})
})
this.setData({ audio })

第二个难点:播放进度条的实现
在这里插入图片描述

先将一些简单的工作完成,先画个容器,容器里面将竖线按照从大到小都绘制完成:

<view class="audio flex-item_f-1 flex flex_a_i--center">
    <image class="listen-image" src="/images/{{ playing ? 'stop' : 'play' }}.png" mode="aspectFill" bind:tap="listenHandle"></image>
    <view class="progress-wrap flex-item_f-1 ">
      <view class="height-full flex flex_a_i--center">
        <view class="stage flex_s-0" wx:for="{{42}}" wx:key="item" style="height: {{ 100 - item % 4 * 25 + '%'}}"></view>
      </view>
    </view>
</view>

通过flex布局将竖线并排显示,超出的部分隐藏。基本工作是做完了现在的难点是如何能让这些竖线按照所在位置的百分比进行变色呢?可以通过JS计算宽度等方式计算出要添加颜色的位置,但是这太麻烦了,不是我想要的方法。有没有不通过JS的实现方式呢?那肯定有,下面来讲一下我的实现思路。

CSS中有一个clip-path属性: 使用裁剪方式创建元素的可显示区域。配置polygon来计算显示的区域。那我们需要一组相同的带颜色的竖线覆盖在原来的竖线上,我们只要从左往右按照播放进度的百分比 (当前播放时间除以音频时长) 对有颜色的竖线进行显示即可,。贴一下我的实现代码:

<view class="audio flex-item_f-1 flex flex_a_i--center">
    <image class="listen-image" src="/images/{{ playing ? 'stop' : 'play' }}.png" mode="aspectFill" bind:tap="listenHandle"></image>
    <view class="progress-wrap flex-item_f-1 ">
    <view class="height-full flex flex_a_i--center">
        <view class="stage flex_s-0" wx:for="{{42}}" wx:key="item" style="height: {{ 100 - item % 4 * 25 + '%'}}"></view>
    </view>
    <view class="clip-wrap flex flex_a_i--center" style="clip-path: polygon(0 0, 0 100%, {{ currentTime / duration * 100 + '%' }} 100%, {{ currentTime / duration * 100 + '%' }} 0);">
        <view class="stage flex_s-0" wx:for="{{42}}" wx:key="item" style="height: {{ 100 - item % 4 * 25 + '%'}};"></view>
        </view>
    </view>
</view>

目前小程序还在审核中,审核通过之后即可体验语音分享功能。如果大家还有好的实现方式可以在评论区一起探讨!

感谢大家观看我今日的水文,文笔实在是不行,欢迎鱼友们给小程序提提意见,或者有什么有趣的想法也可以与楼主提一提。最后希望大家到我的小程序来多坐坐。

感谢看官看到这里,如果觉得文章不错的话,可以给小生的几个开源项目点个Star⭐!