Commit adf74842 authored by sunzh's avatar sunzh
Browse files

小程序插件demo

parent e2054ea7
# VOD_WX_PluginDemo
点播组微信小程序插件Demo
\ No newline at end of file
#### 点播组微信小程序插件Demo说明
- 使用demo需要用户配置 ccvod-plugin-demo/project.config.json appid字段,添加自己的appid。
- 添加配置ccvod插件版本后就可以运行使用ccvod-plugin-demo,并参考demo进行二次开发。
- 申请插件以及插件提供的属性以及API,请参考[点播小程序插件使用文档](https://mp.weixin.qq.com/wxopen/plugindevdoc?appid=wx70d57361939e63ef&token=898833657&lang=zh_CN)
#### 播放器controls说明
- 控制条组件支持2种方式:
- video默认controls;
- 自定义controls;
- ccvod-plugin-demo/components/controls 为demo提供的自定义controls内容(包含进度条、全屏、倍速以及清晰度);
- 如果用户需要封装自定义组件,推荐使用封装好的自定义组件,可以适当调整以及优化,但应避免修改时引起功能异常;
- ccvod-plugin-demo/pages/index为demo播放页,index.js 中通过useCtrol控制使用方式;useCtrol为 true 使用自定义controls;为false使默认controls 。
#### 下载功能说明
- 仅mp4支持下载,实现下载功能有2种方式:
- 使用播放器插件内置按钮;
- 通过插件提供API来实现。
- 下载成功后,应在回调里处理删除缓存文件,避免超出小程序允许的存储空间大小,影响下载功能的使用。
//app.js
App({
onLaunch: function () {
}
})
\ No newline at end of file
{
"pages": [
"pages/videolist/videolist",
"pages/index/index",
"pages/vc/vc"
],
"plugins": {
"ccvod": {
"version": "1.0.1",
"provider": "wx70d57361939e63ef"
}
},
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle": "black"
},
"sitemapLocation": "sitemap.json"
}
\ No newline at end of file
/**app.wxss**/
.container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 200rpx 0;
box-sizing: border-box;
}
// components/ccvod/controls/controls.js
let ccPlayer = requirePlugin('ccvod');
Component({
/**
* 组件的属性列表
*/
properties: {
time: {
type: Object,
value: {},
observer: "handleTimeUpdate"
},
spList: {
type: Array,
value: []
},
dfList: {
type: Array,
value: []
},
ccH5hdTxt: {
type: String,
value: '高清'
},
fullScreen: {
type: Boolean
},
showHdBtn: {
type: Boolean,
value: true
},
showRateBtn: {
type: Boolean,
value: true
},
useCtrol: {
type: Boolean,
value: true
},
showFullscreenBtn: {
type: Boolean,
value: true
}
},
/**
* 组件的初始数据
*/
data: {
currTime: '00:00', // 格式化的当前时间
duration: '00:00', // 格式化的总时长
totalTime: 0,
currentTime: 0,
progressBarWidth: 0,
isPlaying: false,
isMove: false, // 标识是否为拖拽 false为点击事件,true为拖拽事件
spShow: false,
hdShow: false,
ccH5spTxt: '常速',
timer: {},
interFaceShow: true
},
/**
* 组件的方法列表
*/
methods: {
handleInterShow: function(flag) {
if(!this.data.totalTime) return;
if(!flag) {
this.setData({
spShow: false,
hdShow: false
})
}
},
/***
* 播放器点击播放
*/
catchPlay: function() {
if (this.data.isPlaying == false) {
ccPlayer.play();
this.setData({
isPlaying: true
});
} else {
ccPlayer.pause();
this.setData({
isPlaying: false
});
}
},
catchFullScreen: function(e) {
this.triggerEvent("fullscreen", e.detail, {});
// 防止切换获取进度条宽度异常
setTimeout(() => {
this.getLoadingBarSize()
}, 1000)
},
handleTimeUpdate: function(e) {
if (!e || JSON.stringify(e) === "{}") {
return;
}
let duration = e.detail.duration || 0;
let currentTime = e.detail.currentTime || 0;
// 设置duration
if(this.data.totalTime != duration){
this.setData({
duration: this.timeFormat(duration),
totalTime: duration
});
}
let isPlaying = true;
if (e.detail.duration - currentTime < 0.5) {
currentTime = e.detail.duration || 0;
isPlaying = false;
}
let percent = currentTime / duration;
percent = percent.toFixed(2) > 1 ? 1 : percent.toFixed(2);
if(parseInt(this.data.currentTime) !== parseInt(currentTime)) {
this.setData({
currTime: this.timeFormat(currentTime),
dragBtnleft: percent > 0.9 ? 'calc(' + percent * 100 +'% - 5vmin)' : (percent < 0.05? 'calc(' + percent * 100 +'% - 8px)' : 'calc(' + percent * 100 +'% - 3vmin)'),
percent: percent,
currentTime: currentTime
});
}
if(currentTime > 1) {
this.setData({
isPlaying: isPlaying
})
}
},
dragTimeStart: function(e) {
clearTimeout(this.data.timer);
this.setData({
dragStartEvent: e
})
},
/***
* 拖拽跳转时间
*/
dragTimeMove: function(e) {
this.moveIndex++;
let dragStartEvent = this.data.dragStartEvent
if(Math.abs(e.touches[0].pageX - dragStartEvent.touches[0].pageX) > 4) {
this.setData({
isMove: true
})
} else {
this.setData({
isMove: false
})
}
if (this.moveIndex <= 4) {
return;
}
this.moveIndex = 0;
this.setPercent(e);
},
/***
* 拖拽抬起跳转时间
*/
dragTimeEnd: function() {
if(!this.data.isMove) {
this.setPercent(this.data.dragStartEvent);
}
var second = parseFloat(this.data.percent) * this.data.totalTime;
console.log('second: ', second)
this.setData({
isMove: false
})
ccPlayer.pause();
ccPlayer.seek(parseInt(second));
setTimeout(() => {
ccPlayer.play();
}, 300);
},
setPercent: function (e) {
var pageX = e.touches[0].pageX;
var offsetLeft = e.currentTarget.offsetLeft;
var nowX = pageX - offsetLeft;
var width = this.data.progressBarWidth;
let percent = (nowX / width).toFixed(2);
percent = percent > 1 ? 1 : percent < 0 ? 0 : percent;
this.setData({
percent: percent,
dragBtnleft: percent === 0 ? '-5px' : 'calc(' + percent * 100 +'% - 3.5vmin)'
});
},
getLoadingBarSize: function () {
let query = wx.createSelectorQuery().in(this);
query.select("#progressBar").boundingClientRect((res) => {
if (!res || !res.width) {
return false;
}
this.setData({
progressBarWidth: res.width
})
}).exec();
},
/***
* 点击显示隐藏倍速列表
*/
clickSpShow: function() {
if (this.data.spShow == true) {
this.setData({
spShow: false,
hdShow: false,
});
} else {
this.setData({
spShow: true,
hdShow: false,
});
}
this.triggerEvent('intershow', {
interShowDownload: !this.data.spShow
}, {})
},
/***
* 点击切换倍速
*/
changeSpeed: function(e) {
if (e.target.dataset.txt == this.data.ccH5spTxt) {
this.setData({
spShow: false,
});
return;
}
let index = e.target.dataset.key;
let spNum = e.target.dataset.num;
let spTxt = e.target.dataset.txt;
this.setData({
ccH5spTxt: spTxt,
spShow: false,
});
ccPlayer.playbackRate(Number(spNum));
},
/***
* 点击显示隐藏清晰度列表
*/
clickHdShow: function() {
if (this.data.hdShow == true) {
this.setData({
spShow: false,
hdShow: false
});
} else {
this.setData({
spShow: false,
hdShow: true
});
}
this.triggerEvent('intershow', {
interShowDownload: !this.data.spShow
}, {})
},
/***
* 点击切换清晰度
*/
changeQuality: function(e, ) {
if (e.target.dataset.txt == this.data.ccH5hdTxt) {
this.setData({
hdShow: false,
});
return;
}
let hdTxt = e.target.dataset.txt;
let quality = e.target.dataset.quality;
let time = this.data.currentTime;
ccPlayer.changeQuality(quality)
this.setData({
ccH5spTxt: '常速',
ccH5hdTxt: hdTxt,
hdShow: false
});
this.data.isPlaying = false;
ccPlayer.playbackRate(1);
ccPlayer.play();
this.gotoSeek(time);
},
gotoSeek: function(time) {
setTimeout(() => {
ccPlayer.play();
if (!this.data.isPlaying) {
this.gotoSeek(time);
return;
}
ccPlayer.seek(time);
}, 200);
},
/***
* 时间转成00:00格式
*/
timeFormat: function(time) {
var t = parseInt(time),
h, i, s;
h = Math.floor(t / 3600);
h = h ? (h + ':') : '';
i = h ? Math.floor(t % 3600 / 60) : Math.floor(t / 60);
s = Math.floor(t % 60);
i = i > 9 ? i : '0' + i;
s = s > 9 ? s : '0' + s;
return (h + i + ':' + s);
},
clickBtnsShow: function () {
if (this.data.interFaceShow) {
this.hideControl();
clearTimeout(this.data.timer);
} else {
this.showControl();
this.data.timer = setTimeout(() => {
this.hideControl();
}, 6000);
}
},
hideControl: function () {
this.setData({
interFaceShow: false,
spShow: false,
hdShow: false
});
this.triggerEvent('intershow', {
interShowDownload: false
})
},
showControl: function () {
this.setData({
interFaceShow: true,
spShow: false,
hdShow: false
});
this.triggerEvent('intershow', {
interShowDownload: true
})
}
},
ready: function() {
this.moveIndex = 0
this.getLoadingBarSize()
}
})
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file
<!--components/ccvod/controls/controls.wxml-->
<cover-view
class='{{useCtrol? "ctrol-panel" : fullScreen ? "ctrol-panel panel-top":"ctrol-panel panel-bottom"}}'
wx-if="{{showHdBtn||showRateBtn||useCtrol}}" bindtap='clickBtnsShow'>
<!-- 倍速按钮 -->
<cover-view class='{{useCtrol ? "ccH5sp btn-bottom" : "ccH5sp"}}' catchtap='clickSpShow' wx-if=
"{{showRateBtn}}" style="display:{{interFaceShow? 'block':'none'}}">{{ccH5spTxt}}</cover-view>
<!-- 倍速列表 -->
<cover-view class='{{useCtrol ? "ccH5spul list-bottom" : "ccH5spul"}}' wx:if='{{spShow}}'>
<cover-view class="ccH5li" wx:for='{{spList}}' wx:key='{{index}}' data-key='{{index}}' data-num='{{spList[index].num}}'
data-txt='{{spList[index].txt}}' hover-class="btnhover" catchtap='changeSpeed'>{{spList[index].txt}}
</cover-view>
</cover-view>
<!-- 清晰度按钮 -->
<cover-view class='{{useCtrol ? "ccH5hd btn-bottom" : "ccH5hd"}}' catchtap='clickHdShow' wx-if="{{showHdBtn&&ccH5hdTxt}}" style="display:{{interFaceShow?'block':'none'}}">{{ccH5hdTxt}}</cover-view>
<!-- 清晰度列表 -->
<cover-view class='{{useCtrol ? "ccH5hdul list-bottom" : "ccH5hdul"}}' wx:if='{{hdShow}}'>
<cover-view wx:for='dfList' wx:key='{{index}}' class="ccH5li" data-quality='{{dfList[index].quality}}'
data-txt='{{dfList[index].desp}}' catchtap='changeQuality'>{{dfList[index].desp}}</cover-view>
</cover-view>
<cover-view class='ccH5Progress' wx:if='{{useCtrol}}' style="display:{{interFaceShow?'flex':'none'}}">
<!-- 播放暂停按钮 -->
<cover-view catchtap="catchPlay" class='ccPlayBtn'>
<cover-image class='btnBg' wx:if="{{isPlaying}}" src='../../images/ccPauseBtn.png'>
</cover-image>
<cover-image class='btnBg' wx:if="{{!isPlaying}}" src='../../images/ccPlayBtn.png'>
</cover-image>
</cover-view>
<!-- 播放时间 -->
<cover-view class="play-time">
<cover-view class='ccCur'>{{currTime}}</cover-view>
<cover-view class="sperate-line">/</cover-view>
<!-- 总时间 -->
<cover-view class='ccDur'>{{duration}}</cover-view>
</cover-view>
<!-- 自定义进度条 -->
<cover-view class='ccH5ProgressBar' id="progressBar" catchtouchstart='dragTimeStart' catchtouchmove='dragTimeMove'
catchtouchend='dragTimeEnd'>
<cover-view class="inner">
<cover-view class="back"></cover-view>
<cover-view class="top" style="width:{{percent*100}}%"></cover-view>
</cover-view>
<cover-view class='ccH5DragBtn' style='left:{{dragBtnleft}};'>
<cover-image class='btnBg' src='../../images/ccDragBtn.png'></cover-image>
</cover-view>
</cover-view>
<!-- 全屏按钮 -->
<cover-view catchtap="catchFullScreen" class='fullBtn' wx-if="{{showFullscreenBtn}}">
<cover-image class='btnBg' src="../../images/{{fullScreen?'ccExitFullBtn':'ccFullBtn'}}.png"></cover-image>
</cover-view>
</cover-view>
</cover-view>
\ No newline at end of file
/* components/ccvod/controls/controls.wxss */
.ctrol-panel {
width: 100%;
height:100%;
display: flex;
flex-direction: column;
justify-content: flex-end;
position: relative;
}
.panel-bottom {
height: calc(100% - 110rpx);
}
.panel-top {
height: calc(100% - 190rpx);
margin-top:50px;
}
.ccPlayBtn,.ccPauseBtn{
width: 7vmin;
height: 7vmin;
}
.exitFullsBtn{
background:#00a529;
}
.setting-btns {
position: relative;
flex: 1;
margin-bottom: 1vmin;
z-index: 100;
}
.btns-bottom {
margin-bottom: 4vmin;
}
.ccH5Progress{
height: 60rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 3.6vmin;
margin-bottom: 25rpx;
}
.ccH5ProgressBar{
position: relative;
flex: 1;
height: 60rpx;
margin-right: 4rpx;
}
.ccH5ProgressBar .inner {
position: absolute;
top: 27rpx;
left: 10rpx;
right: 10rpx;
height: 6rpx;
border-radius: 3rpx;
}
.ccH5ProgressBar .inner .back {
background: #999;
height: 100%;
width: 100%;
}
.ccH5ProgressBar .inner .top {
background: #ff920a;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 999;
}
.ccH5DragBtn{
position:absolute;
left:-5px;
top: 8rpx;
width: 24px;
height: 24px;
}
.play-time {
min-width: 26vmin;
display: flex;
justify-content: center;
align-items: center;
color: #999;
font-size: 3.6vmin;
}
.ccH5Progress .sperate-line {
padding: 0 3px;
}
.ccH5Progress .ccCur{
color: #eee;
font-size: 3.6vmin;
}
.ccH5Progress .ccDur{
color: #eee;
}
.btnBg{
width:100%;
height:100%;
display:block;
}
.fullBtn{
width: 7vmin;
height: 7vmin;
}
/* 倍速清晰度 */
.ccH5sp, .ccH5hd{
width:74px;
height:22px;
position:absolute;
right:20px;
bottom:0;
background:rgba(34, 34, 34, 0.5);
border-radius: 100px;
color:#ffffff;
font-size: 14px;
text-align: center;
padding-top: 5px;
}