uniapp 音乐播放器 可拖动进度

<template>
	<view class="imt-audio">
		<view class="rotateBox rotatebox" :style="{animationPlayState:paused?'paused':'running'}">
			<img src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=535467763,2481826314&fm=26&gp=0.jpg" alt="" />
		</view>
		<view class="audio-wrapper">
			<view class="audio-number" style="margin-right:13rpx">{{ format(current) }}</view>
			<u-slider
				v-model="slideWidth"
				@moving="moveing"
				@end="endMove"
				:disabled="loading"
				style="width:524rpx"
				:block-width="12"
				block-color="#FFE100"
				:height="2"
				inactive-color="#c4c4c4"
				:unidirectionalDatatTransfer="true"
                active-color='#FFE100'
			></u-slider>
			<view class="audio-number" style="margin-left:13rpx">{{ format(duration) }}</view>
		</view>
		<view class="audio-control-wrapper" :style="{ color }">
			<view class="audio-control audio-control-prev iconfont icon-bofangqi_shangyizhenbeifen" v-if="control" :style="{ borderColor: color,fontSize:'61rpx' }" @click="prev"></view>
			<view class="audio-control audio-control-switch" :class="{ audioLoading: loading }" @click="audio.paused ? play() : audio.pause()">
                <text class="iconfont" :class="loading ? ' icon-jiazai' : paused ? ' icon-bofangqi-bofang_' : ' icon-bofangqi-zanting'" style="font-size:146rpx"></text>
            </view>
			<view class="audio-control audio-control-next iconfont icon-bofangqi_xiayizhenbeifen" v-if="control" :style="{ borderColor: color,fontSize:'61rpx' }" @click="next"></view>
		</view>
	</view>
</template>

<script>
export default {
	data() {
		return {
			audio: uni.createInnerAudioContext(),
			current: 0, //当前进度(s)
			duration: 0, //总时长(s)
			paused: true, //是否处于暂停状态
			loading: false, //是否处于读取状态
			seek: false, //是否处于拖动状态
			slideWidth: 0,
		}
	},
	props: {
		src: String, //音频链接
		autoplay: Boolean, //是否自动播放
		continue: Boolean, //播放完成后是否继续播放下一首,需定义@next事件
		control: {
			type: Boolean,
			default: true,
		}, //是否需要上一曲/下一曲按钮
		color: {
			type: String,
			default: '#C4C4C4',
		}, //主色调
	},
	methods: {
		endMove() {
			this.play()
			const pr = (this.slideWidth / 100) * this.duration
			// this.current = pr
			this.audio.seek(pr)
		},
		moveing() {
			this.play()
			this.seek = true
			const pr = (this.slideWidth / 100) * this.duration
			this.current = pr
			console.log(this.seek)
		},
		//返回prev事件
		prev() {
			this.slideWidth = 0
			this.$emit('prev')
		},
		//返回next事件
		next() {
			this.slideWidth = 0
			this.$emit('next')
		},
		//格式化时长
		format(num) {
			return '0'.repeat(2 - String(Math.floor(num / 60)).length) + Math.floor(num / 60) + ':' + '0'.repeat(2 - String(Math.floor(num % 60)).length) + Math.floor(num % 60)
		},
		//点击播放按钮
		play() {
			this.audio.play()
			// this.loading = true
		},
	},
	created() {
		if (this.src) {
			this.audio.src = this.src
			this.autoplay && this.play()
		}
		this.audio.obeyMuteSwitch = false
		//音频进度更新事件
		this.audio.onTimeUpdate(() => {
			// console.log('音频进度条发生更新')
			if (!this.seek) {
				// console.log('重新更新')
				this.current = this.audio.currentTime
			}
			if (!this.duration) {
				this.duration = this.audio.duration
			}
		})
		//音频播放事件
		this.audio.onPlay(() => {
			// console.log('音频播放')
			this.paused = false
			this.loading = false
			console.log(this.audio.duration)
		})
		//音频暂停事件
		this.audio.onPause(() => {
			this.paused = true
		})
		//音频结束事件
		this.audio.onEnded(() => {
			// console.log('音频结束')
			if (this.continue) {
				this.next()
			} else {
				this.paused = true
				this.current = 0
			}
		})
		//音频完成更改进度事件
		this.audio.onSeeked(() => {
			// console.log('音频进度条完成')
			this.seek = false
			this.$forceUpdate()
		})
		//微信基础库不同,必须监听这个,并且输出这个值,上面的 onTimeUpdate才会触发,不知道啥情况
		this.audio.onCanplay(() => {
			this.loading = false
			console.log(this.audio.duration, '音频能够播放了')
		})

		this.audio.onWaiting(() => {
			// console.log('XXXX')
			this.loading = true
			console.log(this.audio.duration)
		})
	},
	beforeDestroy() {
		this.audio.destroy()
	},
	watch: {
		src(src, old) {
			this.audio.src = src
			this.slideWidth = 0
			this.current = 0
			this.duration = 0
			if (old || this.autoplay) {
				this.play()
			}
		},
		current(value) {
			if (this.duration > 0) {
				if (this.current === this.duration) {
					this.slideWidth = 100
					return
				}
				// this.slideWidth = parseInt(((parseInt(value) / parseInt(this.duration)) * 100).toFixed(2))
				this.slideWidth = Number(((value / this.duration) * 100).toFixed(4))
			}
		},
	},
}
</script>

