hi,好久不见,我是ly,好久不见,最近发生了许多新鲜的事物,我来了Blog。
2023,我将和大家分享,有趣的、轻松的、我认为的复杂的代码和事物。
在我的工作里,常用的是一下这些,最近有在研究cocos!
Num.one(小程序-支付宝小程序-微信小程序-钉钉小程序)
Num.two(后台管理)
pie title In my work: Technology Stack
"pig" : 30
"uniapp" : 85
"vue" : 100
分享一个视频(完整播放器)
组件展示+页面传值+组件代码的编译
<view>
<video-player autoplay :originalUrl="srcUrl" :title="title"
:poster="imgUrl" ></video-player>
</view>
<template>
<view:style="{width,height}"class="video-container">
<view v-if="!showVideo" class="loading-box">
<image class="loading-img abs-center" src="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-098edbd3-5122-424e-90ff-8c8635c9fd75/8ca2275a-f53f-40ef-b1f3-1051706135af.gif"></image>
</view>
<video
v-if="showVideo"
id="video-player"
class="video-box"
:src="playUrl"
:poster="posterUrl"
:autoplay="autoplay"
:loop="loop"
:muted="muted"
:page-gesture="pageGesture"
:enable-progress-gesture="enableProgressesture"
:show-mute-btn="showMuteBtn"
:enable-play-gesture="enablePlayGesture"
:vslide-gesture="vslideGesture"
:vslide-gesture-in-fullscreen="vslideGestureInFullscreen"
:show-center-play-btn="false"
:title="title"
@loadedmetadata="loadedmetadata"
@play="onPlay"
@pause="onPause"
@ended="onEnded"
@timeupdate="timeupdate"
@fullscreenchange="fullscreenchange"
@controlstoggle="controlstoggle"
>
<cover-view v-if="loading" class="loading-box text-white">
<cover-image
class="loading-img abs-center"
src="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-098edbd3-5122-424e-90ff-8c8635c9fd75/8ca2275a-f53f-40ef-b1f3-1051706135af.gif"
></cover-image>
</cover-view>
<cover-view v-if="showPlay && !autoplay" class="play-box abs-center" @click="onCenterPlayBtnClick">
<cover-image
class="play-img"
src="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-098edbd3-5122-424e-90ff-8c8635c9fd75/a8a12b71-eca3-423a-81fa-3adac1d5ac1f.png"
></cover-image>
</cover-view>
<cover-image
v-if="showMenuBtn"
class="more"
src="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-098edbd3-5122-424e-90ff-8c8635c9fd75/1490996b-eeee-4545-95b7-d61e66234b80.png"
@click="moreBtnClick"
></cover-image>
<cover-view v-if="showMenu" class="menu-box" style="color: #fff;">
<cover-view class="video-speed-box">
<cover-view>播放速度</cover-view>
<cover-view class="speed-wrapper">
<cover-view
class="speed-item"
v-for="item in speedList"
:key="item"
:class="[item === currentSpeed ? 'speed-item-active' : 'speed-item-diactive']"
@click="onChangeSpeed(item)"
>
{{ item }}倍
</cover-view>
</cover-view>
</cover-view>
<cover-view class="video-quality-box">
<cover-view>清晰度</cover-view>
<cover-view class="quality-wrapper">
<cover-view
class="speed-item"
v-for="item in qualityList"
:key="item.value"
:class="[item.value === currentQuality ? 'speed-item-active' : 'speed-item-diactive']"
@click="onChangeQuality(item.value)"
>
{{ item.text }}
</cover-view>
</cover-view>
</cover-view>
</cover-view>
</video>
<uni-popup ref="popup" type="bottom" background-color="#fff">
<view class="popup-box">
<view style="margin-top: 12rpx;">
<view>播放速度</view>
<view class="speed-box">
<view
class="speed-item"
v-for="item in speedList"
:key="item"
:class="[item === currentSpeed ? 'speed-item-active' : 'speed-item-diactive']"
@click="onChangeSpeed(item)"
>
{{ item }}倍
</view>
</view>
</view>
<view style="margin-top: 40rpx;">
<view>清晰度</view>
<view class="speed-box">
<view
class="speed-item"
v-for="item in qualityList"
:key="item.value"
:class="[item.value === currentQuality ? 'speed-item-active' : 'speed-item-diactive']"
@click="onChangeQuality(item.value)"
>
{{ item.text }}
</view>
</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import throttle from 'lodash/throttle'
const throttled = throttle(
function(e) {
const { currentTime } = e.detail
this.playProgress = currentTime
this.$emit('timeupdate', e)
},
2000,
{
leading: false
}
)
export default {
props: {
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '450rpx'
},
// 标清播放地址
standardUrl: {
type: String,
required: true
},
// 高清播放地址
highUrl: {
type: String,
default: ''
},
// 超高清播放地址
ultraUrl: {
type: String,
default: ''
},
// 原画播放地址
originalUrl: {
type: String,
default: ''
},
posterUrl: {
type: String,
default: ''
},
autoplay: {
type: Boolean,
default: false
},
loop: {
type: Boolean,
default: false
},
muted: {
type: Boolean,
default: false
},
initialTime: {
type: Number,
default: 0
},
direction: {
type: Number,
default: 90
},
objectFit: {
type: String,
default: 'contain'
},
title: {
type: String,
default: '视频播放'
},
pageGesture: {
type: Boolean,
default: true
},
enableProgressesture: {
type: Boolean,
default: true
},
showMuteBtn: {
type: Boolean,
default: false
},
enablePlayGesture: {
type: Boolean,
default: false
},
vslideGesture: {
type: Boolean,
default: false
},
vslideGestureInFullscreen: {
type: Boolean,
default: false
}
},
data() {
return {
// 0 标清
// 1 高清
// 2 超高清
// 3 原画
loading: true,
showPlay: false,
videoContext: null,
currentSpeed: 1,
speedList: [0.5, 0.8, 1, 1.25, 1.5, 2],
showVideo: false,
playProgress: 0,
hasChangeQuality: false,
hasFullScreen: false,
showMenu: false,
showMenuBtn: false,
currentQuality: -1
}
},
computed: {
urlChange() {
const { standardUrl, highUrl, ultraUrl, originalUrl } = this
return { standardUrl, highUrl, ultraUrl, originalUrl }
},
playUrl() {
let url = ''
const { standardUrl, highUrl, ultraUrl, originalUrl, currentQuality } = this
switch (currentQuality) {
case 0:
url = standardUrl
break
case 1:
url = highUrl
break
case 2:
url = ultraUrl
break
case 3:
url = originalUrl
break
}
return url
},
qualityList() {
const list = []
this.standardUrl &&
list.push({
text: '标清',
value: 0
})
this.highUrl &&
list.push({
text: '高清',
value: 1
})
this.ultraUrl &&
list.push({
text: '超清',
value: 2
})
this.originalUrl &&
list.push({
text: '原画',
value: 3
})
return list
}
},
watch: {
urlChange(val) {
this.initQuality()
},
initialTime(value) {
if (!this.videoContext) {
this.videoContext = uni.createVideoContext('video-player', this)
}
setTimeout(() => {
this.playProgress = value
this.videoContext.seek(value)
}, 300)
}
},
created() {
if (this.initialTime) {
this.playProgress = this.initialTime
}
this.initQuality()
},
mounted() {
this.videoContext = uni.createVideoContext('video-player', this)
},
methods: {
initQuality() {
let quality = -1
const { standardUrl, highUrl, ultraUrl, originalUrl } = this
if (standardUrl) {
quality = 0
} else if (highUrl) {
quality = 1
} else if (ultraUrl) {
quality = 2
} else if (originalUrl) {
quality = 3
}
if (quality !== -1) {
this.currentQuality = quality
this.playProgress = 0
this.initVideo()
this.emitQualityChange()
}
},
timeupdate: throttled,
initVideo() {
this.showVideo = false
setTimeout(() => {
this.showVideo = true
this.loading = true
this.videoContext = uni.createVideoContext('video-player', this)
}, 300)
},
onChangeQuality(value) {
if (value !== this.currentQuality) {
throttled.cancel
this.hasChangeQuality = true
this.currentQuality = value
this.initVideo()
this.emitQualityChange()
}
this.$refs.popup.close()
this.showMenu = false
},
onChangeSpeed(value) {
this.currentSpeed = value
this.videoContext.playbackRate(value)
this.$refs.popup.close()
this.showMenu = false
},
moreBtnClick() {
if (this.hasFullScreen) {
this.showMenu = true
} else {
this.$refs.popup.open()
}
},
controlstoggle(e) {
const show = e.detail.show
if (show) {
this.showMenuBtn = true
} else {
this.showMenuBtn = false
this.showMenu = false
}
},
fullscreenchange(e) {
this.hasFullScreen = e.detail.fullscreen
},
onPlay() {
this.showPlay = false
this.playing = true
},
onPause() {
if (this.hasChangeQuality) return
this.playing = false
},
onEnded() {
this.$emit('ended')
if (this.autoplay) return
this.playing = false
this.playProgress = 0
throttled.cancel
this.showPlay = true
},
onCenterPlayBtnClick() {
this.showPlay = false
this.videoContext.play()
},
loadedmetadata() {
this.loading = false
this.showPlay = true
this.videoContext.seek(this.playProgress)
this.playing && this.videoContext.play()
this.hasChangeQuality = false
},
onTimeupdate(e) {
this.loading && (this.loading = false)
},
emitQualityChange() {
this.$emit('qualitychange', this.currentQuality)
}
}
}
</script>
<style lang="scss" scoped>
.speed-box {
margin-top: 28rpx;
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 16rpx;
font-size: 24rpx;
.speed-item {
text-align: center;
padding: 12rpx 0;
border-radius: 8rpx;
}
.speed-item-diactive {
border: 1rpx solid #eee;
}
.speed-item-active {
background-color: #2979ff;
color: #fff;
}
}
.popup-box {
padding: 28rpx;
}
.abs-center {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.video-container {
position: relative;
background-color: #000;
box-sizing: border-box;
.loading-box {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 3;
background-color: #000;
.loading-img {
width: 80rpx;
height: 80rpx;
}
}
}
.video-box {
width: 100%;
height: 100%;
.menu-box {
position: absolute;
right: 0;
top: 0;
width: 60%;
height: 100%;
background-color: #000;
padding: 28rpx var(--status-bar-height);
z-index: 4;
box-sizing: border-box;
font-size: 24rpx;
display: flex;
flex-direction: column;
justify-content: center;
.video-quality-box {
margin-top: 28rpx;
}
.speed-wrapper,
.quality-wrapper {
display: flex;
flex-wrap: wrap;
margin-top: 28rpx;
}
.speed-item {
width: 110rpx;
padding: 20rpx 0;
text-align: center;
}
.speed-item-active {
color: #2979ff;
}
}
.more {
position: absolute;
width: 50rpx;
height: 50rpx;
right: var(--status-bar-height);
top: var(--status-bar-height);
}
.play-box {
width: 90rpx;
height: 90rpx;
background-color: rgba(#fff, 0.8);
border-radius: 2000px;
display: flex;
align-items: center;
justify-content: center;
.play-img {
width: 70rpx;
height: 70rpx;
}
}
}
</style>
你有更好的方法,可以留言。大家一起畅所欲言,在知识的海洋里,博览代码桥段,希望我们的2023年都能实现我们自己想要的目标,祝大家每天快乐。