Create Loop Button and functionality in video player

This commit is contained in:
Preston 2021-01-12 22:56:31 -05:00
parent fda38b1b21
commit 7be4bf28f2
3 changed files with 80 additions and 3 deletions

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="20px" height="20px"><path class="loop" d="M12 4V2.21c0-.45-.54-.67-.85-.35l-2.8 2.79c-.2.2-.2.51 0 .71l2.79 2.79c.32.31.86.09.86-.36V6c3.31 0 6 2.69 6 6 0 .79-.15 1.56-.44 2.25-.15.36-.04.77.23 1.04.51.51 1.37.33 1.64-.34.37-.91.57-1.91.57-2.95 0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-.79.15-1.56.44-2.25.15-.36.04-.77-.23-1.04-.51-.51-1.37-.33-1.64.34C4.2 9.96 4 10.96 4 12c0 4.42 3.58 8 8 8v1.79c0 .45.54.67.85.35l2.79-2.79c.2-.2.2-.51 0-.71l-2.79-2.79c-.31-.31-.85-.09-.85.36V18z"/></svg>

After

Width:  |  Height:  |  Size: 577 B

View File

@ -1,4 +1,5 @@
import Vue from 'vue'
import { mapActions } from 'vuex'
import FtCard from '../ft-card/ft-card.vue'
import $ from 'jquery'
@ -87,6 +88,7 @@ export default Vue.extend({
'remainingTimeDisplay',
'customControlSpacer',
'playbackRateMenuButton',
'loopButton',
'chaptersButton',
'descriptionsButton',
'subsCapsButton',
@ -156,6 +158,7 @@ export default Vue.extend({
}
this.createFullWindowButton()
this.createLoopButton()
this.determineFormatType()
this.determineMaxFramerate()
},
@ -533,6 +536,52 @@ export default Vue.extend({
}
},
createLoopButton: function () {
const v = this
const VjsButton = videojs.getComponent('Button')
const loopButton = videojs.extend(VjsButton, {
constructor: function(player, options) {
VjsButton.call(this, player, options)
},
handleClick: function() {
v.toggleVideoLoop()
},
createControlTextEl: function (button) {
return $(button).html($('<div id="loopButton" class="vjs-icon-loop loop-white vjs-button loopWhite"></div>')
.attr('title', 'Toggle Loop'))
}
})
videojs.registerComponent('loopButton', loopButton)
},
toggleVideoLoop: async function () {
if (!this.player.loop()) {
const currentTheme = localStorage.getItem('mainColor')
const colorNames = this.$store.state.utils.colorClasses
const colorValues = this.$store.state.utils.colorValues
const nameIndex = colorNames.findIndex((color) => {
return color === currentTheme
})
const themeTextColor = await this.calculateColorLuminance(colorValues[nameIndex])
$('#loopButton').addClass('vjs-icon-loop-active')
if (themeTextColor === '#000000') {
$('#loopButton').addClass('loop-black')
$('#loopButton').removeClass('loop-white')
}
this.player.loop(true)
} else {
$('#loopButton').removeClass('vjs-icon-loop-active')
$('#loopButton').removeClass('loop-black')
$('#loopButton').addClass('loop-white')
this.player.loop(false)
}
},
createFullWindowButton: function () {
const v = this
const VjsButton = videojs.getComponent('Button')
@ -827,6 +876,10 @@ export default Vue.extend({
break
}
}
}
},
...mapActions([
'calculateColorLuminance'
])
}
})

View File

@ -449,7 +449,6 @@ body.vjs-full-window {
content: url(assets/img/open_fullwindow.svg);
}
.vjs-icon-fullwindow-exit, .video-js.vjs-fullwindow .vjs-fullwindow-control .vjs-icon-placeholder {
font-family: VideoJS;
font-weight: normal;
@ -459,6 +458,30 @@ body.vjs-full-window {
content: url(assets/img/close_fullwindow.svg);
}
.vjs-icon-loop, .video-js .vjs-fullwindow-control .vjs-icon-placeholder {
color: white !important;
margin-top: 5px !important;
padding-top: 5px !important;
cursor: pointer;
}
.vjs-icon-loop-active {
background-color: var(--primary-color);
}
.vjs-icon-loop:before, .video-js.vjs-fullwindow .vjs-fullwindow-control .vjs-icon-placeholder:before {
content: url(assets/img/loop.svg);
/* filter: invert(1) drop-shadow(1px 0px 0px var(--primary-color)); */
}
.loop-black:before {
filter: brightness(0%);
}
.loop-white:before {
filter: none;
}
.vjs-full-window .video-js.vjs-fullscreen {
position: fixed;
overflow: hidden;