Мало знаний, большой вызов! Эта статья участвует в "Необходимые знания для программистов«Творческая деятельность.
Эта статья приняла участие"Проект "Звезда раскопок"", чтобы выиграть творческий подарочный пакет и бросить вызов творческим поощрительным деньгам.
🎯Предисловие
Воспроизведение видео, возможно, не является обычным явлением в повседневных бизнес-сценариях, но оно определенно не является чем-то необычным.Выбор простого в использовании подключаемого модуля часто более эффективен при меньших усилиях. Сегодня автор представит сцену, чтобы представитьByteDanceОткрытый исходный кодАрбузный игрок (щелкните по нему), многие функции очень мощные 😎.
В этой статье используетсяVue+Xgplayer
URL тестового видео: sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-360p.mp4
Данные videoList можно гибко обрабатывать, короче говоря, нужны только URL-адрес видео и URL-адрес изображения.
🎯 Ожидаемые результаты
Видео с арбузом имеет такой эффект предварительного просмотра (он есть на многих видеосайтах), и наш сегодняшний контент — это этот эффект
🎯 Конечный эффект
🎯 xgplayer прост в использовании
🫀 Установите xgplayer
npm install xgplayer
Внедрить и инициализировать в требуемом компоненте vue
import Player from 'xgplayer'
let player = new Player({
id:'' , //标签的id名或者 使用 el:dom元素
url: 视频url,
videoInit: true,
poster: 封面图,
controls: false,
playbackRate: [0.5, 0.75, 1, 1.5, 2],
whitelist: [
''
],
fluid: false,
// download: true,
width: '100%',
height: '200px'
})
Это создаст видеоплеер, который можно создать в указанном контейнере.
🎯 Реализация идеи
В приведенном выше полном эффекте этот случай, очевидно, представляет собой несколько контейнеров, которые зациклены. Здесь нам нужно рассмотреть проблему экземпляров Player, создавать ли один или несколько. Здесь есть две идеи. В этой статье принимаетсяПервый. Кстати, данные в реальном бизнесе идут от сервиса интерфейса (яма тут).
1. Создайте несколько контейнеров в цикле и создайте экземпляр для каждого из них.Последовательная загрузка вызовет проблему слишком большого количества экземпляров, чтобы избежать этого, можно использовать пейджинг.
2. Контейнер создается в цикле, экземпляр не создается, отображается только обложка, предыдущий экземпляр уничтожается при перемещении в контейнер, а текущий экземпляр создается (Сравните оптимальное решение), читатели могут попробовать.
По эффекту нетрудно заметить, что видео воспроизводится при его перемещении в контейнер, а текущее видео перемещается при его перемещении наружу.Пауза, который поддерживает только одно воспроизведение за раз. Здесь я подготовил слой обложки img и слой видео видео, слой изображения отображается по умолчанию, а два события mouseEnter и mouseleave используются для динамического управления отображением и сокрытием соответствующего контейнера (там тоже есть небольшая ямка) и работать с экземпляром соответствующего индекса ( приостановить, уничтожить и т. д.).
startPlay(data,index){
this.$refs['img'+index][0].style.display="none"
this.$refs['video'+index][0].style.display="block"
this.$nextTick(()=>{
this.dom[index].play()
})
},
move(data,index){
this.$refs['img'+index][0].style.display="block"
setTimeout(() => {
this.dom[index].pause()
}, 0);
this.$refs['video'+index][0].style.display="none"
},
🎯 полный код
<template>
<div class="video">
<div class="video-content" id="videoScroll" ref="videoScrollBar">
<div class="card" v-for="(item,index) in videoList" :key="index" >
<div style="width:100%;height:200px"
@mouseenter="startPlay(item,index)"
@mouseleave="move(item,index)">
<div
:ref="`img${index}`"
style="width:100%;height:200px;background-size: cover;"
:style="{'background-image':`url(${item.spsltlj+'/'+item.spslt}) `}">
</div>
<div style="display:none;overflow:hidden" :ref="`video${index}`">
</div>
</div>
<div class="title">
{{item.spmc}}
</div>
</div>
</div>
</div>
</template>
<script>
import Player from 'xgplayer'
import { loadVideoList } from "@/api/video"
export default {
name: 'Video',
components: {
TitleField: Title
},
data () {
return {
// 视频的url由 splj+spbh组成,缩略图poster由spsltlj+spslt组成
videoList:[
{
splj:'',
spbh:'',
spsltlj:'',
spslt:''
}
],
dom:[],
}
},
created() {
this.setBaseList()
},
mounted() {
},
methods: {
async setBaseList(){
const res =await loadVideoList(this.form)
this.videoList=res.data.records
setTimeout(() => {
if(this.videoList.length){
this.videoList.forEach((item,index)=>{
this.init(item,index)
},1000)
}else{
this.dom.length=0
}
})
},
init (data,index) {
this.dom[index]= new Player({
el: this.$refs['video'+index][0],
url: data.splj+'/'+data.spbh,
videoInit: true,
poster:data.spsltlj+'/'+data.spslt, //封面图
// cssFullscreen: true,
lang: 'zh-cn',
controls: false,
playbackRate: [0.5, 0.75, 1, 1.5, 2],
whitelist: [
''
],
ignores: ['play'],
fluid: false,
// download: true,
width: '100%',
height: '200px'
})
},
startPlay(data,index){
this.$refs['img'+index][0].style.display="none"
this.$refs['video'+index][0].style.display="block"
this.$nextTick(()=>{
this.dom[index].play()
})
},
move(data,index){
this.$refs['img'+index][0].style.display="block"
setTimeout(() => {
this.dom[index].pause()
}, 0);
this.$refs['video'+index][0].style.display="none"
},
}
}
</script>
<style scoped lang = "less">
.card{
width: 18%;
margin: 0 20px 20px 0;
float: left;
}
.title{
width: 100%;
color: #000;
height:40px;
line-height: 40px;
background-color: #ffffff;
font-weight: 600;
padding-left: 10px;
}
</style>
🎯 Две маленькие ямы
🫀 Проблема инициализации экземпляра до загрузки данных
Здесь таймер используется для задержки выполнения.Если цикл зациклен напрямую, арбузный проигрыватель сообщит об ошибке при воспроизведении.Вообще говоря, экземпляр не был инициализирован. Точно так же в событии воспроизведения вызовите метод play для воспроизведения после загрузки DOM.
async setBaseList(){
const res =await loadVideoList(this.form)
this.videoList=res.data.records
setTimeout(() => {
if(this.videoList.length){
this.videoList.forEach((item,index)=>{
this.init(item,index) //初始化视频实例
},1000)
}else{
this.dom.length=0
}
})
},
🫀 mouseenter и mouseleave
При использовании цикла v-for к родительскому элементу следует добавить mouseenter и mouseleave.
<div class="card" v-for="(item,index) in videoList" :key="index" >
<div style="width:100%;height:200px"
@mouseenter="startPlay(item,index)"
@mouseleave="move(item,index)">
<div
:ref="`img${index}`"
style="width:100%;height:200px;background-size: cover;"
:style="{'background-image':`url(${item.spsltlj+'/'+item.spslt}) `}">
</div>
<div style="display:none;overflow:hidden" :ref="`video${index}`">
</div>
</div>
<div class="title">
{{item.spmc}}
</div>
</div>
🎯Сводка
Выше приведено простое демонстрационное введение видео с арбузом, более мощные функции могут бытьОфициальный сайтОпыт, такой как заградительный огонь, картинка в картинке с некоторыми простыми конфигурациями. В дополнение к этому, этот плагин с открытым исходным кодом может не только воспроизводить видео, но ипрямая трансляция, можно использовать не только на ПК, но и на мобильных устройствах.
🎯 Прошлые статьи
🎉Напишите диаграмму Ганта с низкой имитацией с помощью Echarts (конкретно для секунд)
Написание диаграммы Ганта с низкой имитацией почерка с точностью до секунды
Teleport, новые функции Vue3.0 в "Free Gate
Проблема проходки компонента мобильного подборщика Наступление на яму
Ant Design of Vue не имеет api общей строки таблицы, другой способ мышления