Skip to content

Commit 2f01735

Browse files
authored
feat(video-player): support youtube videos (#426)
* feat(video-player): support youtube videos * fix: temporary use `<img`>
1 parent 1393bde commit 2f01735

File tree

2 files changed

+101
-13
lines changed

2 files changed

+101
-13
lines changed

nuxtjs.org/content/0.docs/1.get-started/1.installation.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,7 @@ ManualInstallVideoTitle: Nuxt Manual Installation
1717

1818
## Using create-nuxt-app
1919

20-
::video-player
21-
sources:
22-
- src: https://www.youtube.com/watch?v=wHkPjOmJTt0
23-
type: video/webm
24-
poster: http://i3.ytimg.com/vi/wHkPjOmJTt0/maxresdefault.jpg
25-
---
26-
::
20+
:video-player{src="https://www.youtube.com/watch?v=wHkPjOmJTt0"}
2721

2822
To get started quickly you can use the [create-nuxt-app](https://github.com/nuxt/create-nuxt-app).
2923

src/defaultTheme/components/atoms/VideoPlayer.vue

Lines changed: 100 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,119 @@
11
<template>
2-
<video :poster="poster">
3-
<source v-for="source in sources" :key="source.src || source" :src="source.src || source" :type="source.type" />
4-
</video>
2+
<div class="video-player relative my-4">
3+
<img
4+
class="video absolute top-0 left-0 w-full h-full object-cover"
5+
:src="provider ? provider.poster : poster"
6+
:width="670"
7+
:height="377"
8+
/>
9+
<div v-if="loaded" class="video absolute top-0 left-0 w-full h-full">
10+
<!-- remote videos -->
11+
<video v-if="!provider" :poster="poster" controls autoplay>
12+
<source v-if="src" :src="src" />
13+
<source v-for="source in sources" :key="source.src || source" :src="source.src || source" :type="source.type" />
14+
</video>
15+
<!-- youtube -->
16+
<iframe
17+
v-else-if="provider.name === 'youtube'"
18+
width="560"
19+
height="377"
20+
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
21+
allowfullscreen=""
22+
class="w-full h-full"
23+
:src="provider.src"
24+
></iframe>
25+
</div>
26+
<div v-if="!loaded" class="overlay absolute top-0 left-0 w-full h-full cursor-pointer" @click="loaded = true">
27+
<button class="play"></button>
28+
</div>
29+
</div>
530
</template>
631

732
<script>
8-
export default {
33+
import { defineComponent, ref } from '@nuxtjs/composition-api'
34+
export default defineComponent({
935
props: {
1036
poster: {
1137
type: String,
1238
default: ''
1339
},
40+
src: {
41+
type: String,
42+
default: ''
43+
},
1444
sources: {
1545
type: Array,
16-
required: true
46+
default: () => []
47+
}
48+
},
49+
setup(props) {
50+
const provider = ref(null)
51+
const loaded = ref(false)
52+
53+
if (!props.src && !props.sources.length) {
54+
throw new Error('VideoPlayer: you need to provide either `src` or `sources` props')
55+
}
56+
57+
const src = props.src || props.sources[0].src
58+
59+
if (src && src.includes('youtube.com/watch')) {
60+
const match = src.match(/\?v=([^&]*)/)
61+
provider.value = {
62+
name: 'youtube',
63+
src: `https://www.youtube-nocookie.com/embed/${match[1]}?autoplay=1`,
64+
poster: props.poster || `https://i.ytimg.com/vi/${match[1]}/hqdefault.jpg`
65+
}
66+
}
67+
68+
return {
69+
loaded,
70+
provider
1771
}
1872
}
19-
}
73+
})
2074
</script>
2175

2276
<style scoped lang="postcss">
77+
.video-player {
78+
&:before {
79+
content: ' ';
80+
display: block;
81+
position: absolute;
82+
top: 0;
83+
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADGCAYAAAAT+OqFAAAAdklEQVQoz42QQQ7AIAgEF/T/D+kbq/RWAlnQyyazA4aoAB4FsBSA/bFjuF1EOL7VbrIrBuusmrt4ZZORfb6ehbWdnRHEIiITaEUKa5EJqUakRSaEYBJSCY2dEstQY7AuxahwXFrvZmWl2rh4JZ07z9dLtesfNj5q0FU3A5ObbwAAAABJRU5ErkJggg==');
84+
background-position: top;
85+
background-repeat: repeat-x;
86+
height: 60px;
87+
padding-bottom: 50px;
88+
width: 100%;
89+
transition: all 0.2s cubic-bezier(0, 0, 0.2, 1);
90+
z-index: 1;
91+
}
92+
&:after {
93+
content: ' ';
94+
display: block;
95+
padding-bottom: 56.25%;
96+
}
97+
98+
.play {
99+
width: 68px;
100+
height: 48px;
101+
position: absolute;
102+
cursor: pointer;
103+
transform: translate3d(-50%, -50%, 0);
104+
top: 50%;
105+
left: 50%;
106+
z-index: 1;
107+
background-color: transparent;
108+
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 68 48"><path fill="%23f00" fill-opacity="0.8" d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z"></path><path d="M 45,24 27,14 27,34" fill="%23fff"></path></svg>');
109+
filter: grayscale(100%);
110+
transition: filter 0.1s cubic-bezier(0, 0, 0.2, 1);
111+
border: none;
112+
}
113+
&:hover .play {
114+
filter: none;
115+
}
116+
}
23117
video {
24118
@apply w-full py-4;
25119
}

0 commit comments

Comments
 (0)