feat: 集成音频播放组件和视频播放器
This commit is contained in:
@@ -1,295 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<u-popup key="1" :show="videoShow" :round="10" @close="closeVideo">
|
||||
<view class="" style="padding: 10px;">
|
||||
<view>
|
||||
<view class="container">
|
||||
<div
|
||||
ref="videoContent"
|
||||
@tap="renderScript.handleClick"
|
||||
id="url-player-test"
|
||||
:videoData="videoData"
|
||||
:opname="opname"
|
||||
:change:opname="renderScript.opnameChange"
|
||||
:change:videoData="renderScript.receiveMsg"
|
||||
></div>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<div class="fullScreenButton-container">
|
||||
<div
|
||||
:class="`prism-fullscreen-btn ${isFullScreen ? 'fullscreen' : ''}`"
|
||||
@tap="renderScript.changeVideoScreen"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<view class="btn" style="text-align: center;">
|
||||
<button type="primary" @click="closeVideo" size="mini">关闭视频</button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick } from 'vue'
|
||||
import type { IVideoData } from '@/types/video'
|
||||
|
||||
// Props 定义
|
||||
interface Props {
|
||||
videoData: IVideoData
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
// Emits 定义
|
||||
const emit = defineEmits<{
|
||||
close: []
|
||||
}>()
|
||||
|
||||
// 响应式数据
|
||||
const videoShow = ref(true)
|
||||
const isFullScreen = ref(false)
|
||||
const opname = ref('')
|
||||
|
||||
// 方法: 关闭视频
|
||||
const closeVideo = () => {
|
||||
opname.value = 'close'
|
||||
nextTick(() => {
|
||||
emit('close')
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<script module="renderScript" lang="renderjs">
|
||||
// RenderJS 模块 - 保持 Vue2 写法
|
||||
// jQuery 在 RenderJS 中通过全局变量访问
|
||||
var $ = window.jQuery || window.$
|
||||
|
||||
export default {
|
||||
mounted() {
|
||||
console.log(this.options, '这是monted')
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
player: null,
|
||||
curTime: null,
|
||||
curStatus: null
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
curTime(val) {
|
||||
if (this.curTime !== null && this.curStatus !== null) {
|
||||
// 可以添加逻辑
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleClick(event, ownerInstance) {
|
||||
console.log('event at line 165:', event)
|
||||
},
|
||||
|
||||
emitData(event, ownerInstance) {
|
||||
ownerInstance.callMethod('recordTime', {
|
||||
time: this.curTime,
|
||||
status: this.curStatus
|
||||
})
|
||||
},
|
||||
|
||||
changeVideoScreen(event, ownerInstance) {
|
||||
var status = this.player.fullscreenService.getIsFullScreen()
|
||||
|
||||
ownerInstance.callMethod('screenChange', {
|
||||
status: status,
|
||||
primary: status ? 'portrait' : 'landscape'
|
||||
})
|
||||
|
||||
if (status) {
|
||||
setTimeout(() => {
|
||||
plus.screen.lockOrientation('portrait-primary')
|
||||
this.player.fullscreenService.cancelFullScreen()
|
||||
}, 100)
|
||||
} else {
|
||||
this.player.fullscreenService.requestFullScreen()
|
||||
setTimeout(() => {
|
||||
plus.screen.lockOrientation('landscape-primary')
|
||||
}, 100)
|
||||
}
|
||||
},
|
||||
|
||||
endEmitData(event, ownerInstance) {
|
||||
ownerInstance.callMethod('handleEnd')
|
||||
},
|
||||
|
||||
getLive() {
|
||||
if (this.videoData.type == 1) {
|
||||
var fullScreenButtonComponent = Aliplayer.Component({
|
||||
init: function(status, toAddress) {
|
||||
this.fullScreenStatus = status
|
||||
this.$html = $('.fullScreenButton-container')
|
||||
},
|
||||
|
||||
createEl: function(el) {
|
||||
this.$html.find('.ad').attr('src', this.adAddress)
|
||||
var $adWrapper = this.$html.find('.ad-wrapper')
|
||||
$adWrapper.attr('href', this.toAddress)
|
||||
$adWrapper.click(function() {})
|
||||
$(el).find('.prism-time-display').after(this.$html)
|
||||
},
|
||||
|
||||
playing: function(player, e) {
|
||||
this.$html.show()
|
||||
}
|
||||
})
|
||||
|
||||
console.log('this.currentVideoList at line 456111111111111111111111:', this.videoList)
|
||||
|
||||
var player = new Aliplayer({
|
||||
id: 'url-player-test',
|
||||
vid: this.videoData.videoId,
|
||||
playauth: this.videoData.playAuth,
|
||||
encryptType: 1,
|
||||
playConfig: {
|
||||
EncryptType: 'AliyunVoDEncryption'
|
||||
},
|
||||
width: '100%',
|
||||
height: '200px',
|
||||
playsinline: true,
|
||||
controlBarVisibility: 'click',
|
||||
cover: '',
|
||||
components: [
|
||||
{
|
||||
name: 'adComponent',
|
||||
type: fullScreenButtonComponent,
|
||||
args: ['http://101.201.146.165:8088/Pf-EH/statics/uploadFile/2024-05-10/b0f420c7-9178-41ad-9dd6-f59a64a6e190.png']
|
||||
}
|
||||
],
|
||||
skinLayout: [
|
||||
{ name: 'bigPlayButton', align: 'blabs', x: 30, y: 80 },
|
||||
{ name: 'H5Loading', align: 'cc' },
|
||||
{ name: 'errorDisplay', align: 'tlabs', x: 0, y: 0 },
|
||||
{ name: 'infoDisplay' },
|
||||
{ name: 'tooltip', align: 'blabs', x: 0, y: 56 },
|
||||
{ name: 'thumbnail' },
|
||||
{
|
||||
name: 'controlBar',
|
||||
align: 'blabs',
|
||||
x: 0,
|
||||
y: 0,
|
||||
children: [
|
||||
{ name: 'progress', align: 'blabs', x: 0, y: 44 },
|
||||
{ name: 'playButton', align: 'tl', x: 15, y: 12 },
|
||||
{ name: 'timeDisplay', align: 'tl', x: 10, y: 7 },
|
||||
{ name: 'prism-speed-selector', align: 'tr', x: 15, y: 12 },
|
||||
{ name: 'volume', align: 'tr', x: 5, y: 10 }
|
||||
]
|
||||
}
|
||||
]
|
||||
}, function(player) {})
|
||||
|
||||
this.player = player
|
||||
}
|
||||
},
|
||||
|
||||
opnameChange(newValue, oldValue, ownerVm, vm) {
|
||||
console.log('opnameChange-----------', newValue)
|
||||
if (newValue == 'close') {
|
||||
if (this.player) {
|
||||
this.player.dispose()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
receiveMsg(newValue, oldValue, ownerVm, vm) {
|
||||
console.log('数据变化newValue', newValue)
|
||||
if (newValue.playAuth) {
|
||||
this.loadWebPlayerSDK()
|
||||
}
|
||||
},
|
||||
|
||||
checkValue() {
|
||||
console.log(this.videoData, this.videoData.playAuth, '1111888888')
|
||||
if (!this.videoData.playAuth) {
|
||||
setTimeout(() => {
|
||||
this.checkValue()
|
||||
}, 1000)
|
||||
} else {
|
||||
console.log('this.videoList at line 这是这只只是594:', this.currentVideoList)
|
||||
this.getLive()
|
||||
}
|
||||
},
|
||||
|
||||
loadWebPlayerSDK() {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 先加载 jQuery
|
||||
if (!window.jQuery && !window.$) {
|
||||
const jquery_tag = document.createElement('script')
|
||||
jquery_tag.type = 'text/javascript'
|
||||
jquery_tag.src = 'https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js'
|
||||
jquery_tag.charset = 'utf-8'
|
||||
jquery_tag.onload = () => {
|
||||
$ = window.jQuery || window.$
|
||||
this.loadAliPlayerSDK(resolve, reject)
|
||||
}
|
||||
jquery_tag.onerror = () => {
|
||||
console.error('jQuery 加载失败')
|
||||
reject(new Error('jQuery 加载失败'))
|
||||
}
|
||||
document.body.appendChild(jquery_tag)
|
||||
} else {
|
||||
$ = window.jQuery || window.$
|
||||
this.loadAliPlayerSDK(resolve, reject)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
loadAliPlayerSDK(resolve, reject) {
|
||||
const s_tag = document.createElement('script')
|
||||
s_tag.type = 'text/javascript'
|
||||
s_tag.src = 'https://g.alicdn.com/apsara-media-box/imp-web-player/2.20.3/aliplayer-min.js'
|
||||
s_tag.charset = 'utf-8'
|
||||
s_tag.onload = () => {
|
||||
const s_tag1 = document.createElement('script')
|
||||
s_tag1.type = 'text/javascript'
|
||||
s_tag1.src = 'https://player.alicdn.com/aliplayer/presentation/js/aliplayercomponents.min.js'
|
||||
s_tag1.charset = 'utf-8'
|
||||
s_tag1.onload = () => {
|
||||
this.checkValue()
|
||||
resolve()
|
||||
}
|
||||
s_tag1.onerror = () => {
|
||||
console.error('阿里云播放器组件加载失败')
|
||||
reject(new Error('阿里云播放器组件加载失败'))
|
||||
}
|
||||
document.body.appendChild(s_tag1)
|
||||
}
|
||||
s_tag.onerror = () => {
|
||||
console.error('阿里云播放器 SDK 加载失败')
|
||||
reject(new Error('阿里云播放器 SDK 加载失败'))
|
||||
}
|
||||
document.body.appendChild(s_tag)
|
||||
|
||||
const l_tag = document.createElement('link')
|
||||
l_tag.rel = 'stylesheet'
|
||||
l_tag.href = 'https://g.alicdn.com/apsara-media-box/imp-web-player/2.20.3/skins/default/aliplayer-min.css'
|
||||
document.body.appendChild(l_tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fullScreenButton-container {
|
||||
color: #fff;
|
||||
float: right;
|
||||
height: 35px;
|
||||
margin-top: 6px;
|
||||
margin-right: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
@@ -1,123 +0,0 @@
|
||||
<template>
|
||||
<view class="richDetail">
|
||||
<view
|
||||
scroll-x="true"
|
||||
class="detail_title video_box"
|
||||
style="background-color: #fff"
|
||||
>
|
||||
<view
|
||||
v-for="(v, i) in dataList"
|
||||
:key="v.id"
|
||||
:class="`video_item ${currentVideo && currentVideo.id == v.id ? 'hot' : ''}`"
|
||||
@click="handleClick(v, i)"
|
||||
>
|
||||
【{{ v.type == '2' ? '音频' : '视频' }}】{{ getNumber(i + 1) }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<slot name="richHeadImg"></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { IVideoInfo, IChapterDetail } from '@/types/video'
|
||||
|
||||
// Props 定义
|
||||
interface Props {
|
||||
detailInfo: IChapterDetail
|
||||
dataList: IVideoInfo[]
|
||||
currentVideo: IVideoInfo | null
|
||||
changeVideoLock: boolean
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
// Emits 定义
|
||||
const emit = defineEmits<{
|
||||
open: [video: IVideoInfo]
|
||||
}>()
|
||||
|
||||
// 方法: 格式化序号为两位数
|
||||
const getNumber = (num: number): string => {
|
||||
if (num >= 10) {
|
||||
return num.toString()
|
||||
} else {
|
||||
return `0${num}`
|
||||
}
|
||||
}
|
||||
|
||||
// 方法: 处理视频点击
|
||||
const handleClick = (data: IVideoInfo, index: number) => {
|
||||
if (props.changeVideoLock) {
|
||||
return
|
||||
}
|
||||
console.log('data at line 35:', data)
|
||||
emit('open', data)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.commonPageBox {
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
|
||||
.contentBox {
|
||||
.headImage {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.detail_title {
|
||||
padding: 0 20rpx 0;
|
||||
font-size: 26rpx;
|
||||
line-height: 65rpx;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.rich_box {
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
p {
|
||||
display: block;
|
||||
text-indent: 2em;
|
||||
letter-spacing: 2px !important;
|
||||
line-height: 46rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.richDetail {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.video_box {
|
||||
width: 100%;
|
||||
|
||||
.video_item {
|
||||
width: 23%;
|
||||
margin-right: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
float: left;
|
||||
border: 2rpx solid #2979ff;
|
||||
background: #fff;
|
||||
color: #2979ff;
|
||||
text-align: center;
|
||||
border-radius: 10rpx;
|
||||
box-shadow: 0px 0px 6rpx 0px rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
.video_item:nth-child(4n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.hot {
|
||||
background-color: #2979ff !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
</style>
|
||||
105
components/ali-video/audio.vue
Normal file
105
components/ali-video/audio.vue
Normal file
@@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<div class="video-player">
|
||||
<image :src="coverImageUrl" class="video-cover" style="width: 100%; height:100%;" />
|
||||
<CxAudioPlayer
|
||||
v-if="list.length > 0"
|
||||
:list="list"
|
||||
:autoplays="true"
|
||||
style="
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
position: absolute; left: 0; top: 0;
|
||||
width: 100%; height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mainClient } from '@/api/clients';
|
||||
import CxAudioPlayer from './cx-audio-play/cx-audio-play.vue'
|
||||
export default {
|
||||
props: {
|
||||
currentVideo: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
coverImageUrl: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
http: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
},
|
||||
components: {
|
||||
CxAudioPlayer
|
||||
},
|
||||
watch: {
|
||||
currentVideo: {
|
||||
handler(newVal, oldVal) {
|
||||
if (!newVal || !newVal.id) return
|
||||
this.fetchRealAudioUrl(newVal)
|
||||
},
|
||||
immediate: true,
|
||||
deep: true,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isfresh: false,
|
||||
screenLoading: false,
|
||||
isFullScreen: false,
|
||||
changeVideoLock: false,
|
||||
secondCountDown: 10,
|
||||
list: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async fetchRealAudioUrl(videoInfo) {
|
||||
if (!videoInfo) return
|
||||
const data = { ...videoInfo }
|
||||
try {
|
||||
const res = await mainClient.request({
|
||||
url: 'sociology/course/checkVideo',
|
||||
method: 'POST',
|
||||
data,
|
||||
header: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
console.log('获取播放凭证666',JSON.stringify(res.video));
|
||||
const real = res && res.video ? res.video : null
|
||||
if (!real) {
|
||||
this.list = []
|
||||
return
|
||||
}
|
||||
const src = real.videoUrl || real.m3u8Url || real.source || ''
|
||||
if (!src) {
|
||||
|
||||
this.list = []
|
||||
return
|
||||
}
|
||||
this.list = [{ recorPath: src }]
|
||||
} catch (e) {
|
||||
this.list = []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.video-player {
|
||||
position: relative;
|
||||
height: 400rpx;
|
||||
width: 100%;
|
||||
|
||||
.player {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute; left: 0; top: 0; width: 100%; height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
16
components/ali-video/cx-audio-play/changelog.md
Normal file
16
components/ali-video/cx-audio-play/changelog.md
Normal file
@@ -0,0 +1,16 @@
|
||||
## 2.0.1(2023-12-15)
|
||||
优化体积和倍数播放功能
|
||||
## 2.0.0(2023-12-15)
|
||||
修改一些bug,兼容基本平台
|
||||
## 1.0.7(2023-12-15)
|
||||
优化功能体积速度
|
||||
## 1.0.5(2023-12-15)
|
||||
优化功能,兼容基本平台
|
||||
## 1.0.4(2023-12-15)
|
||||
简化代码,优化功能,处理一些bug
|
||||
## 1.0.3(2023-02-09)
|
||||
修改切换的某些bug,新增自动播放下一首功能
|
||||
## 1.0.2(2022-12-16)
|
||||
适配app平台
|
||||
## 1.0.1(2022-12-16)
|
||||
1.0.1
|
||||
585
components/ali-video/cx-audio-play/cx-audio-play.vue
Normal file
585
components/ali-video/cx-audio-play/cx-audio-play.vue
Normal file
@@ -0,0 +1,585 @@
|
||||
<template>
|
||||
<!--音频组件-->
|
||||
<view>
|
||||
<view class="bgfff">
|
||||
<view>
|
||||
<view class="audo-video">
|
||||
<!--音频api处[视频代替音频-实现倍数功能]-->
|
||||
<video
|
||||
id="myVideo" ref="myVideo" :src="recorPath" class="hidden" @timeupdate="timeupdate"
|
||||
:autoplay="autoplays" @loadedmetadata="loadedmetadata" @ended="next" :controls="true"
|
||||
:show-center-play-btn="false" :show-mute-btn="true"
|
||||
/>
|
||||
<!--音频api处[视频代替音频-实现倍数功能]-->
|
||||
|
||||
<!--音频播放按钮处-->
|
||||
<view class="audo-top">
|
||||
<!--上一首切换按钮-->
|
||||
<!-- <image v-if="jian" style="width:50rpx;height:50rpx;" @click="nosig" src="./static/sys.png" mode="aspectFill"></image>
|
||||
<image v-else @click="sig" src="./static/xys.png" style="width:50rpx;height:50rpx;transform:rotate(180deg)"
|
||||
mode="aspectFill"></image> -->
|
||||
<!--上一首切换按钮-->
|
||||
|
||||
<!--快退按钮-->
|
||||
<image src="./static/kt.png" style="width:60rpx;height:60rpx;" mode="aspectFill" @click="kt()"></image>
|
||||
<!--快退按钮-->
|
||||
|
||||
<!--播放按钮-->
|
||||
<image v-if="succes" src="./static/bofang2.png" mode="aspectFill"
|
||||
style="width:180rpx;height:180rpx;" @click="plays()"></image>
|
||||
<image v-else src="./static/zt.png" mode="aspectFill"
|
||||
style="width:180rpx;height:180rpx;" @click="plays()"></image>
|
||||
<!--播放按钮-->
|
||||
|
||||
<!--快进按钮-->
|
||||
<image src="./static/kj.png" style="width:60rpx;height:60rpx;" mode="aspectFill" @click="kj()"></image>
|
||||
<!--快进按钮-->
|
||||
|
||||
<!--下一首切换按钮-->
|
||||
<!-- <image v-if="jia" @click="noxig" style="width:50rpx;height:50rpx;transform:rotate(180deg)" src="./static/sys.png"
|
||||
mode="aspectFill"> </image>
|
||||
<image v-else style="width:50rpx;height:50rpx;" src="./static/xys.png" @click="xig" mode="aspectFill"></image> -->
|
||||
<!--下一首切换按钮-->
|
||||
</view>
|
||||
<!--音频播放按钮处-->
|
||||
|
||||
|
||||
<view class="audo-a" style="margin:0 auto;">
|
||||
|
||||
<!--进度条-->
|
||||
<view class="slider-box">
|
||||
<text class="mm">{{timer}}</text>
|
||||
<slider style="width: 370rpx;" @change="sliderChange" @changing="sliderChanging"
|
||||
class="audio-slider" block-size="16" :min="0" :max="duration" :value="currentTime"
|
||||
activeColor="#FFA929" />
|
||||
<text class="ss" v-if="overTimer!='NaN:NaN'">{{overTimer}}</text>
|
||||
<text class="ss" v-else>00.00</text>
|
||||
</view>
|
||||
<!--进度条-->
|
||||
|
||||
|
||||
<!--倍速-->
|
||||
<view class="beishu" style="border:3rpx solid #C8C9CC;" @click="beishu">{{BsNav[bsindex].bs}} X
|
||||
</view>
|
||||
<!--倍速-->
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="h-100"></view>
|
||||
<!--占位-->
|
||||
</view>
|
||||
<!--音频组件 Author:chenxin-->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/*
|
||||
list -- 音频文件传入 不传无法播放/数组形式
|
||||
Faskms -- 快进秒数 number 默认15秒
|
||||
Slowms -- 快退秒数 number 默认15秒
|
||||
autoNext -- 是否自动播放下一首
|
||||
autoplays -- 进入页面是否自动播放 - 默认false
|
||||
slideYes -- 滑动进度条时是否开启播放 - 默认false
|
||||
switAud -- 切换上下音频是否开启播放 - 默认false
|
||||
BsNav -- 倍数数据传入/数组形式
|
||||
|
||||
按钮图片未自定义,如想改动请在组件内部修改,页面头部已注释 -- 逻辑根据自己需求改
|
||||
目前只测试 微信小程序和H5和APP -- 其他平台未知
|
||||
Author:chenxin 交流vx:cxalq8-24
|
||||
*/
|
||||
export default {
|
||||
name: "cx-audio-play",
|
||||
props: {
|
||||
list: { //音频数据
|
||||
Type: Array,
|
||||
default: () => []
|
||||
},
|
||||
Faskms: { //快进秒数
|
||||
Type: Number,
|
||||
default: 15,
|
||||
},
|
||||
Slowms: { //快退秒数
|
||||
Type: Number,
|
||||
default: 15,
|
||||
},
|
||||
autoNext: {
|
||||
Type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
autoplays: { //是否开启自动播放
|
||||
Type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
slideYes: { //滑动进度条 - 是否开启播放
|
||||
Type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
switAud: {
|
||||
Type: Boolean, //切换上下音频 - 是否开启播放
|
||||
default: false,
|
||||
},
|
||||
BsNav: { //倍数-传入
|
||||
Type: Array,
|
||||
default: () => [{
|
||||
id: 0.5,
|
||||
bs: '0.5',
|
||||
}, {
|
||||
id: 0.8,
|
||||
bs: '0.8'
|
||||
}, {
|
||||
id: 1.0,
|
||||
bs: '1.0'
|
||||
}, {
|
||||
id: 1.25,
|
||||
bs: '1.25'
|
||||
}, {
|
||||
id: 1.5,
|
||||
bs: '1.5'
|
||||
}],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
jian: true, //减-切换图标
|
||||
jia: true, //加-切换图标
|
||||
succes: false, //播放按钮
|
||||
bsid: '', //倍数默认显示第一个
|
||||
bsindex: 0, //倍数默认显示第一个
|
||||
num: 0,
|
||||
current: 0, //当前选中的索引
|
||||
recorPath: '', //音频播放地址
|
||||
lock: false, // 锁
|
||||
currentTime: 0, //当前进度
|
||||
duration: 100, // 总进度
|
||||
videoContext: null,
|
||||
loading: true, //锁 加载
|
||||
}
|
||||
},
|
||||
onReady() {},
|
||||
onShow() {},
|
||||
mounted() {
|
||||
this.videoContext = uni.createVideoContext('myVideo', this)
|
||||
//默认播放第一个 -- 按钮展示
|
||||
if (this.list.length != 0) {
|
||||
this.recorPath = this.list[0].recorPath
|
||||
if (this.list.length > 1) { //音频文件大于1 -- 下一个切换默认显示
|
||||
this.jia = false
|
||||
}
|
||||
if (this.autoplays) {
|
||||
this.succes = true
|
||||
}
|
||||
}
|
||||
//倍数默认处理
|
||||
if (this.BsNav.length != 0) {
|
||||
const defaultRate = 1.0
|
||||
const index = this.BsNav.findIndex(item => item.id === defaultRate)
|
||||
if (index !== -1) {
|
||||
this.bsid = this.BsNav[index].id
|
||||
this.bsindex = index
|
||||
} else {
|
||||
this.bsid = this.BsNav[0].id
|
||||
this.bsindex = 0
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.playbackRate(this.bsid)
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.playbackRate(this.bsid)
|
||||
//#endif
|
||||
})
|
||||
}
|
||||
},
|
||||
updated() {
|
||||
|
||||
},
|
||||
onLoad() {
|
||||
|
||||
},
|
||||
onHide() { //监听页面离开 - 销毁音频
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.stop();
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.stop();
|
||||
//#endif
|
||||
},
|
||||
onUnload() { //监听页面卸载 - 销毁音频
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.stop();
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.stop();
|
||||
//#endif
|
||||
},
|
||||
destroyed() {
|
||||
// this.innerAudioContext.stop();
|
||||
},
|
||||
computed: {
|
||||
timer() {
|
||||
return calcTimer(this.currentTime)
|
||||
},
|
||||
overTimer() {
|
||||
return calcTimer(this.duration)
|
||||
}
|
||||
},
|
||||
watch: { },
|
||||
methods: {
|
||||
plays() { //播放暂停
|
||||
if (!this.list || this.list.length == 0) {
|
||||
console.log('暂无音频数据~')
|
||||
return;
|
||||
}
|
||||
this.playloading()
|
||||
this.succes = !this.succes
|
||||
if (this.succes) {
|
||||
// this.currentTime = 0
|
||||
// console.log('-----------------')
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.play()
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.play()
|
||||
//#endif
|
||||
} else {
|
||||
uni.hideLoading()
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.pause()
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.pause()
|
||||
//#endif
|
||||
}
|
||||
},
|
||||
beishu() {
|
||||
if (!this.BsNav || this.BsNav.length === 0) {
|
||||
return
|
||||
}
|
||||
let nextIndex = this.bsindex + 1
|
||||
if (nextIndex >= this.BsNav.length) {
|
||||
nextIndex = 0
|
||||
}
|
||||
const item = this.BsNav[nextIndex]
|
||||
this.bsid = item.id
|
||||
this.bsindex = nextIndex
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.playbackRate(item.id)
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.playbackRate(item.id)
|
||||
//#endif
|
||||
},
|
||||
|
||||
// 更新进度条
|
||||
timeupdate(event) {
|
||||
if (this.lock) return; // 锁
|
||||
var currentTime, duration;
|
||||
if (event.detail.detail) {
|
||||
currentTime = event.detail.detail.currentTime
|
||||
duration = event.detail.detail.duration
|
||||
} else {
|
||||
currentTime = event.detail.currentTime
|
||||
duration = event.detail.duration
|
||||
}
|
||||
this.currentTime = currentTime
|
||||
this.duration = duration
|
||||
},
|
||||
|
||||
// 拖动进度条
|
||||
sliderChange(data) {
|
||||
const value = data.detail.value
|
||||
//此处滑动进度条--开始播放
|
||||
if (this.slideYes && !this.succes) {
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.play()
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.play()
|
||||
//#endif
|
||||
this.succes = true
|
||||
}
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.seek(value) //获取秒数
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.seek(value) //获取秒数
|
||||
//#endif
|
||||
this.currentTime = value
|
||||
this.lock = false
|
||||
},
|
||||
|
||||
//拖动中
|
||||
sliderChanging(data) {
|
||||
this.lock = true
|
||||
if (data.detail.value == 0) {
|
||||
this.succes = false
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.pause()
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.pause()
|
||||
//#endif
|
||||
}
|
||||
this.currentTime = data.detail.value
|
||||
},
|
||||
|
||||
// 视频加载完成
|
||||
loadedmetadata(data) {
|
||||
this.duration = data.detail.duration
|
||||
},
|
||||
sig() { //上一首
|
||||
if (!this.list || this.list.length == 0) {
|
||||
console.log('暂无音频数据~')
|
||||
return;
|
||||
}
|
||||
this.num -= 1
|
||||
if (this.num < this.list.length) {
|
||||
this.loading = true
|
||||
this.playloading() //加载框
|
||||
}
|
||||
if (this.num + 1 < this.list.length && this.num + 1 != 1) { //点击上一首小于音频数据总长度
|
||||
this.jia = false // 下按钮-亮且可点击
|
||||
this.jian = false // 上按钮-亮且可点击
|
||||
} else {
|
||||
this.jian = true // 上按钮-灰且阻止
|
||||
this.jia = false // 下按钮-亮且可点击
|
||||
}
|
||||
this.recorPath = this.list[this.num].recorPath
|
||||
if (this.switAud) { //切换时是否默认开启播放
|
||||
this.succes = true
|
||||
setTimeout(() => {
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.play()
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.play()
|
||||
//#endif
|
||||
}, 100)
|
||||
} else {
|
||||
this.succes = false
|
||||
}
|
||||
},
|
||||
xig() { //下一首
|
||||
if (!this.list || this.list.length == 0) {
|
||||
console.log('暂无音频数据~')
|
||||
return;
|
||||
}
|
||||
this.num += 1
|
||||
if (this.num < this.list.length) {
|
||||
this.loading = true
|
||||
this.playloading() //加载框
|
||||
}
|
||||
if (this.num + 1 < this.list.length) { //点击下一首小于音频数据总长度
|
||||
this.jia = false // 下按钮-亮且可点击
|
||||
this.jian = false // 上按钮-亮且可点击
|
||||
} else { //大于总长度
|
||||
this.jia = true //下按钮 - 灰且阻止
|
||||
this.jian = false //上按钮 - 亮可点击
|
||||
}
|
||||
this.recorPath = this.list[this.num].recorPath
|
||||
if (this.switAud) { //切换时是否默认开启播放
|
||||
this.succes = true
|
||||
setTimeout(() => {
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.play()
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.play()
|
||||
//#endif
|
||||
}, 100)
|
||||
} else {
|
||||
this.succes = false
|
||||
}
|
||||
},
|
||||
nosig() {
|
||||
uni.showToast({
|
||||
title: '到头了~',
|
||||
icon: "none"
|
||||
})
|
||||
},
|
||||
noxig() {
|
||||
uni.showToast({
|
||||
title: '没有更多了~',
|
||||
icon: "none"
|
||||
})
|
||||
},
|
||||
kt() { //快退
|
||||
if (!this.list || this.list.length == 0) {
|
||||
console.log('暂无音频数据~')
|
||||
return;
|
||||
}
|
||||
let a = (this.currentTime - Math.floor(15 % 60)).toFixed(0) //当前时间-15秒
|
||||
if (a < 1) {
|
||||
this.succes = false
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.pause()
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.pause()
|
||||
//#endif
|
||||
}
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.seek(a)
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.seek(a)
|
||||
//#endif
|
||||
},
|
||||
kj() { //快进
|
||||
if (!this.list || this.list.length == 0) {
|
||||
console.log('暂无音频数据~')
|
||||
return;
|
||||
}
|
||||
let a = (this.currentTime + Math.floor(15 % 60)).toFixed(0) //当前时间+15秒
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.seek(a)
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.seek(a)
|
||||
//#endif
|
||||
},
|
||||
next(data) { //监听音频结束
|
||||
this.succes = false
|
||||
/*音频结束--是否自动播放下一首*/
|
||||
if (!this.autoNext) {
|
||||
return
|
||||
}
|
||||
if (this.num + 1 < this.list.length) {
|
||||
this.succes = true
|
||||
this.num += 1
|
||||
this.recorPath = this.list[this.num].recorPath
|
||||
setTimeout(() => {
|
||||
//#ifdef H5
|
||||
this.$refs.myVideo.play()
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.videoContext.play()
|
||||
//#endif
|
||||
}, 100)
|
||||
} else {
|
||||
this.jia = true //下按钮 - 灰且阻止
|
||||
this.jian = false //上按钮 - 亮可点击
|
||||
}
|
||||
// console.log('音频结束-------')
|
||||
},
|
||||
playloading() { //加载框--封
|
||||
if (this.loading) {
|
||||
uni.showLoading({
|
||||
title: "音频缓存中..."
|
||||
})
|
||||
this.loading = false
|
||||
}
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
}, 1600)
|
||||
},
|
||||
},
|
||||
watch: {}
|
||||
}
|
||||
function calcTimer(timer) {
|
||||
if (typeof timer !== 'number' || !isFinite(timer) || timer <= 0) {
|
||||
return '00:00'
|
||||
}
|
||||
let mm = Math.floor(timer / 60)
|
||||
let ss = Math.floor(timer % 60)
|
||||
if (mm < 10) {
|
||||
mm = '0' + mm
|
||||
}
|
||||
if (ss < 10) {
|
||||
ss = '0' + ss
|
||||
}
|
||||
return mm + ':' + ss
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
/* #video {
|
||||
width: 100%;
|
||||
} */
|
||||
.audo-video {
|
||||
padding-bottom: 20rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.slider-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 27rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
button {
|
||||
display: inline-block;
|
||||
width: 100rpx;
|
||||
background-color: #fff;
|
||||
font-size: 24rpx;
|
||||
color: #000;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.video {
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: -10rpx;
|
||||
z-index: -1;
|
||||
width: 1rpx;
|
||||
height: 1rpx;
|
||||
}
|
||||
|
||||
.audo-top {
|
||||
padding: 20rpx 40rpx;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
image {
|
||||
width: 45rpx;
|
||||
height: 45rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.audo-a {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 700rpx;
|
||||
position: relative;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.beishu {
|
||||
position: relative;
|
||||
width: 100rpx;
|
||||
padding-top: 5rpx;
|
||||
padding-bottom: 5rpx;
|
||||
text-align: center;
|
||||
border-radius: 25rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.absolute {
|
||||
position: absolute;
|
||||
|
||||
.beishu-a {
|
||||
width: 200rpx;
|
||||
border-radius: 20rpx;
|
||||
text-align: center;
|
||||
line-height: 90rpx;
|
||||
background: #fff;
|
||||
|
||||
.title {
|
||||
padding-left: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
85
components/ali-video/cx-audio-play/package.json
Normal file
85
components/ali-video/cx-audio-play/package.json
Normal file
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"id": "cx-audio-play",
|
||||
"displayName": "音频播放组件,自定义修改",
|
||||
"version": "2.0.1",
|
||||
"description": "音频播放组件,兼容微信小程序、h5等,可倍数播放,快进快退,切换上下音频等",
|
||||
"keywords": [
|
||||
"音频",
|
||||
"音频播放",
|
||||
"播放器",
|
||||
"倍数播放",
|
||||
"播放"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.5.5"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "u"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "u"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "u",
|
||||
"百度": "u",
|
||||
"字节跳动": "u",
|
||||
"QQ": "u",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
components/ali-video/cx-audio-play/readme.md
Normal file
13
components/ali-video/cx-audio-play/readme.md
Normal file
@@ -0,0 +1,13 @@
|
||||
### 组件各参说明 :
|
||||
____
|
||||
#### 1. 实现切换上下首、自动播放、倍数播放、快进快退、进度条播放等
|
||||
#### 2. list 【Array】 音频数据/不传无法播放
|
||||
#### 3. Seconds 【number】 快进快退秒数 - 默认15秒
|
||||
#### 4. autoNext 【Boolean】 自动播放下一首 - 默认不开启
|
||||
#### 5. autoplays 【Boolean】 进入页面是否自动播放 - 默认不开启
|
||||
#### 6. slideYes 【Boolean】 拖动进度条时开启播放 - 默认不开启
|
||||
#### 7. switAud 【Boolean】 切换上下音频开启播放 - 默认开启
|
||||
#### 8. BsNav 【Array】 倍数数据
|
||||
#### 本音频组件扩展性强,样式功能随意调整,兼容H5,微信小程序,App,建议下载示例项目,避免因图片缺失引起报错,谢谢支持~
|
||||
#### 作者: chenxin ,微信交流: cxalq8-24
|
||||
----
|
||||
BIN
components/ali-video/cx-audio-play/static/bofang2.png
Normal file
BIN
components/ali-video/cx-audio-play/static/bofang2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
BIN
components/ali-video/cx-audio-play/static/kj.png
Normal file
BIN
components/ali-video/cx-audio-play/static/kj.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
components/ali-video/cx-audio-play/static/kt.png
Normal file
BIN
components/ali-video/cx-audio-play/static/kt.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
components/ali-video/cx-audio-play/static/sys.png
Normal file
BIN
components/ali-video/cx-audio-play/static/sys.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
components/ali-video/cx-audio-play/static/xys.png
Normal file
BIN
components/ali-video/cx-audio-play/static/xys.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
components/ali-video/cx-audio-play/static/zt.png
Normal file
BIN
components/ali-video/cx-audio-play/static/zt.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
1393
components/ali-video/demo.vue
Normal file
1393
components/ali-video/demo.vue
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1531
components/ali-video/video.vue
Normal file
1531
components/ali-video/video.vue
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user