@94ai/nf-audio 3.1.37 → 3.1.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/nf-audio.cjs.js +73 -981
- package/lib/nf-audio.esm-bundler.js +70 -978
- package/lib/volume-tool.vue.d.ts +2 -2
- package/package/index.ts +8 -0
- package/package/more-btn.vue +43 -0
- package/package/nf-audio.vue +287 -0
- package/package/style/css.ts +1 -0
- package/package/style/index.ts +1 -0
- package/package/volume-tool.vue +52 -0
- package/package.json +3 -3
package/lib/volume-tool.vue.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{}, {
|
|
1
|
+
declare const _default: __VLS_WithTemplateSlots<import("vue-demi").DefineComponent<{}, {
|
|
2
2
|
showPopper: typeof showPopper;
|
|
3
3
|
$props: {
|
|
4
4
|
readonly visible?: string | boolean | undefined;
|
|
5
5
|
};
|
|
6
6
|
$emit: (event: "update:visible", ...args: any[]) => void;
|
|
7
|
-
}, {}, {}, {}, import("vue/types/v3-component-options").ComponentOptionsMixin, import("vue/types/v3-component-options").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>, {
|
|
7
|
+
}, {}, {}, {}, import("vue/types/v3-component-options").ComponentOptionsMixin, import("vue/types/v3-component-options").ComponentOptionsMixin, {}, string, Readonly<import("vue-demi").ExtractPropTypes<{}>>, {}>, {
|
|
8
8
|
reference?(_: {}): any;
|
|
9
9
|
default?(_: {}): any;
|
|
10
10
|
}>;
|
package/package/index.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="more-btn-box">
|
|
3
|
+
<el-popover placement="right" popper-class="audio-popover">
|
|
4
|
+
<div class="audio-btn-list">
|
|
5
|
+
<el-popover placement="right" popper-class="audio-popover">
|
|
6
|
+
<div class="audio-btn-list">
|
|
7
|
+
<div v-for="(item,index) in multipleArray" :key="index" class="btn-item" :class="speed===item?'active':''" @click="handleSpeed(item)">x {{ item }}</div>
|
|
8
|
+
</div>
|
|
9
|
+
<div slot="reference" class="btn-item">倍速</div>
|
|
10
|
+
</el-popover>
|
|
11
|
+
<div class="btn-item" @click="handleDown">下载</div>
|
|
12
|
+
</div>
|
|
13
|
+
<div slot="reference" class="more-icon">
|
|
14
|
+
<span class="more-btn"></span>
|
|
15
|
+
</div>
|
|
16
|
+
</el-popover>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script>
|
|
21
|
+
export default {
|
|
22
|
+
name: 'more-btn',
|
|
23
|
+
components: {},
|
|
24
|
+
data() {
|
|
25
|
+
return {
|
|
26
|
+
multipleArray: ['1.0', '1.25', '1.5', '1.75', '2.0'],
|
|
27
|
+
speed: ''
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
mounted() {
|
|
31
|
+
},
|
|
32
|
+
methods: {
|
|
33
|
+
handleDown() {
|
|
34
|
+
this.$emit('down')
|
|
35
|
+
},
|
|
36
|
+
handleSpeed(speed) {
|
|
37
|
+
this.speed = speed
|
|
38
|
+
this.$emit('speed', speed)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
</script>
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="nf-audio-strip">
|
|
3
|
+
<audio @canplay="getDuration" controls crossOrigin="anonymous" @timeupdate="updateTime" @ended="handleAudioEnded" v-show="false" ref="audio"
|
|
4
|
+
:src="audioSrc"/>
|
|
5
|
+
<div class="nf-fast">
|
|
6
|
+
<span class="nf-fast-icon" @click="jumpToTime"></span>
|
|
7
|
+
<!-- 以下是 快进/快退 功能 -->
|
|
8
|
+
<!--
|
|
9
|
+
<div>
|
|
10
|
+
<span class="pre" @click="handleBack">
|
|
11
|
+
<i class="el-icon-d-arrow-left"></i>
|
|
12
|
+
<span style="color: #C7C7C9;font-size: 13px;margin-left: 10px">-{{ backSecond }}s</span>
|
|
13
|
+
</span>
|
|
14
|
+
<span style="display:inline-block; height: 20px; width: 100px;"></span>
|
|
15
|
+
<span class="next" @click="handleForward">
|
|
16
|
+
<span style="color: #C7C7C9;font-size: 13px;margin-right: 10px">+{{ forwardSecond }}s </span>
|
|
17
|
+
<i class="el-icon-d-arrow-right"></i>
|
|
18
|
+
</span>
|
|
19
|
+
</div>
|
|
20
|
+
-->
|
|
21
|
+
</div>
|
|
22
|
+
<div class="nf-audio">
|
|
23
|
+
<div class="play" @click="handlePauseOrPlay">
|
|
24
|
+
<span class="pause-icon" v-show="!paused"></span>
|
|
25
|
+
<span class="play-icon" v-show="paused"></span>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="time">
|
|
28
|
+
<span class="startTime">{{ currentDuration }}</span>/
|
|
29
|
+
<span class="endTime">{{ duration }}</span>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="progress" ref="progress" @click="clickProgress" @mouseup="handleMouseup">
|
|
32
|
+
<div class="currentProgress" ref="currentProgress">
|
|
33
|
+
<span class="circle" ref="circle" @mousedown="handleMousedown"></span>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
<div class="nf-volume-panel">
|
|
37
|
+
<volumeTool :visible.sync="volumeVisible">
|
|
38
|
+
<template v-slot:reference>
|
|
39
|
+
<div class="volume" v-if="volume == 0"></div>
|
|
40
|
+
<div class="volume-mute" v-else></div>
|
|
41
|
+
</template>
|
|
42
|
+
<el-slider
|
|
43
|
+
v-model="volumeValue"
|
|
44
|
+
vertical
|
|
45
|
+
:min="0"
|
|
46
|
+
:max="100"
|
|
47
|
+
:show-tooltip="volumeVisible"
|
|
48
|
+
:class="volumeValue===0 ? 'volume-mute' : 'volume-phonic'"
|
|
49
|
+
@change="rangeVolume"
|
|
50
|
+
height="60px">
|
|
51
|
+
</el-slider>
|
|
52
|
+
</volumeTool>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="option">
|
|
55
|
+
<moreBtn @down="downRecord()" @speed="changeSpeed" />
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</template>
|
|
60
|
+
|
|
61
|
+
<script>
|
|
62
|
+
import volumeTool from './volume-tool.vue'
|
|
63
|
+
import moreBtn from './more-btn.vue'
|
|
64
|
+
import { Message } from 'element-ui'
|
|
65
|
+
|
|
66
|
+
export default {
|
|
67
|
+
name: "nf-audio",
|
|
68
|
+
components: { volumeTool, moreBtn },
|
|
69
|
+
props: {
|
|
70
|
+
audioSrc: {
|
|
71
|
+
type: String,
|
|
72
|
+
default: ''
|
|
73
|
+
},
|
|
74
|
+
backSecond: {
|
|
75
|
+
type: Number,
|
|
76
|
+
default: 3
|
|
77
|
+
},
|
|
78
|
+
forwardSecond: {
|
|
79
|
+
type: Number,
|
|
80
|
+
default: 10
|
|
81
|
+
},
|
|
82
|
+
startTime: {
|
|
83
|
+
type: Number,
|
|
84
|
+
default: 0
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
data() {
|
|
88
|
+
return {
|
|
89
|
+
duration: '00:00',
|
|
90
|
+
currentDuration: '00:00',
|
|
91
|
+
audio: '',
|
|
92
|
+
volume: 0.8,
|
|
93
|
+
paused: true,
|
|
94
|
+
showVolumePanel: false,
|
|
95
|
+
volumeVisible: false,
|
|
96
|
+
volumeValue: 80,
|
|
97
|
+
speed: 1.0
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
mounted() {
|
|
101
|
+
this.audio = this.$refs.audio
|
|
102
|
+
},
|
|
103
|
+
methods: {
|
|
104
|
+
//后退
|
|
105
|
+
handleBack() {
|
|
106
|
+
if (this.audio.currentTime > this.backSecond) {
|
|
107
|
+
this.audio.currentTime = this.audio.currentTime - this.backSecond
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
//前进
|
|
111
|
+
handleForward() {
|
|
112
|
+
if (this.audio.duration - this.audio.currentTime > this.forwardSecond) {
|
|
113
|
+
this.audio.currentTime = this.audio.currentTime + 10
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
//暂停或播放
|
|
117
|
+
handlePauseOrPlay() {
|
|
118
|
+
if (this.audio.readyState >= 2) {
|
|
119
|
+
// 如果音频资源已加载元数据或更多,可以播放
|
|
120
|
+
this.audio.paused ? this.audio.play() : this.audio.pause()
|
|
121
|
+
this.audio.playbackRate = this.speed
|
|
122
|
+
this.paused = !this.paused
|
|
123
|
+
console.log(this.paused);
|
|
124
|
+
} else {
|
|
125
|
+
console.log("Audio is not ready yet.");
|
|
126
|
+
Message.warning("音频还未加载完成")
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
//视频在可以播放时触发
|
|
130
|
+
getDuration() {
|
|
131
|
+
this.duration = this.timeFormat(this.$refs.audio.duration)
|
|
132
|
+
this.audio.volume = this.volume //默认百分百音量
|
|
133
|
+
//监听音量的变化
|
|
134
|
+
// this.audio.addEventListener('volumechange',(volumeValue)=>{
|
|
135
|
+
// console.log(this.audio.volume)
|
|
136
|
+
// })
|
|
137
|
+
},
|
|
138
|
+
//将单位为秒的的时间转换成mm:ss的形式
|
|
139
|
+
timeFormat( number ) {
|
|
140
|
+
let minute = parseInt(number / 60);
|
|
141
|
+
let second = parseInt(number % 60);
|
|
142
|
+
minute = minute >= 10 ? minute : "0" + minute;
|
|
143
|
+
second = second >= 10 ? second : "0" + second;
|
|
144
|
+
return minute + ":" + second;
|
|
145
|
+
},
|
|
146
|
+
//进度条发生变化时触发
|
|
147
|
+
updateTime() {
|
|
148
|
+
if (!this.$refs.progress) return
|
|
149
|
+
this.currentDuration = this.timeFormat(this.audio.currentTime)
|
|
150
|
+
//如果不是正在移动 和 没有暂停播放就执行
|
|
151
|
+
if ( !this.audio.paused) {
|
|
152
|
+
// 设置当前时间
|
|
153
|
+
let MoveX = this.$refs.progress.clientWidth * ( this.audio.currentTime / this.audio.duration )
|
|
154
|
+
//播放时更新距离
|
|
155
|
+
this.$refs.currentProgress.style.width = MoveX + 'px'
|
|
156
|
+
this.$refs.circle.style.left = MoveX - ( this.$refs.circle.clientWidth / 2 ) + 'px'
|
|
157
|
+
this.paused = false
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
handleAudioEnded(){
|
|
161
|
+
// 在这里处理音频播放完毕的逻辑
|
|
162
|
+
console.log('音频播放完毕!');
|
|
163
|
+
this.paused = true
|
|
164
|
+
},
|
|
165
|
+
//点击进度条更新进度
|
|
166
|
+
clickProgress( e ) {
|
|
167
|
+
if(this.duration === '00:00'){
|
|
168
|
+
Message.warning("音频还未加载完成")
|
|
169
|
+
return false
|
|
170
|
+
}
|
|
171
|
+
//如果不是正在移动 和 没有暂停播放就执行
|
|
172
|
+
if (!this.audio.paused) {
|
|
173
|
+
this.updateProgress(e.offsetX)
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
//更新进度
|
|
177
|
+
updateProgress( MoveX ) {
|
|
178
|
+
//当前移动的位置 = 当前移动的位置 / 当前进度条的可视长度 //this.$refs.progress.clientWidth 注意一定要拿总长度 否则会拿进度条已经走过的长度
|
|
179
|
+
let clickProgress = ( MoveX / this.$refs.progress.clientWidth )
|
|
180
|
+
//设置播放的时间 = 总时长 * 当前点击的长度
|
|
181
|
+
this.audio.currentTime = this.audio.duration * clickProgress
|
|
182
|
+
//设置移动的位置
|
|
183
|
+
this.$refs.currentProgress.style.width = MoveX + 'px'
|
|
184
|
+
this.$refs.circle.style.left = MoveX - ( this.$refs.circle.clientWidth / 2 ) + 'px'
|
|
185
|
+
},
|
|
186
|
+
//鼠标弹起
|
|
187
|
+
handleMouseup() {
|
|
188
|
+
if(this.duration === '00:00'){
|
|
189
|
+
Message.warning("音频还未加载完成")
|
|
190
|
+
return false
|
|
191
|
+
}
|
|
192
|
+
// 销毁的时候清除定时器
|
|
193
|
+
const timer = setTimeout(() => {
|
|
194
|
+
this.audio.play()
|
|
195
|
+
this.paused = false
|
|
196
|
+
clearTimeout(timer)
|
|
197
|
+
}, 200)
|
|
198
|
+
|
|
199
|
+
this.$once('hook:beforeDestroy', () => {
|
|
200
|
+
clearTimeout(timer)
|
|
201
|
+
})
|
|
202
|
+
},
|
|
203
|
+
//调整进度
|
|
204
|
+
handleMousedown() {
|
|
205
|
+
this.audio.pause()
|
|
206
|
+
this.paused = true
|
|
207
|
+
let progress = this.$refs.progress
|
|
208
|
+
//进度条 左 边距离页面左边的距离 移动最小值
|
|
209
|
+
let moveMin = progress.offsetParent.offsetLeft + progress.offsetLeft
|
|
210
|
+
//进度条 右 边距离页面左边的距离 移动最大值
|
|
211
|
+
let moveMax = progress.offsetParent.offsetLeft + progress.offsetLeft + progress.clientWidth
|
|
212
|
+
//小圆圈的宽度
|
|
213
|
+
let circleWidth = ( this.$refs.circle.clientWidth / 2 )
|
|
214
|
+
let moveX = ( e ) => {
|
|
215
|
+
if (e.pageX >= moveMax) {
|
|
216
|
+
return
|
|
217
|
+
} else if (e.pageX <= moveMin) {
|
|
218
|
+
return
|
|
219
|
+
}
|
|
220
|
+
this.$refs.circle.style.left = e.pageX - moveMin - circleWidth + 'px'
|
|
221
|
+
this.updateProgress(e.pageX - moveMin)
|
|
222
|
+
}
|
|
223
|
+
//获取当前鼠标的位置 X
|
|
224
|
+
document.addEventListener('mousemove', moveX)
|
|
225
|
+
//鼠标弹起来
|
|
226
|
+
document.addEventListener('mouseup', () => {
|
|
227
|
+
document.removeEventListener('mousemove', moveX)
|
|
228
|
+
})
|
|
229
|
+
},
|
|
230
|
+
rangeVolume(val){
|
|
231
|
+
console.log(val);
|
|
232
|
+
},
|
|
233
|
+
/** 设置倍速播放 */
|
|
234
|
+
changeSpeed(command) {
|
|
235
|
+
const audioPlayer = this.$refs.audio
|
|
236
|
+
if (audioPlayer) {
|
|
237
|
+
audioPlayer.playbackRate = command
|
|
238
|
+
}
|
|
239
|
+
this.speed = command
|
|
240
|
+
},
|
|
241
|
+
downRecord() {
|
|
242
|
+
this.$emit('downloadCallback')
|
|
243
|
+
},
|
|
244
|
+
calcMoveX() {
|
|
245
|
+
if (!this.audio.paused) {
|
|
246
|
+
// 设置当前时间
|
|
247
|
+
let MoveX = this.$refs.progress.clientWidth * ( this.audio.currentTime / this.audio.duration )
|
|
248
|
+
//播放时更新距离
|
|
249
|
+
this.$refs.currentProgress.style.width = MoveX + 'px'
|
|
250
|
+
this.$refs.circle.style.left = MoveX - ( this.$refs.circle.clientWidth / 2 ) + 'px'
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
jumpToTime(){
|
|
254
|
+
this.audio.pause()
|
|
255
|
+
const formatStartT = this.timeFormat(this.startTime)
|
|
256
|
+
if(this.duration === '00:00'){
|
|
257
|
+
Message.warning("音频还未加载完成")
|
|
258
|
+
return false
|
|
259
|
+
}
|
|
260
|
+
if(formatStartT >= this.duration){
|
|
261
|
+
this.audio.currentTime = this.duration
|
|
262
|
+
this.currentDuration = this.timeFormat(this.audio.currentTime)
|
|
263
|
+
this.calcMoveX()
|
|
264
|
+
this.audio.play()
|
|
265
|
+
console.error("开始时间不能大于总时长");
|
|
266
|
+
return false
|
|
267
|
+
}else if(formatStartT >= '00:00' && formatStartT < this.duration){
|
|
268
|
+
this.audio.currentTime = this.startTime
|
|
269
|
+
this.currentDuration = this.timeFormat(this.audio.currentTime)
|
|
270
|
+
this.calcMoveX()
|
|
271
|
+
this.audio.play()
|
|
272
|
+
}else{
|
|
273
|
+
this.audio.currentTime = 0
|
|
274
|
+
this.currentDuration = this.timeFormat(this.audio.currentTime)
|
|
275
|
+
this.calcMoveX()
|
|
276
|
+
this.audio.play()
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
watch:{
|
|
281
|
+
volumeValue(val){
|
|
282
|
+
this.volume = val/100
|
|
283
|
+
this.audio.volume = val/100
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
</script>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@94ai/nf-theme-chalk/lib/css/nf-audio.css'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@94ai/nf-theme-chalk/lib/nf-audio.scss'
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="nf-volume-tool" :class=" visible ? 'nf-tool-show':'nf-tool-hide'" @click="showPopper" >
|
|
3
|
+
<div ref="reference">
|
|
4
|
+
<slot name="reference"/>
|
|
5
|
+
</div>
|
|
6
|
+
<transition name="slide-fade">
|
|
7
|
+
<div ref="popperRef" class="nf-popper" v-show="visible" >
|
|
8
|
+
<slot/>
|
|
9
|
+
</div>
|
|
10
|
+
</transition>
|
|
11
|
+
|
|
12
|
+
</div>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script setup>
|
|
16
|
+
import { watch, ref ,onUnmounted} from 'vue-demi'
|
|
17
|
+
|
|
18
|
+
const emits = defineEmits(['update:visible'])
|
|
19
|
+
const props = defineProps({
|
|
20
|
+
visible: [Boolean, String]
|
|
21
|
+
})
|
|
22
|
+
const reference = ref()
|
|
23
|
+
const popperRef = ref()
|
|
24
|
+
|
|
25
|
+
watch(() => props.visible, ( newValue ) => {
|
|
26
|
+
if (newValue) {
|
|
27
|
+
window.addEventListener('mousedown',docClick)
|
|
28
|
+
}else {
|
|
29
|
+
window.removeEventListener('mousedown',docClick)
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
function docClick(e){
|
|
34
|
+
//如果点击的是音量 或者 是音量面板 则 不隐藏音量面板
|
|
35
|
+
if (popperRef.value.contains(e.target) || reference.value.contains(e.target)){
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
emits('update:visible', false)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function showPopper() {
|
|
42
|
+
emits('update:visible', true)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
onUnmounted(()=>{
|
|
46
|
+
emits('update:visible', false)
|
|
47
|
+
})
|
|
48
|
+
defineExpose({
|
|
49
|
+
showPopper
|
|
50
|
+
})
|
|
51
|
+
</script>
|
|
52
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@94ai/nf-audio",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.39",
|
|
4
4
|
"description": "> TODO: description",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"author": "liuxiangxiang <liuxiangxiang@94ai.com>",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"url": "http://94ai.gitlab.com/zoujiahe/common-ui.git"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@94ai/nf-theme-chalk": "^
|
|
17
|
+
"@94ai/nf-theme-chalk": "^1.0.0",
|
|
18
18
|
"vue-demi": "^0.14.5"
|
|
19
19
|
},
|
|
20
20
|
"peerDependenciesMeta": {
|
|
@@ -30,5 +30,5 @@
|
|
|
30
30
|
"types": "lib/index.d.ts",
|
|
31
31
|
"main": "lib/nf-audio.cjs.js",
|
|
32
32
|
"module": "lib/nf-audio.esm-bundler.js",
|
|
33
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "2b60696b405feafbbaeed385e5bcf666ceefbf2c"
|
|
34
34
|
}
|