<style lang="scss" scoped>
@font-face {font-family: "iconfont";
  src: url('//at.alicdn.com/t/font_2279025_ref7yewe9x8.eot?t=1608278021196'); /* IE9 */
  src: url('//at.alicdn.com/t/font_2279025_ref7yewe9x8.eot?t=1608278021196#iefix') format('embedded-opentype'), /* IE6-IE8 */
  url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAARsAAsAAAAACigAAAQdAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDSAqGZIUlATYCJAMYCw4ABCAFhG0HgQ4bkQjIngPu5taspEecucywEpQz+PesecqmabdL6sweoPQo/qoHKAeg/tPaQjyZpB8KGkmmiZPK2pthWJWWTwhyd/W/LLWIgxZgAoFQUgMEfMg+WVNbROHw3LsaXecByQGhaioUKFr8OqGYHZByYz23GWe30K4hUCu/jtcDASh8RSOj9P6Zq+GC3QiA7G5cztVaNnyGTchGaeTYBLkQ5DqFWgDMyt+efCQmA5QIBDeqNw9abv2gHWOqVUWrUKEe5wGgnQQwQDSAAzmjvsGKZSIaozh/oaRSDgYyij9oLlq2dkg7ZrVCSxWECEOow1H/8ChOAGkgnQHx1UkBGmIEGGguCBDQshGgoB1CgIN2zAaBJunAbZwAvyEDAS3YDjKGYlgHlCFmNAYxFn2XmRfp9dMWqPMVZerCEYsa2aaFCwkxL9JXBdT5Q6eienhucWksWDLVtclC8yBSt4wsbk1piercaP7UgbR++xtak5svml5/3vjas+GkaVRImr97Q2vd7ueoJ1t2LKT9BrXj8kvJB6/4ilVX0w5c9ummNI7YeDDYuRNbGplvO3+5h0vnBQcObfMiLSHbTZgb8RYtosa2/4dCXDqzZVHoWbDCXVi0/+BWT9ICs12FuTFv2ZLXURWLckxncbbo0ti9hL6KrtAoTbQy4uo/W5myYJ27bD/F4lbUnXVM48Y1cbrn2DlLmpxSwgYV+vtDGTG7qWOTdrKzU0q4ifTnqRrWMbe5vz+/HYpTSaKqq2zX3TnHbW05qs+xBFW8UThtezqysZgrGkcW60VjTrnhwqOPFmPvjPTxkf1gL1Xfe+QxkPqPvnt8AkPKPfWFxj0xgUElF9PmOAaVHfeIGJbAELCi8idlDAugU70bNui+1a3WOb/TYf4HuWgPwzZsJQfAqnLCVObejUoWwv8XZkbQO65AAASWl6hn29plf5P13J26R80Cldtl/xg9xPK/VkcCsFp5upLtUtr94y1AAJKuahSjACUMAVYMOXpwlOJbk6UBmUsNlA0fYGTBaI6PBkEvGSSyPFBEKTtZz0l/RSR1ACJNACDs7QLK6BQw9s6jOf4+CK7egcQ+BoomxemceqF1U4r6Qw6gUYdh1K2jbbHIGTSK8gd4aMheU5lzvuH5IkwJsfHd9AkWvCMOGDCYLwcOZGTqb5tUCjeDYdjUt7/9hhpMuw4MnFVcnGnshaYd+5i5hiIekAVAQzpIkW5UNgtLJwcavdd/AC5kkHkzfR3hb+DxibWTBLHiBeiTzhL1fcrGA0S4pYECjHcy8dhMpBQ9YIQJG+k7vtUbqAJTXTfEHCtxNMwk1U2vN5jv8goARXBbqVDCCCeCSMQG0uomZ7JodujDZIu7YlIMPDuW4e1fWdDiY/Q8/Ve+dyqyFywFgsEaDo8lQtasuRwAAA==') format('woff2'),
  url('//at.alicdn.com/t/font_2279025_ref7yewe9x8.woff?t=1608278021196') format('woff'),
  url('//at.alicdn.com/t/font_2279025_ref7yewe9x8.ttf?t=1608278021196') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
  url('//at.alicdn.com/t/font_2279025_ref7yewe9x8.svg?t=1608278021196#iconfont') format('svg'); /* iOS 4.1- */
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon-jiazai:before {
  content: "\e615";
}

.icon-bofangqi-bofang_:before {
  content: "\e63c";
}

.icon-bofangqi-zanting:before {
  content: "\e600";
}

.icon-bofangqi_shangyizhenbeifen:before {
  content: "\e6b7";
}

.icon-bofangqi_xiayizhenbeifen:before {
  content: "\e6bb";
}

.imt-audio {
	padding: 32rpx 0;
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: flex-start;
	.rotateBox {
		width: 362rpx;
		height: 362rpx;
		padding: 13rpx;
		border-radius: 50%;
		background-color: rgba(54, 54, 54, 0.2);
		> img {
			width: 100%;
			height: 100%;
			border-radius: 50%;
		}
	}
}

.audio-wrapper {
	display: flex;
	align-items: center;
    
}

.audio-number {
	width: 64rpx;
	height: 34rpx;
	font-size: 24rpx;
	font-family: PingFang SC;
	font-weight: 500;
	text-align: center;
	color: #c8c7c7;
}

.audio-slider {
	flex: 1;
	margin: 0;
}

.audio-control-wrapper {
	margin-top:64rpx;
	display: flex;
	justify-content: center;
	align-items: center;
}

.audio-control {
	font-size: 32rpx;
	line-height: 1;
	// border-radius: 50%;
	padding:0 33rpx;
}


.audioLoading {
	animation: loading 2s;
	animation-iteration-count: infinite;
	animation-timing-function: linear;
}

@keyframes loading {
	to {
		transform: rotate(360deg);
	}
}
@keyframes rotate{
    from{
        transform: rotate(0deg);
    }
    to{
        transform: rotate(360deg);
    }
}
.rotatebox{
    animation-name: rotate;
    animation-duration: 8s;//完成一组动画需要的时间
    animation-timing-function:linear;//动画曲线
    animation-iteration-count:infinite;//播放次数
    animation-direction:normal;//是否逆向播放
    animation-play-state:running;//动画是否暂停
}
</style>
<template>
	<view class="content">
		<Musice
			continue
			:src="audio[now]"
			:duration="audio[now].duration"
			@prev="now = now === 0 ? audio.length - 1 : now - 1"
			@next="now = now === audio.length - 1 ? 0 : now + 1"
		></Musice>
		<!-- 
			 src: String 音频链接*必须*
			 autoplay: Boolean 是否自动播放*默认false*
			 continue: Boolean 播放完成后是否继续播放下一首,需定义@next事件*默认false*
			 control: Boolean 是否需要上一曲/下一曲按钮*默认true*
			 color: String 主色调*默认#169af3*
			 @prev:点击上一首按钮
			 @next:点击下一首按钮
		  -->
		<!-- <view class="list" :class="{ active: key === now }" v-for="(item, key) in audio" :key="key" @click="now = key">{{ key + 1 }}</view> -->
		<!-- <button @click="open">打开输入</button> -->

		<!-- <AutoIn :showModel.sync="show" v-model="text"></AutoIn> -->
	</view>
</template>

<script>
import Musice from '@/components/musice.vue'
import AutoIn from '@/components/AutoIn.vue'
import { getData } from '@/api/user'
export default {
	mixins: [],
	data() {
		return {
			audio: [
				'http://xiaozhang.php-cli.cn/music-1.mp3',
				'http://xiaozhang.php-cli.cn/music-2.mp3',
				'http://xiaozhang.php-cli.cn/music-3.mp3',
				'http://xiaozhang.php-cli.cn/music-4.mp3',
				'http://xiaozhang.php-cli.cn/music-5.mp3',
			],
			now: 0,
			text: '',
			show: false,
		}
	},
	onLoad() {},
	components: {
		Musice,
		AutoIn,
	},
	methods: {
		async open() {
			// this.show = true
            let data = await getData({ index: 1 })
            console.log(data)
		},
	},
	mounted() {},
}
</script>

<style scoped lang='scss'>

.content {
	padding: 20upx;
    background:#121212;
    
}

.list {
	font-size: 28upx;
	line-height: 88upx;
	padding-left: 30upx;
	background: #fff;
	border-radius: 10upx;
	margin-top: 20upx;
	color: #333;
}

.active {
	background: #169af3;
	color: #fff;
}
</style>

 

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
要实现进度条,需要以下步骤: 1. 在页面中引入uni-ui组件库,可以使用uni-progress组件来实现进度条。 2. 绑定uni-progress组件的value属性到当前歌曲的播放进度,可以使用uni.getBackgroundAudioManager()获取全局唯一的背景音频管理器,通过onTimeUpdate事件监听音乐播放进度的变化,在事件回调中更新进度条的value属性。 3. uni-progress组件提供了一个show-info属性,可以用来显示进度条的百分比,可以根据需要选择是否显示。 4. 如果需要拖动进度条来调整歌曲的播放进度,可以给uni-progress组件绑定一个change事件,当进度条的值发生变化时,在事件回调中调用背景音频管理器的seek方法来跳转到指定的播放时间。 示例代码如下: ```html <template> <view> <audio :src="musicUrl" @play="onPlay" @pause="onPause"></audio> <uni-progress :value="progress" show-info @change="onChange"></uni-progress> </view> </template> <script> export default { data() { return { musicUrl: 'http://music.163.com/song/media/outer/url?id=1330348068.mp3', playing: false, duration: 0, currentTime: 0, progress: 0, } }, mounted() { uni.getBackgroundAudioManager().onTimeUpdate(() => { const audio = uni.getBackgroundAudioManager() this.duration = audio.duration this.currentTime = audio.currentTime this.progress = this.currentTime / this.duration * 100 }) }, methods: { onPlay() { this.playing = true }, onPause() { this.playing = false }, onChange(e) { const audio = uni.getBackgroundAudioManager() const position = e.detail.value / 100 * this.duration audio.seek(position) }, } } </script> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值