主功能代码
<template>
<view class="lp-record">
<!-- 多选控件 -->
<view class="conbox record">
<view class="panel source-player" v-if="source">
<view class="head">原音播放</view>
<audio-player ref="audioPlayer" :audio="{src:source}"></audio-player>
</view>
<view class="panel">
<!-- 此处可放置倒计时,可根据需要自行添加 -->
<view class="time">
{{showRecordTime}}
</view>
<view class="c999">
最短{{minTime}}秒,最长{{maxTime}}秒
</view>
<view class="record-box" @touchmove.stop.prevent="onMoveHandler">
<!-- 空占位 -->
<view class="btn empty" v-if="isRecording" style="background: unset;"></view>
<view class="btn recording" @touchstart="onTouchStartHandler"
@touchend="onTouchEndHandler">
<text class="ws-icon" :class="{flash:isRecording&&!isRecordPaused}" style="font-size: 35rpx;">
{{isRecording&&!isRecordPaused ? '暂停' : '录音'}}
</text>
</view>
<view class="btn confirm" @touchstart.stop="onRecordEndHandler" v-if="isRecording"><text
class="ws-icon">结束</text></view>
<view class="btn confirm" @touchstart.stop="onConfirmHandler" v-if="!isRecording && playPath"><text
class="gui-icons">确认</text></view>
</view>
<view class="c666 fz32 domess">
{{isRecording ? (isRecordPaused ? '已暂停' : '录音中') : (playPath ? '录音完成' : '点击开始录音')}}
</view>
<view v-if="playPath">
<view class="head">录音播放</view>
<audio-player :audio="{src:playPath}"></audio-player>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
frame: 50, // 执行绘画的频率,单位毫秒
recordTime: 0, //录音时长
isRecording: false, //是否录制中
isRecordPaused: false, //是否录制暂停
playing: 0, //是否播放中
playPath: "",
recorderManager: null, //录音
innerAudioContext: null, //播放
source: 'https://statici.jpworld.cn/files/aaaaaa0802.mp3',
maxTime: 600,
minTime: 5,
canPuase: true,
}
},
computed: {
showRecordTime() {
var strs = "";
var m = Math.floor(this.recordTime / 60);
if (m < 10) strs = "0" + m;
var s = this.recordTime % 60;
strs += (s < 10) ? ":0" + s : ":" + s;
return strs
},
},
onLoad() {
console.log('onload');
var _this = this;
this.initValue();
//获取录音权限
try {
uni.authorize({
scope: 'scope.record',
success() {}
})
} catch (e) {
console.error(e);
}
this.showPicker();
},
beforeDestroy() {
if (this.isRecording) {
this.recordEnd(true);
}
this.stopVoice();
this.pauseTime();
},
onReady() {
console.log('onReady');
},
methods: {
//-----------------------------------------------------------------------------------------------
//
// action
//
//-----------------------------------------------------------------------------------------------
//组件数据初始化 进入时、关闭时调用初始化
initValue() {},
//显示组件
showPicker() {
this.recordReset();
this.initSound();
//this.$emit('open');
},
//关闭组件
closePicker() {
//点遮罩 点取消关闭说明用户不想修改,所以这里对数据进行初始化
//this.initValue();
if (this.isRecording) {
this.recordEnd();
}
this.destorySound();
this.stopVoice();
//this.$emit('close');
},
recordReset: function() {
this.playPath = ""; //音频地址
this.stopVoice();
this.resetTime();
},
recordStart: function() {
let _this = this;
console.log('recordStart', this.recorderManager);
_this.resetTime();
// 开始录音
this.recorderManager.start({
duration: this.maxTime * 1000
});
},
recordPause: function() {
this.recorderManager.pause();
},
recordResume: function() {
this.recorderManager.resume();
},
recordEnd: function(force) {
let recordTime = this.recordTime;
force = !!force;
if (!force && recordTime < this.minTime) {
if (recordTime <= 0) {
//==点击事件==;
return false;
}
//==小于5秒==;
uni.showToast({
title: "不能小于" + this.minTime + "秒,请重新录制",
icon: "none"
})
return false;
}
console.log('recordEnd');
this.recorderManager.stop();
},
playVoice() {
if (this.playPath) {
this.innerAudioContext.src = this.playPath;
this.innerAudioContext.play();
this.playing = 1;
}
},
stopVoice() {
if (this.innerAudioContext) {
this.innerAudioContext.stop();
}
this.playing = 0;
},
//-----------------------------------------------------------------------------------------------
//
// Source
//
//-----------------------------------------------------------------------------------------------
initSound: function() {
console.log('initSound');
this.recorderManager = uni.getRecorderManager(); //录音
this.innerAudioContext = uni.createInnerAudioContext(); //播放
var _this = this;
this.recorderManager.onStart(function() {
console.log('开始录音');
_this.startTime();
_this.isRecording = true;
});
//录音暂停事件
this.recorderManager.onPause(function() {
console.log('录音暂停');
_this.isRecordPaused = true;
_this.pauseTime();
});
// 录音恢复事件
this.recorderManager.onResume(function() {
console.log('录音继续');
_this.isRecordPaused = false;
_this.startTime();
})
//录音停止事件
this.recorderManager.onStop(function(res) {
console.log('开始结束' + JSON.stringify(res));
_this.pauseTime();
_this.isRecording = false;
_this.playPath = res.tempFilePath;
_this.onConfirmHandler();
});
},
destorySound: function() {
if (this.recorderManager) {
this.recorderManager.stop();
}
if (this.innerAudioContext) {
this.innerAudioContext.stop();
}
},
//-----------------------------------------------------------------------------------------------
//
// Timer
//
//-----------------------------------------------------------------------------------------------
resetTime: function() {
this.recordTime = 0;
this.pauseTime();
},
startTime: function() {
let _this = this;
this.pauseTime();
_this.timeObj = setInterval(function() {
_this.recordTime++;
//this.$refs.recordClock.setValue(_this.recordTime / _this.maxTime);
if (_this.recordTime == _this.maxTime) _this.recordEnd();
}, 1000);
},
pauseTime: function() {
clearInterval(this.timeObj);
},
//-----------------------------------------------------------------------------------------------
//
// Draw
//
//-----------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------
//
// handler
//
//-----------------------------------------------------------------------------------------------
/**
* 事件取消
*/
onMoveHandler() {
return false;
},
/**
*
*/
onTouchStartHandler: function() {
console.log('onTouchStartHandler');
// 可以暂停情况下,开始录制
if (this.canPuase) {
if (this.isRecording) {
this.isRecordPaused ? this.recordResume() : this.recordPause();
} else {
this.recordReset();
this.recordStart();
}
} else {
this.recordReset();
}
},
/**
* 长按
*/
onLongpressHandler: function() {
// 不可以暂停情况下,开始录制
if (!this.canPuase) {
this.recordStart();
}
},
/**
* 长按结束
*/
onTouchEndHandler: function() {
if (!this.canPuase) {
this.recordEnd();
}
},
onRecordEndHandler: function() {
this.recordEnd();
},
//点击确定
onConfirmHandler() {
// var data = {},list = {},textStr = "",indexStr = "";
this.$emit('recconfirm', this.playPath)
//确定后更新默认初始值,这样再次进入默认初值就是最后选择的
// this.defaultArr = textStr;
//关闭
this.closePicker();
},
}
}
</script>
<style lang="scss">
.lp-record {
position: relative;
z-index: 99;
.mask {
position: fixed;
z-index: 1000;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
}
.conbox {
background: #fff;
}
.c666 {
color: #666;
}
.c999 {
color: #999;
}
.fz28 {
font-size: 28rpx;
}
.fz32 {
font-size: 32rpx;
}
.source-player {
padding: 50rpx 0rpx;
border-bottom: solid 1px #eeeeee;
.head {
text-align: left;
font-size: 30rpx;
margin-bottom: 20rpx;
}
}
.record {
text-align: center;
.time {
text-align: center;
font-size: 60rpx;
color: #000;
line-height: 100rpx;
margin-top: 50rpx;
}
.domess {
margin-bottom: 50rpx;
}
.record-box {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.btn {
display: flex;
justify-content: center;
align-items: center;
width: 90rpx;
height: 90rpx;
border-radius: 50%;
color: #fff;
background-color: $uni-color-primary;
text {
font-size: 40rpx;
}
}
.recording {
//position: absolute;
//top: 10px;
//left: 10px;
margin: 20rpx;
width: 80px;
height: 80px;
background-color: $uni-color-error;
z-index: 100;
font-size: 35px;
}
.stop {}
.play {
margin-left: 5rpx;
}
.confirm {}
}
}
.flash {
animation: 2s opacity2 0s infinite;
-webkit-animation: 2s opacity2 0s infinite;
-moz-animation: 2s opacity2 0s infinite;
}
@keyframes opacity2 {
0% {
opacity: 0.1
}
50% {
opacity: .8;
}
100% {
opacity: 0.1;
}
}
@-webkit-keyframes opacity2 {
0% {
opacity: 0.1
}
50% {
opacity: .8;
}
100% {
opacity: 0.1;
}
}
@-moz-keyframes opacity2 {
0% {
opacity: 0.1
}
50% {
opacity: .8;
}
100% {
opacity: 0.1;
}
}
</style>
播放组件代码;
<template>
<view class="gui-player" :class="{mini:mini,nobroud:nobroud}">
<!-- 播放控制 -->
<view class="gui-player-console">
<view class="gui-player-console-c">
<text class="gui-player-tool gui-icons" style="font-size:33rpx;" @tap="pause" v-if="playStatus == 1">暂停</text>
<text class="gui-player-tool gui-icons" style="font-size:33rpx;margin-left: 4rpx;" @tap="play" v-if="playStatus == 2">播放</text>
</view>
<!-- 播放进度 -->
<view v-if="!mini" class="progress-bar">
{{playTime}} / {{timeFormat(audioLength)}}
</view>
</view>
</view>
</template>
<script>
export default {
props: {
color: {
type: String,
default: '#333'
},
mini: {
type: Boolean,
default: false
},
nobroud:{
type: Boolean,
default: false
},
autoPlay: {
type: Boolean,
default: false
},
audio: {
type: Object,
default: {
title: "我们都一样",
singer: "张杰",
epname: "杰哥精选",
coverImgUrl: "https://7465-test01-632ffe-1258717418.tcb.qcloud.la/personal/player/images/jie02.jpg?sign=00e5e68d81145037000a162e2220736a&t=1556345760",
src: "https://7465-test01-632ffe-1258717418.tcb.qcloud.la/personal/player/song/%E6%88%91%E4%BB%AC%E9%83%BD%E4%B8%80%E6%A0%B7%20-%20%E5%BC%A0%E6%9D%B0.mp3?sign=008d62b6bea06a8a6814b5f284fac0ac&t=1556345730"
}
}
},
data() {
return {
playStatus: 2,
player: null,
playTime: '00:00',
timer: null,
audioLength: 1
}
},
beforeDestroy() {
this.destroy();
},
created: function() {
this.player = uni.createInnerAudioContext();
this.player.onTimeUpdate(() => {
try {
if (this.playStatus != 1) {
return;
}
this.audioLength = this.player.duration;
// 调整进度
var progress = this.player.currentTime / this.audioLength;
progress = Math.round(progress * 100);
var ref = this.$refs.graceSingleSlider;
if (ref) {
ref.setProgress(progress);
}
this.playTime = this.timeFormat(this.player.currentTime);
} catch (e) {};
});
this.player.onPlay(() => {
this.playStatus = 1;
this.audioLength = this.player.duration;
});
this.player.onPause(() => {
this.playStatus = 2;
});
this.player.onEnded(() => {
this.playStatus = 2;
});
this.load(this.audio, this.autoPlay);
},
methods: {
load: function(audio, autoPlay) {
//this.player.title = audio.title;
//this.player.singer = audio.singer;
//this.player.coverImgUrl = audio.coverImgUrl;
console.log(audio);
this.player.src = audio.src;
autoPlay && this.player.play();
},
progressChange: function(e) {
if (this.timer != null) {
clearTimeout(this.timer);
}
this.player.pause();
var needTime = this.audioLength * e / 100;
needTime = Math.round(needTime);
this.playTime = this.timeFormat(needTime);
this.timer = setTimeout(() => {
this.player.seek(needTime);
this.player.play();
}, 800);
},
timeFormat: function(s) {
s = Math.round(s);
if (s < 60) {
if (s < 10) {
return '00:0' + s;
}
return '00:' + s;
} else {
var second = s % 60;
s = s - second;
var minute = s / 60;
if (minute < 10) {
minute = '0' + minute;
}
if (second < 10) {
second = '0' + second;
}
return minute + ':' + second;
}
},
pause: function() {
console.log('pause');
this.player && this.player.pause();
},
play: function() {
console.log('play',this.player.src);
this.player && this.player.play();
},
destroy: function() {
this.player && this.player.destroy();
},
}
}
</script>
<style lang="scss" scoped>
.gui-player {
padding: 30rpx;
border: solid 1px #eee;
border-radius: 10rpx;
.gui-player-console {
display: flex;
justify-content: center;
align-items: center;
}
.gui-player-tool {
width: 96rpx;
line-height: 96rpx;
text-align: center;
font-size: 33rpx;
display: block;
flex-shrink: 0;
color: #fff;
}
.gui-player-console-c {
display: flex;
align-items: center;
background: #28b28b;
border-radius: 50%;
width: 96rpx;
height: 96rpx;
}
.progress-bar {
flex: 1;
padding: 25rpx;
}
}
.mini ,.nobroud{
padding: unset;
border: unset;
}
</style>
wskeee (作者)
微信小程序,APP我没有测过
2021-08-07 10:29
wskeee (作者)
微信社区需要原生代码,我现在是uniapp代码怎么给他们反馈?https://developers.weixin.qq.com/community/develop/doc/000808deed8378249ee9f82965b800 微信社区好像也有类似的反馈,但到现在也没解决。
2021-08-07 10:32
DCloud_UNI_GSQ
回复 wskeee: 原生代码写个最简单的示例分享为代码片段即可。反馈的人多了应该会得到重视。
2021-08-08 16:54