原生的video组件功能已经可以满足用户所有需求,本文介绍一下非正常的用户需求怎么解决。
比如:用户需要限制播放时不能滑动屏幕快进、不能拖动进度条快进快退,不准倍速播放,不准全屏;用户第一次完整看完视频后可以倍速,快进,暂停和全屏。
解决的思路:隐藏掉video自带的所有控件功能,包括原生的video功能全部设置为false,然后自己画一个底部控件包含播放按钮还有进度条和全屏按钮,在全屏页面左上角添加返回退出全屏按钮。
上面是效果图;
下面看一下页面中的写法:
<video wx:if="{{videofalse}}" id="myvideo" custom-cache="{{false}}" bindpause="bindPause" bindplay="bindPlay" bindtimeupdate="bindtimeupdate" bindended="bindended" bindfullscreenchange="bindfullscreenchange" initial-time="{{strtime}}" enable-progress-gesture="{{progress}}" show-progress="{{progress}}" controls="{{progress}}" objectFit="cover" src="{{VideoUrl}}">
<view class='mast_video' wx:if="{{mast_video}}">
<button bindtap='seed_change'>倍速</button>
</view>
<view class='change_mast' wx:if="{{change_mast}}" bindtap='close_change'>
<view class='seed_change'>
<button bindtap="bindButtonRate" data-rate='1.0'>1.0X</button>
<button bindtap="bindButtonRate" data-rate='1.25'>1.25X</button>
<button bindtap="bindButtonRate" data-rate='1.5'>1.5X</button>
</view>
</view>
<view class='process-container' wx:if="{{stuflag == true}}">
<image src='{{playStates ? "/images/main/puse_v.png" : "/images/main/play_v.png"}}' class='video-controls-icon' bindtap='videoOpreation'></image>
<view class='slider-container'>
<slider bindchange="sliderChange" bindchanging="sliderChanging" step="0.5" value="{{sliderValue}}" backgroundColor="#A8A8A8" activeColor="#FFFFFF" block-color="#FFFFFF" block-size="14" /><text decode="{{true}}" space="{{true}}">{{canvasTime}}</text>
</view>
<image src='{{playAlls ? "/images/main/play_all.png" : "/images/main/puse_all.png"}}' class='video-controls-icon' bindtap='videoAllscreen'></image>
</view>
<view class='video_back'><image src='{{playAlls ? " " : "/images/main/video_back.png"}}' bindtap='video_back'></image></view>
</video>
有人会说为什么不使用cover-view来实现呢?cover-view是挺方便的,但是它不能实现完全的自我控制,有些属性被微信官方定义死了,还不如使用最基础的view组件和image组件自由呢。
在video组件中将自己需要控制的属性全部使用**{{false}}或者自定义名字来控制**。对自己画出的倍速和控制条的内容使用wx:if来判断可控制还是不可控制
播放按钮和全屏按钮使用三元运算来判断是播放按钮还是暂停按钮,是全屏按钮还是退出全屏按钮。
默认条件为真(true)
playStates: true, //控制播放 & 暂停按钮的显示
playAlls: true,
在点击函数中进行判断:
videoOpreation() { //自定义暂停
this.data.playStates ? this.videoContext.pause() : this.videoContext.play();
this.setData({
playStates: !this.data.playStates
})
},
videoAllscreen(e) { //自定义全屏
this.data.playAlls ? this.videoContext.requestFullScreen() : this.videoContext.exitFullScreen();
this.setData({
playAlls: !this.data.playAlls
})
},
video_back: function (e) {
this.data.playAlls ? this.videoContext.requestFullScreen() : this.videoContext.exitFullScreen();
this.setData({
playAlls: !this.data.playAlls
})
},
sliderChanging(e) { //拖拽过程中,不允许更新进度条
var new_stuflag = wx.getStorageSync("key_stuflag");
if (new_stuflag == 1) { //学完允许拖动
this.setData({
updateState: false
})
} else {
}
},
sliderChange(e) {
var new_stuflag = wx.getStorageSync("key_stuflag");
if (new_stuflag == 1) { //学完允许拖动
if (this.data.duration && obj == 200) { //完成拖动后,计算对应时间并跳转到指定位置
this.videoContext.seek(e.detail.value / 100 * this.data.duration);
this.setData({
sliderValue: e.detail.value,
updateState: true //完成拖动后允许更新滚动条
})
} else { }
} else { }
},
通过自定义函数来控制自定义组件的内容。然后在第一遍播放完成度额时候给后台提交播放信息和时长,根据返回结果来开放video组件的相应属性功能。
bindended: function (res) { //第一遍结束
var that = this,
obj_time = wx.getStorageSync("v_time"), //本次学习时长
userNid = wx.getStorageSync("unionid"),
vid = wx.getStorageSync("bo_vid"),
bid = wx.getStorageSync("ke_id");
wx.request({
url: app.globalData.Url + "/api/users/event/addstudent/", //进度提交
data: {
unionid: userNid,
vid: vid + 1,
bid: bid,
stime: obj_time
},
method: "POST",
header: {
'content-type': 'application/x-www-form-urlencoded' // 默认值
},
success: function (res) {
wx.setStorageSync("key_stuflag", res.data.stuflag)
if (res.data.stuflag == 0) { //根据学习进度状态改变是否可快进
that.setData({
progress: false,
mast_video: false,
stuflag: true
})
} else {
that.setData({
progress: true,
stuflag: false,
mast_video: true,
})
}
}
})
},
bindButtonRate(e) { //倍速
var that = this;
let rate = e.currentTarget.dataset.rate
this.videoContext.playbackRate(Number(rate))
setTimeout(function () {
that.setData({
change_mast: false,
mast_video: true,
})
}, 400)
},
seed_change: function (s) { //按钮展开倍速
this.setData({
mast_video: false,
change_mast: true,
})
},
close_change: function () { //空白处关闭倍速
this.setData({
mast_video: true,
change_mast: false,
})
},
这样自定义video功能就准备齐全了。
根据评论区需求,加上本页面CSS样式:
.weui-cells {
margin-top: 80rpx;
text-align: left;
}
.weui-label {
width: 5em;
}
.coursedes-item {
border-bottom: 1rpx solid #e5e5e5;
padding: 40rpx 10rpx;
font-size: 26rpx;
color: #141414;
line-height: 39rpx;
text-indent: 52rpx;
text-align: justify;
}
.conact {
width: 100%;
height: 105rpx;
padding: 12.5rpx 0 12.5rpx 10rpx;
background: #ccc;
position: fixed;
bottom: 0px;
left: 0;
right: 0;
min-height: 105rpx;
}
.search-left {
flex: 6;
background: #fff;
text-align: left;
}
.search-left input {
display: inline-block;
height: 85rpx;
font-size: 26rpx;
width: 100%;
}
.search-placeholder {
color: #333;
line-height: 85rpx;
font-size: 26rpx;
margin-left: 20px;
}
.sCode image {
width: 44rpx;
height: 44rpx;
padding: 10rpx 10rpx;
}
.conact .search-left image {
width: 40rpx;
height: 40rpx;
padding: 10rpx;
float: right;
}
.conact .search-right {
flex: 1;
}
.conact .search-right image {
width: 64rpx;
height: 64rpx;
}
.kefuBtn {
background-color: rgba(255, 255, 255, 0);
border: 0px;
right: 0;
display: flex;
justify-content: center;
align-items: center;
}
.kefuBtn::after {
border: 0px;
}
.fenxBtn {
background-color: rgba(255, 255, 255, 0);
border: 0px;
left: 0;
flex: 1;
}
.fenxBtn::after {
border: 0px;
}
.fenxBtn image {
width: 44rpx;
height: 44rpx;
padding: 14rpx 5rpx;
}
.pof {
position: fixed;
}
video {
width: 100%;
height: 430rpx;
}
.video_top {
width: 100%;
height: 430rpx;
}
.page-body-button {
margin-bottom: 30rpx;
font-size: 30rpx;
line-height: 90rpx;
}
.top_img {
width: 100%;
height: 430rpx;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
left: 0;
top: 0;
z-index:19;
background:#333;
}
.top_img .cover_img {
width: 90rpx;
height: 90rpx;
z-index:5;
}
video .content {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
left: 0;
bottom: 0;
z-index: 1;
width: 100%;
height: 75rpx;
font-size: 32rpx;
color: #fff;
}
video .content cover-image {
width: 44rpx;
height: 44rpx;
}
.page-cont {
height: 100%;
}
.belly-scroll {
width: 100%;
height: auto;
background-color: #f5f5f5;
overflow: hidden;
}
.hook {
width: 100%;
height: auto;
}
.header-info {
padding: 0 30rpx;
background-color: #fff;
margin-bottom: 10rpx;
}
.header-info .title {
font-size: 36rpx;
color: #333;
line-height: 1.2;
padding-top: 30rpx;
margin-bottom: 10rpx;
}
.header-info .desc {
font-size: 28rpx;
color: #555;
}
.header-info .video-total {
margin-top: 30rpx;
padding-bottom: 20rpx;
}
.header-info .user-cont {
font-size: 24rpx;
color: #808080;
}
.header-info .user-cont label {
font-size: 28rpx;
color: #1a1a1a;
}
.header-info .user-tool {
height: 46rpx;
}
.header-info .play-audio {
color: #c21327;
font-size: 22rpx;
padding: 0 10rpx;
height: 38rpx;
border: 1rpx solid #c21327;
margin-right: 55rpx;
}
.header-info .play-audio image {
width: 40rpx;
height: 40rpx;
margin-right: 10rpx;
}
.header-info .recomment {
width: 42rpx;
height: 42rpx;
margin-top: 2rpx;
margin-right: 40rpx;
}
.header-info .recomment image {
width: 40rpx;
height: 40rpx;
}
.header-info .share {
width: 42rpx;
height: 42rpx;
margin-top: 2rpx;
margin-right: 5rpx;
}
.header-info .share image {
width: 40rpx;
height: 40rpx;
}
.header-info .share-tips {
white-space: nowrap;
padding: 0 15rpx;
height: 38rpx;
line-height: 38rpx;
position: fixed;
right: 6%;
margin-top: 8px;
font-size: 22rpx;
color: #c21327;
border-radius: 19rpx;
border: 1px solid #c21327;
background-color: #fbebed;
}
.header-info .share-tips:before {
content: '';
position: absolute;
right: -1px;
top: -7rpx;
width: 16rpx;
height: 30rpx;
background-color: #fbebed;
transform: skewY(-36deg);
border-top: 1.5px solid #c21327;
border-right: 1px solid #c21327;
}
.header-info .share-tips:after {
content: '';
position: absolute;
top: 0;
right: 0;
background-color: #fbebed;
width: 20rpx;
height: 5rpx;
}
.column-inner {
background-color: #fff;
}
.column-box {
width: 100%;
height: 88rpx;
background-color: #fff;
}
.column-box .column-content {
width: 100%;
height: 88rpx;
border-bottom: 1px solid #eee;
background-color: #fff;
}
.column-box .column-pof {
position: absolute;
top: 430rpx;
left: 0;
z-index: 100;
}
.column-box .column-item {
flex: 1;
text-align: center;
padding-top: 15rpx;
line-height: 68rpx;
font-size: 28rpx;
color: #666;
}
.column-box .column-item.active {
color: #c21327;
position: relative;
}
.column-box .column-item.active:before {
content: '';
width: 50rpx;
height: 4rpx;
background-color: #c21327;
position: absolute;
bottom: 0;
left: 50%;
margin-left: -25rpx;
}
.footer {
width: 100%;
height: 102rpx;
border-bottom: 1rpx solid #e6e6e6;
left: 0;
background-color: #fff;
}
.go-home {
width: 100rpx;
flex-wrap: wrap;
font-size: 0;
line-height: 1.2;
}
.go-home image {
width: 38rpx;
height: 38rpx;
position: relative;
top: 8rpx;
}
.go-home label {
width: 100%;
text-align: center;
font-size: 24rpx;
color: #999;
}
.pay-box {
flex: 1;
width: 650rpx;
padding-right: 26rpx;
padding-left: 26rpx;
}
.pay-box button {
width: 300rpx;
height: 80rpx;
border: 1px solid #c21327;
text-align: center;
line-height: 78rpx;
border-radius: 10rpx;
font-size: 28rpx;
color: #4c4c4c;
}
.pay-box button label {
color: #c21327;
}
.pay-box .vip-btn {
color: #fff;
background: #c21327;
}
.evaluate-inner {
padding: 0 30rpx 30rpx;
background-color: #fff;
}
.evaluate-item {
padding: 20rpx 0 20rpx;
font-size: 26rpx;
color: #141414;
line-height: 32rpx;
}
.user-info {
margin-bottom: 30rpx;
}
.user-box {
height: 80rpx;
color: #333;
}
.user-box image {
width: 80rpx;
height: 80rpx;
will-change: transform;
margin-right: 20rpx;
border-radius: 100%;
}
.recommend-cont {
color: #676767;
font-size: 20rpx;
}
.recommend-cont image {
width: 23rpx;
height: 23rpx;
margin-left: 4rpx;
}
.recommend-cont text {
margin-left: 12rpx;
line-height: 1.8;
padding-top: 5rpx;
}
.eavluate {
line-height: 1.5;
border-bottom: 1px solid #eee;
}
.course-list {
padding: 0 20rpx;
background-color: #fff;
color: #1a1a1a;
}
.course-list .title {
padding-top: 50rpx;
font-size: 34rpx;
margin-bottom: 10rpx;
}
.course-item {
padding: 30rpx 0;
border-bottom: 1rpx solid #eee;
}
.course-item .course-before {
font-size: 28rpx;
width: 520rpx;
}
.course-item .name {
margin-bottom: 5rpx;
text-align: left;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.course-item.active .name {
color: #c21327;
}
.course-item .info {
font-size: 24rpx;
color: #666;
}
.course-item.active .palyer {
width: 24rpx;
height: 24rpx;
margin-left: 8rpx;
}
.experience-icon {
font-size: 22rpx;
color: #fff;
padding: 5rpx 8rpx;
background-color: #b6985b;
border-radius: 10rpx;
vertical-align: initial;
margin-left: 8rpx;
}
.course-after {
width: 130rpx;
height: 55rpx;
border: 1px solid #c21327;
color: #c21327;
border-radius: 26rpx;
text-align: center;
background-color: #ffeef0;
}
.course-after image {
width: 22rpx;
height: 22rpx;
margin-right: 6rpx;
}
.course-after.playered {
background-color: #fff;
}
.evaluate-btn {
padding: 20rpx 60rpx 50rpx;
}
.evaluate-btn .evaluate-btn-item {
width: 250rpx;
height: 80rpx;
line-height: 78rpx;
border: 1px solid #ccc;
border-radius: 40rpx;
font-size: 28rpx;
color: #666;
text-align: center;
margin: 0 auto;
}
.isPayShow {
display: block;
}
.isPayHide {
display: none;
}
.mast_video{
display:block;
width:60rpx;
height:60rpx;
right:10rpx;
position:absolute;
margin-top:165rpx;
text-align:center;
border-radius:50%;
z-index:11;
background-color: rgba(0,0,0,0.5);
}
.mast_video button{
font-size:28rpx;
line-height:60rpx;
color:#fff;
}
.change_mast{
width:100%;
height:430rpx;
position:relative;
z-index:13;
background-color: rgba(0,0,0,0.5);
}
.seed_change{
width:40%;
height:60rpx;
display:flex;
text-align:center;
position:absolute;
top:165rpx;
left:30%;
z-index:13;
}
.seed_change button{
flex:1;
color:#fff;
}
.process-container{
width:100%;
padding:1% 2% 1% 2%;
height:60rpx;
max-height:60rpx;
position:absolute;
bottom:4px;
left:0;
right:0;
z-index:13;
display:flex;
align-items: center;
background:rgba(59, 57, 57, 0.2);
}
.process-container image{
display:inline-block;
flex:1;
max-width:60rpx;
max-height:60rpx;
text-align:center;
}
.slider-container{
z-index:13;
height:60rpx;
margin-bottom:10rpx;
flex:6;
}
.video_btn{
flex:1;
}
.video_btn image{
width:80rpx;
height:80rpx;
}
.video_time{
flex:1;
}
.shares{
width:80rpx;
height:80rpx;
position:fixed;
right:10rpx;
bottom:160rpx;
display:flex;
flex-direction: column;
align-items: center;
background-color:#05b5eb;
color:white;
border-radius:50%;
z-index:1;
}
.shares text{
text-align:center;
font-size:24rpx;
color:#fff;
line-height:36rpx;
}
.video_back{
display:block;
width:60rpx;
height:60rpx;
left:5rpx;
top:15rpx;
position:absolute;
text-align:center;
z-index:19;
}
.video_back image{
width:44rpx;
height:44rpx;
}