VideoPlayer.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. <template>
  2. <div ref="videoPlayerWrapper"
  3. class="vPlayer">
  4. <video ref="videoPlayer"
  5. dir="ltr"
  6. class="video-js vjs-fluid vjs-big-play-centered vjs-show-big-play-button-on-pause"
  7. controls
  8. preload="none">
  9. <p class="vjs-no-js">
  10. To view this video please enable JavaScript, and consider upgrading to a web browser that
  11. <a href="https://videojs.com/html5-video-support/"
  12. target="_blank">
  13. supports HTML5 video
  14. </a>
  15. </p>
  16. </video>
  17. <div class="VastElements">
  18. <div ref="VastTimerBtn"
  19. class="VastElement VastTimerBtn hide" />
  20. <div ref="VastSkipAdBtn"
  21. class="VastElement VastSkipAdBtn hide">
  22. رد کردن
  23. </div>
  24. <div ref="VastLinkBtn"
  25. class="VastElement VastLinkBtn hide">
  26. اطلاعات بیشتر
  27. </div>
  28. </div>
  29. <div v-if="useOverPlayer && !isInVastMode"
  30. ref="overPlayer"
  31. class="over-player-wrapper">
  32. <q-btn icon-right="isax:menu-1"
  33. size="sm"
  34. color="primary"
  35. class="toggleSideBarBtn"
  36. @click="toggleSideBar" />
  37. <div class="over-player-slot"
  38. :class="{'show': localOverPlayer, 'hide': !localOverPlayer}"
  39. :style="{width: overPlayerWidth}">
  40. <slot name="overPlayer" />
  41. </div>
  42. </div>
  43. </div>
  44. </template>
  45. <script>
  46. import videojs from 'video.js'
  47. import 'videojs-hls-quality-selector'
  48. import videojsBrand from 'videojs-brand'
  49. import fa from 'video.js/dist/lang/fa.json'
  50. import { APIGateway } from 'src/api/APIGateway.js'
  51. // import { mixinAbrisham } from 'src/mixin/Mixins.js'
  52. import { PlayerSourceList } from 'src/models/PlayerSource.js'
  53. import videoJsResolutionSwitcher from 'src/assets/js/videoJsResolutionSwitcher.js'
  54. // https://cph-p2p-msl.akamaized.net/hls/live/2000341/test/master.m3u8 (Live)
  55. // https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8
  56. export default {
  57. name: 'VideoPlayer',
  58. // mixins: [mixinAbrisham],
  59. props: {
  60. hasVast: {
  61. type: Boolean,
  62. default: false
  63. },
  64. source: {
  65. type: [String, PlayerSourceList],
  66. default: null
  67. },
  68. useOverPlayer: {
  69. type: Boolean,
  70. default: false
  71. },
  72. poster: {
  73. type: String,
  74. default () {
  75. return ''
  76. }
  77. },
  78. overPlayer: {
  79. type: Boolean,
  80. default: true
  81. },
  82. overPlayerWidth: {
  83. type: String,
  84. default: '100%'
  85. },
  86. keepCalculating: {
  87. type: Boolean,
  88. default () {
  89. return true
  90. }
  91. },
  92. bookmarkLoading: {
  93. type: Boolean,
  94. default () {
  95. return false
  96. }
  97. },
  98. currentTimed: {
  99. type: Number
  100. }
  101. },
  102. emits: ['seeked', 'adStarted', 'update:sideBar'],
  103. data() {
  104. return {
  105. needReInitVideo: false,
  106. isInVastMode: false,
  107. vastSrc: null,
  108. vastLink: null,
  109. vastSkipOffset: null,
  110. vastStartOffset: null,
  111. vastTimerInterval: null,
  112. width: '',
  113. showVastElements: false,
  114. drawer: false,
  115. player: null,
  116. localOverPlayer: true,
  117. favLoading: false,
  118. options: {
  119. myItems: [{
  120. name: 'test'
  121. }],
  122. controlBar: {
  123. // currentTimeDisplay: true,
  124. TimeDivider: true,
  125. children: [
  126. 'playToggle',
  127. 'PlaybackRateMenuButton',
  128. 'CurrentTimeDisplay',
  129. 'progressControl',
  130. 'TimeDivider',
  131. 'RemainingTimeDisplay',
  132. 'volumePanel',
  133. 'SubtitlesButton',
  134. 'QualitySelector',
  135. 'fullscreenToggle',
  136. 'PictureInPictureToggle'
  137. ],
  138. volumePanel: {
  139. inline: true,
  140. vertical: true
  141. }
  142. },
  143. language: 'fa',
  144. languages: {
  145. fa
  146. },
  147. responsive: true,
  148. autoplay: false,
  149. controls: true,
  150. playbackRates: [0.5, 1, 1.5, 2, 3, 4],
  151. nativeControlsForTouch: false,
  152. sources: [],
  153. poster: null,
  154. plugins: {
  155. // hotkeys: {
  156. // enableModifiersForNumbers: false,
  157. // seekStep: 5,
  158. // enableMute: true,
  159. // enableVolumeScroll: true,
  160. // enableHoverScroll: true,
  161. // enableFullscreen: true
  162. // }
  163. }
  164. },
  165. videoIsPlaying: false,
  166. postIsFavored: {}
  167. }
  168. },
  169. computed: {
  170. calcTheHeight() {
  171. return '100%'
  172. },
  173. calcTheWidth() {
  174. return '100%'
  175. },
  176. currentTime() {
  177. return this.currentTimed
  178. }
  179. },
  180. watch: {
  181. source: {
  182. handler () {
  183. if (typeof window === 'undefined') {
  184. return
  185. }
  186. this.$nextTick(() => {
  187. if (this.$refs.videoPlayer) {
  188. this.reInitVideo()
  189. } else {
  190. this.needReInitVideo = true
  191. }
  192. })
  193. },
  194. immediate: true
  195. },
  196. currentTime(time) {
  197. this.player.currentTime(time)
  198. },
  199. overPlayer(newValue) {
  200. this.localOverPlayer = newValue
  201. },
  202. useOverPlayer (newValue) {
  203. if (!newValue) {
  204. return
  205. }
  206. this.$nextTick(() => {
  207. this.moveSideBarElementIntoVideoPlayerElements()
  208. })
  209. }
  210. },
  211. created() {
  212. this.width = this.overPlayerWidth
  213. this.setPoster()
  214. this.setSources()
  215. },
  216. mounted() {
  217. if (this.needReInitVideo) {
  218. this.$nextTick(() => {
  219. this.reInitVideo()
  220. })
  221. }
  222. if (this.useOverPlayer) {
  223. this.$nextTick(() => {
  224. this.moveSideBarElementIntoVideoPlayerElements()
  225. })
  226. }
  227. },
  228. beforeUnmount() {
  229. if (this.player) {
  230. this.player.dispose()
  231. }
  232. },
  233. methods: {
  234. getVast () {
  235. return APIGateway.vast.getXml()
  236. .then((vastXml) => {
  237. this.loadVast(vastXml)
  238. })
  239. .catch(() => {
  240. })
  241. },
  242. showVastElement (vastClassName) {
  243. this.removeVastClass(vastClassName, 'hide')
  244. this.addVastClass(vastClassName, 'show')
  245. },
  246. hideVastElement (vastClassName) {
  247. this.removeVastClass(vastClassName, 'show')
  248. this.addVastClass(vastClassName, 'hide')
  249. },
  250. addVastClass (vastClassName, classValue) {
  251. const vastElement = this.vastElementExist(vastClassName)
  252. if (!vastElement) {
  253. return false
  254. }
  255. vastElement.classList.add(classValue)
  256. },
  257. removeVastClass (vastClassName, classValue) {
  258. const vastElement = this.vastElementExist(vastClassName)
  259. if (!vastElement) {
  260. return false
  261. }
  262. vastElement.classList.remove(classValue)
  263. },
  264. vastElementExist (vastClassName) {
  265. const vastElement = this.$refs.videoPlayerWrapper.getElementsByClassName(vastClassName)[0]
  266. if (!vastElement) {
  267. return false
  268. }
  269. return vastElement
  270. },
  271. loadVastDomElements () {
  272. this.injectDomeElement(this.$refs.VastTimerBtn)
  273. this.injectDomeElement(this.$refs.VastSkipAdBtn)
  274. this.injectDomeElement(this.$refs.VastLinkBtn)
  275. },
  276. showVastLinkBtn (link, title = 'اطلاعات بیشتر') {
  277. this.showVastElement('VastLinkBtn')
  278. this.updateVastElementInnerHTML('VastLinkBtn', '<a href="' + link + '" target="_blank">' + title + '</a>')
  279. },
  280. stopVastTimer () {
  281. if (this.vastTimerInterval) {
  282. clearInterval(this.vastTimerInterval)
  283. }
  284. this.updateVastTimer(0)
  285. this.hideVastElement('VastTimerBtn')
  286. },
  287. startVastTimer (endTimerCallback) {
  288. this.showVastElement('VastTimerBtn')
  289. if (this.vastTimerInterval) {
  290. clearInterval(this.vastTimerInterval)
  291. }
  292. let seconds = this.getVastTimerSeconds()
  293. if (seconds === 0) {
  294. this.stopVastTimer()
  295. return
  296. }
  297. this.updateVastTimer(seconds--)
  298. this.vastTimerInterval = setInterval(() => {
  299. this.updateVastTimer(seconds--)
  300. if (seconds < 0) {
  301. this.stopVastTimer()
  302. endTimerCallback()
  303. }
  304. }, 1000)
  305. },
  306. getVastTimerSeconds () {
  307. if (!this.vastSkipOffset) {
  308. return 0
  309. }
  310. const array = this.vastSkipOffset.split(':')
  311. return (array[0] * 60 * 60) + (array[1] * 60) + array[2]
  312. },
  313. updateVastTimer (timer) {
  314. this.updateVastElementInnerHTML('VastTimerBtn', timer + ' ثانیه')
  315. },
  316. updateVastElementInnerHTML (vastClassName, innerHTML) {
  317. const vastElement = this.vastElementExist(vastClassName)
  318. if (!vastElement) {
  319. return false
  320. }
  321. vastElement.innerHTML = innerHTML
  322. },
  323. sowVastSkipAdBtn () {
  324. const vastClassName = 'VastSkipAdBtn'
  325. this.showVastElement(vastClassName)
  326. const vastElement = this.vastElementExist(vastClassName)
  327. if (!vastElement) {
  328. return false
  329. }
  330. vastElement.addEventListener('click', (event) => {
  331. this.endVast()
  332. })
  333. },
  334. loadVast (vastXml) {
  335. const parser = new DOMParser()
  336. const xmlDoc = parser.parseFromString(vastXml, 'text/xml')
  337. this.vastSrc = xmlDoc.getElementsByTagName('MediaFile')[0].childNodes[0].nodeValue
  338. this.vastLink = xmlDoc.getElementsByTagName('ClickThrough')[0].childNodes[0].nodeValue
  339. this.vastStartOffset = xmlDoc.getElementsByTagName('Linear')[0].getAttribute('startoffset')
  340. this.vastSkipOffset = xmlDoc.getElementsByTagName('Linear')[0].getAttribute('skipoffset')
  341. this.player.addClass('vjs-ad-playing')
  342. setTimeout(() => {
  343. this.isInVastMode = true
  344. const playerSourceList = new PlayerSourceList([{
  345. src: this.vastSrc,
  346. type: 'video/mp4',
  347. label: 'کیفیت عالی',
  348. caption: 'کیفیت عالی',
  349. link: this.vastSrc,
  350. res: 720,
  351. selected: false
  352. }])
  353. const source = this.isPlayerSourceList() ? playerSourceList.list : this.vastSrc
  354. this.player.src(source)
  355. }, 100)
  356. this.player.one('play', () => {
  357. this.player.controlBar.progressControl.disable()
  358. this.loadVastDomElements()
  359. this.showVastLinkBtn(this.vastLink)
  360. this.startVastTimer(() => {
  361. this.sowVastSkipAdBtn()
  362. })
  363. this.$emit('adStarted')
  364. })
  365. this.player.one('ended', () => {
  366. if (!this.isInVastMode) {
  367. return
  368. }
  369. this.endVast()
  370. })
  371. },
  372. startVast (vastXml) {
  373. const parser = new DOMParser()
  374. const xmlDoc = parser.parseFromString(vastXml, 'text/xml')
  375. this.vastSrc = xmlDoc.getElementsByTagName('MediaFile')[0].childNodes[0].nodeValue
  376. this.vastLink = xmlDoc.getElementsByTagName('ClickThrough')[0].childNodes[0].nodeValue
  377. this.vastStartOffset = xmlDoc.getElementsByTagName('Linear')[0].getAttribute('startoffset')
  378. this.vastSkipOffset = xmlDoc.getElementsByTagName('Linear')[0].getAttribute('skipoffset')
  379. // in a real plugin, you might fetch ad inventory here
  380. this.player.trigger('adsready')
  381. },
  382. endVast () {
  383. this.isInVastMode = false
  384. this.player.controlBar.progressControl.enable()
  385. this.hideVastElement('VastTimerBtn')
  386. this.hideVastElement('VastSkipAdBtn')
  387. this.hideVastElement('VastLinkBtn')
  388. this.player.removeClass('vjs-ad-playing')
  389. // setTimeout(() => {
  390. this.setPoster()
  391. this.setSources()
  392. const source = this.isPlayerSourceList() ? this.source.list : this.source
  393. this.player.src(source)
  394. this.player.poster(this.poster)
  395. // this.player.reset()
  396. this.player.play()
  397. // }, 100)
  398. this.$emit('adEnded')
  399. },
  400. focusOnPlayer () {
  401. this.player.el().focus()
  402. },
  403. setPlayerBrand () {
  404. this.player.brand({
  405. image: 'https://nodes.alaatv.com/upload/landing/chatr/alaa%20logo.png?w=30&h=30',
  406. title: 'پالیزوانی',
  407. destination: '/',
  408. destinationTarget: '_blank'
  409. })
  410. },
  411. redefineTap () {
  412. this.player.on('touchend', function(e) { // tap
  413. if (this.player().controls()) {
  414. const classes = [
  415. 'vjs-tech'
  416. ]
  417. const canDoAction = !classes.find(className => e.target.classList.contains(className))
  418. if (canDoAction) {
  419. return
  420. }
  421. if (this.player().paused()) {
  422. this.player().play()
  423. } else {
  424. this.player().pause()
  425. }
  426. }
  427. })
  428. },
  429. hasPlugin (pluginName) {
  430. return Object.keys(videojs.getPlugins()).includes(pluginName)
  431. },
  432. initPlayer (withVast) {
  433. if (!this.hasPlugin('brand')) {
  434. videojs.registerPlugin('brand', videojsBrand)
  435. }
  436. // if (this.isPlayerSourceList(this.source) && !this.hasPlugin('videoJsResolutionSwitcher')) { // old multiple quality type
  437. if (this.isPlayerSourceList(this.source)) { // old multiple quality type
  438. videoJsResolutionSwitcher(videojs)
  439. this.options.plugins.videoJsResolutionSwitcher = {
  440. default: 'کیفیت بالا',
  441. dynamicLabel: true
  442. }
  443. }
  444. this.player = videojs(this.$refs.videoPlayer, this.options)
  445. if (this.hasVast && (typeof withVast === 'undefined' || withVast === true)) {
  446. // this.loadVast()
  447. this.getVast()
  448. }
  449. this.player.ready(() => {
  450. this.setPlayerBrand()
  451. this.focusOnPlayer()
  452. this.redefineTap()
  453. // this.on('timeupdate', function () {
  454. // if (that.keepCalculating) {
  455. // that.calcWatchedPercentage(this.currentTime(), this.duration())
  456. // }
  457. // // document.querySelector('.video-js').focus()
  458. // if (that.$refs.videoPlayer) {
  459. // that.$refs.videoPlayer.focus()
  460. // }
  461. // if (!that.player.paused() && !that.player.userActive()) {
  462. // that.videoStatus(false)
  463. // } else if (!that.player.paused()) {
  464. // that.videoStatus(true)
  465. // }
  466. // })
  467. })
  468. if (typeof this.source === 'string' && this.source.includes('.m3u8')) { // hls type
  469. this.player.hlsQualitySelector()
  470. }
  471. this.player.on('seeked', () => {
  472. this.$emit('seeked', this.player.currentTime())
  473. })
  474. // const events = [
  475. // 'loadstart',
  476. // 'progress',
  477. // 'suspend',
  478. // 'abort',
  479. // 'error',
  480. // 'emptied',
  481. // 'stalled',
  482. // 'loadedmetadata',
  483. // 'loadeddata',
  484. // 'canplay',
  485. // 'canplaythrough',
  486. // 'playing',
  487. // 'waiting',
  488. // 'seeking',
  489. // 'seeked',
  490. // 'ended',
  491. // 'durationchange',
  492. // 'timeupdate',
  493. // 'play',
  494. // 'pause',
  495. // 'ratechange',
  496. // 'resize',
  497. // 'volumechange'
  498. // ]
  499. //
  500. // events.forEach(event => {
  501. // this.player.on(event, () => {
  502. // console.log('event: ', event)
  503. // console.log('sources: ', this.player.sources)
  504. // })
  505. // })
  506. },
  507. changeCurrentTime (time) {
  508. if (!this.player) {
  509. return
  510. }
  511. this.player.currentTime(time)
  512. },
  513. injectDomeElement (element) {
  514. this.$refs.videoPlayerWrapper.querySelector('.video-js').appendChild(element)
  515. },
  516. createDomeElement (elementClass, refKey) {
  517. const div = document.createElement('div')
  518. div.classList = elementClass
  519. const child = this.$refs[refKey].$el ? this.$refs[refKey].$el : this.$refs[refKey]
  520. div.appendChild(child)
  521. this.$refs.videoPlayerWrapper.querySelector('.video-js').appendChild(div)
  522. },
  523. moveSideBarElementIntoVideoPlayerElements () {
  524. this.createDomeElement('over-player-wrapper-div', 'overPlayer')
  525. },
  526. toggleSideBar () {
  527. this.localOverPlayer = !this.localOverPlayer
  528. // this.$emit('update:sideBar', this.localOverPlayer)
  529. },
  530. activate(time) {
  531. this.player.currentTime(time)
  532. this.player.play()
  533. const requiredElement = document.querySelector('.video-js')
  534. requiredElement.focus()
  535. },
  536. setSources(sources) {
  537. this.options.sources = sources || (this.isPlayerSourceList() ? this.source.list : this.source)
  538. },
  539. setPoster(poster) {
  540. this.options.poster = poster || this.poster
  541. },
  542. reInitVideo(withVast) {
  543. if (this.player?.reset) {
  544. this.player.reset()
  545. }
  546. // this.player.dispose()
  547. this.setPoster()
  548. this.setSources()
  549. this.initPlayer(withVast)
  550. const source = this.isPlayerSourceList() ? this.source.list : this.source
  551. this.player.src(source)
  552. this.player.poster(this.poster)
  553. },
  554. isPlayerSourceList () {
  555. return (this.source && this.source.list && Array.isArray(this.source.list))
  556. },
  557. calcWatchedPercentage(currentTime, duration) {
  558. const watchedPercentage = ((currentTime / duration) * 100)
  559. const videoPlayerTimeData = {
  560. currentTime,
  561. duration,
  562. watchedPercentage
  563. }
  564. this.$emit('calcTimeData', videoPlayerTimeData)
  565. },
  566. videoStatus(val) {
  567. this.videoIsPlaying = val
  568. },
  569. toggleFullScreen() {
  570. if (document.exitFullscreen) {
  571. document.exitFullscreen()
  572. } else if (document.webkitExitFullscreen) { /* Safari */
  573. document.webkitExitFullscreen()
  574. } else if (document.msExitFullscreen) { /* IE11 */
  575. document.msExitFullscreen()
  576. }
  577. }
  578. }
  579. }
  580. </script>
  581. <style lang="scss">
  582. @import "video.js/dist/video-js.css";
  583. .vPlayer {
  584. width: 100%;
  585. overflow: hidden;
  586. display: contents;
  587. .VastElements {
  588. display: none;
  589. }
  590. .VastElement {
  591. position: absolute;
  592. bottom: 60px;
  593. height: 50px;
  594. border: solid 2px $primary;
  595. border-radius: 8px;
  596. background: rgba(0, 0, 0, 0.3);
  597. display: flex;
  598. flex-flow: row;
  599. justify-content: center;
  600. align-items: center;
  601. cursor: pointer;
  602. transition: all 1s;
  603. $width: 150px;
  604. &.VastTimerBtn {
  605. border-top-right-radius: 0;
  606. border-bottom-right-radius: 0;
  607. border-right: none;
  608. width: $width;
  609. cursor: not-allowed;
  610. &.show {
  611. right: 0;
  612. }
  613. &.hide {
  614. right: -$width;
  615. }
  616. }
  617. &.VastSkipAdBtn {
  618. right: 0;
  619. border-top-right-radius: 0;
  620. border-bottom-right-radius: 0;
  621. border-right: none;
  622. width: $width;
  623. color: white;
  624. display: flex;
  625. align-items: center;
  626. justify-content: center;
  627. font-size: 0.8rem;
  628. &.show {
  629. right: 0;
  630. }
  631. &.hide {
  632. right: -$width;
  633. }
  634. }
  635. &.VastLinkBtn {
  636. left: 0;
  637. border-top-left-radius: 0;
  638. border-bottom-left-radius: 0;
  639. border-left: none;
  640. width: $width;
  641. &.show {
  642. left: 0;
  643. }
  644. &.hide {
  645. left: -$width;
  646. }
  647. a {
  648. width: 100%;
  649. height: 100%;
  650. color: white;
  651. display: flex;
  652. align-items: center;
  653. justify-content: center;
  654. font-size: 0.8rem;
  655. }
  656. }
  657. @media screen and(max-width: 600px) {
  658. height: 35px;
  659. $screen-max-600-width: 100px;
  660. &.VastTimerBtn {
  661. width: $screen-max-600-width;
  662. font-size: 0.7rem;
  663. &.hide {
  664. left: -$screen-max-600-width;
  665. }
  666. }
  667. &.VastSkipAdBtn {
  668. width: $screen-max-600-width;
  669. font-size: 0.7rem;
  670. &.hide {
  671. left: -$screen-max-600-width;
  672. }
  673. }
  674. &.VastLinkBtn {
  675. width: $screen-max-600-width;
  676. &.hide {
  677. right: -$screen-max-600-width;
  678. }
  679. a {
  680. font-size: 0.7rem;
  681. }
  682. }
  683. }
  684. }
  685. .over-player-wrapper-div {
  686. position: absolute;
  687. top: 0;
  688. left: 0;
  689. height: 100%;
  690. z-index: 1;
  691. .over-player-wrapper {
  692. position: absolute;
  693. top: 0;
  694. left: 0;
  695. height: 100%;
  696. .over-player-slot {
  697. left: 2000px;
  698. height: 100%;
  699. color: initial;
  700. transition: 0.4s;
  701. direction: ltr;
  702. position: relative;
  703. z-index: 1;
  704. &.show {
  705. right: 0;
  706. }
  707. &.hide {
  708. width: 0 !important;
  709. right: 2500px;
  710. }
  711. }
  712. }
  713. }
  714. .toggleSideBarBtn {
  715. position: absolute;
  716. top: 5px;
  717. left: 5px;
  718. z-index: 2;
  719. }
  720. .video-js {
  721. overflow: hidden;
  722. background-color: transparent;
  723. &.vjs-ad-playing {
  724. .vjs-resolution-button {
  725. display: none;
  726. }
  727. }
  728. .vjs-loading-spinner {
  729. right: 50%;
  730. margin: -25px -25px 0 0;
  731. text-align: right;
  732. }
  733. .vjs-big-play-button {
  734. color: white;
  735. width: 80px;
  736. height: 80px;
  737. border-radius: 100%;
  738. background: $primary;
  739. border-color: $primary;
  740. @media screen and(max-width: 600px) {
  741. margin-top: -60px;
  742. }
  743. .vjs-icon-placeholder:before {
  744. display: flex;
  745. font-size: 65px;
  746. align-items: center;
  747. justify-content: center;
  748. }
  749. }
  750. .vjs-control-bar {
  751. z-index: 2;
  752. .vjs-volume-panel {
  753. .vjs-volume-control {
  754. // right: -3.5em;
  755. // margin-right: -1px;
  756. }
  757. }
  758. .vjs-resolution-button {
  759. .vjs-menu-button {
  760. .vjs-icon-placeholder {
  761. &:before {
  762. content: "\f114";
  763. font-style: normal;
  764. font-weight: normal;
  765. font-family: VideoJS, Arial, serif;
  766. }
  767. }
  768. }
  769. }
  770. }
  771. .vjs-play-progress {
  772. &:before {
  773. /*rtl:ignore*/
  774. right: -0.5em;
  775. /*rtl:ignore*/
  776. left: auto;
  777. }
  778. }
  779. .vjs-volume-tooltip {
  780. float: right;
  781. }
  782. .vjs-volume-level {
  783. right: 0;
  784. }
  785. }
  786. }
  787. .vjs-slider-horizontal .vjs-volume-level:before {
  788. left: 0;
  789. right: auto;
  790. }
  791. .video-js .vjs-volume-level {
  792. /* right: 0; */
  793. }
  794. .video-js .vjs-volume-tooltip {
  795. /* float: left; */
  796. }
  797. .vPlayer .video-js .vjs-control-bar .vjs-volume-panel .vjs-volume-control {
  798. /* left: -3.5em; */
  799. /* margin-left: -1px; */
  800. }
  801. </style>