mirror of
https://github.com/GuerillaStudio/souvenir.git
synced 2024-11-09 16:31:52 +00:00
feat:(encoding&download): Add new design
This commit is contained in:
parent
777f66380b
commit
f91b072528
16 changed files with 401 additions and 126 deletions
|
@ -28,6 +28,7 @@
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
|
font-weight: bold;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background .4s;
|
transition: background .4s;
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Default layout
|
||||||
|
-------------------------------------------------------------- */
|
||||||
|
|
||||||
.layout {
|
.layout {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -20,3 +23,55 @@
|
||||||
max-width: calc(100% - 2rem);
|
max-width: calc(100% - 2rem);
|
||||||
width: 32rem;
|
width: 32rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Overlay layout
|
||||||
|
-------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.layoutOverlay {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
flex-grow: 1;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
padding-top: 7rem;
|
||||||
|
max-width: calc(100% - 2rem);
|
||||||
|
width: 32rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layoutOverlay-body {
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layoutOverlay-close,
|
||||||
|
.layoutOverlay-close:visited {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
align-self: flex-end;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
color: #fff;
|
||||||
|
line-height: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Content */
|
||||||
|
|
||||||
|
.layoutOverlay-content {
|
||||||
|
padding-top: 2rem;
|
||||||
|
padding-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layoutOverlay-title {
|
||||||
|
margin-bottom: .7rem;
|
||||||
|
font-size: 2.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layoutOverlay-subtitle {
|
||||||
|
color: rgba(255, 255, 255, .7);
|
||||||
|
font-size: 1.4rem;
|
||||||
|
line-height: 120%;
|
||||||
|
}
|
||||||
|
|
|
@ -3,68 +3,44 @@
|
||||||
/* ----------------------------------------------------------- */
|
/* ----------------------------------------------------------- */
|
||||||
|
|
||||||
.encoding {
|
.encoding {
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 1;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
flex-grow: 1;
|
||||||
height: 100%;
|
padding-bottom: 4rem;
|
||||||
background-color: rgba(0, 0, 0, .9);
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 2.4rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.encoding-illu {
|
/* Loader
|
||||||
|
-------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.encoding-loader {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-bottom: 5rem;
|
flex-shrink: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.encoding-illu::before {
|
.encoding-loader__preview {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: .5rem;
|
top: 1.4rem;
|
||||||
right: -1rem;
|
left: 1.4rem;
|
||||||
left: -1rem;
|
|
||||||
height: .5rem;
|
|
||||||
border-radius: .5rem;
|
|
||||||
border-radius: .4rem;
|
|
||||||
background: var(--color-primary);
|
|
||||||
box-shadow: 0 .4rem .4rem rgba(0, 0, 0, .25);
|
|
||||||
content: "";
|
|
||||||
animation: encodingProgress .3s ease-in-out infinite alternate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes encodingProgress {
|
|
||||||
from {
|
|
||||||
top: .5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
top: calc(100% - 1rem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.encoding-label {
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.encoding-progressBar {
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin: 2rem 0;
|
width: 11.4rem;
|
||||||
max-width: 30rem;
|
height: 11.4rem;
|
||||||
width: 90%;
|
border-radius: 100%;
|
||||||
border-radius: .5rem;
|
|
||||||
background-color: rgba(255, 255, 255, .2);
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.encoding-progressBar__state {
|
/* Progress bar
|
||||||
height: .5rem;
|
-------------------------------------------------------------- */
|
||||||
background: linear-gradient(91.78deg, var(--color-primary) 0%,var(--color-secondary) 100%);
|
|
||||||
transition: .3s all ease-in-out;
|
.encoding-progress__value {
|
||||||
|
transition: stroke-dashoffset .2s ease-in-out;
|
||||||
|
|
||||||
|
will-change: auto;
|
||||||
|
stroke-miterlimit: round;
|
||||||
}
|
}
|
||||||
|
|
||||||
.encoding-percent {
|
.encoding-percent {
|
||||||
|
@ -72,3 +48,39 @@
|
||||||
font-size: 5rem;
|
font-size: 5rem;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Percent
|
||||||
|
-------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.encoding-percent {
|
||||||
|
color: rgba(255, 255, 255, .5);
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 1.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notif
|
||||||
|
-------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.encoding-notif,
|
||||||
|
.encoding-notif:visited {
|
||||||
|
margin-top: auto;
|
||||||
|
padding: .5rem 2rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: .3rem;
|
||||||
|
background-color: transparent;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.encoding-notif:focus {
|
||||||
|
outline: none;
|
||||||
|
box-shadow: var(--focus-ring);
|
||||||
|
}
|
||||||
|
|
||||||
|
.encoding-notif
|
||||||
|
.encoding-notif__icon {
|
||||||
|
margin-bottom: .7rem;
|
||||||
|
}
|
||||||
|
|
|
@ -7,10 +7,39 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Preview
|
||||||
|
-------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.download-preview {
|
||||||
|
position: relative;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-preview__visual {
|
||||||
|
width: 16.2rem;
|
||||||
|
border-radius: 42rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-preview__flower {
|
||||||
|
position: absolute;
|
||||||
|
right: -.6rem;
|
||||||
|
bottom: .2rem;
|
||||||
|
width: 7.1rem;
|
||||||
|
height: 7.9rem;
|
||||||
|
}
|
||||||
|
/* Button
|
||||||
|
-------------------------------------------------------------- */
|
||||||
|
|
||||||
.download-btn,
|
.download-btn,
|
||||||
.download-btn:visited {
|
.download-btn:visited {
|
||||||
margin-top: auto;
|
display: flex;
|
||||||
margin-bottom: 4rem;
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-btn svg {
|
||||||
|
margin-right: .6rem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,23 @@
|
||||||
flex-grow: inherit;
|
flex-grow: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Overlay layout
|
||||||
|
-------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.layoutOverlay-body {
|
||||||
|
background: var(--color-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.layoutOverlay-close {
|
||||||
|
top: 1rem;
|
||||||
|
right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layoutOverlay-close svg {
|
||||||
|
width: 8rem;
|
||||||
|
height: 8rem;
|
||||||
|
}
|
||||||
|
|
||||||
/* Welcome screen
|
/* Welcome screen
|
||||||
-------------------------------------------------------------- */
|
-------------------------------------------------------------- */
|
||||||
|
|
||||||
|
@ -35,4 +52,11 @@
|
||||||
.capture-btn:visited {
|
.capture-btn:visited {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Encoding screen
|
||||||
|
-------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.encoding-notif {
|
||||||
|
margin-top: 7rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,9 @@ import store from '/store'
|
||||||
import registerServiceWorker from '/register-service-worker.js'
|
import registerServiceWorker from '/register-service-worker.js'
|
||||||
|
|
||||||
import LayoutDefault from '/views/layout/default'
|
import LayoutDefault from '/views/layout/default'
|
||||||
|
import LayoutOverlay from '/views/layout/overlay'
|
||||||
Vue.component('layout-default', LayoutDefault)
|
Vue.component('layout-default', LayoutDefault)
|
||||||
|
Vue.component('layout-overlay', LayoutOverlay)
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
|
|
36
src/views/components/encoding-loader.vue
Normal file
36
src/views/components/encoding-loader.vue
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<template>
|
||||||
|
<svg width="142" height="142" viewBox="0 0 142 142" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="71" cy="71" r="69" stroke="#fff" stroke-opacity=".2" stroke-width="4" stroke-miterlimit="3.864" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path :stroke-dasharray="progressPerimeter" :stroke-dashoffset="pathDashOffset" class="encoding-progress__value" d="m 72.239,2.011 c 37.9809,0.6782829 68.26967,31.931708 67.75989,69.895071 C 139.48913,109.8675 108.37484,140.24197 70.395213,139.90478 32.415584,139.56759 1.8454901,108.64548 2.0098165,70.680986 2.1741514,32.714556 33.013046,2.0038306 71,2" stroke="url(#paint0_linear)" stroke-width="4" stroke-miterlimit="3.864" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear" x1="4" y1="4" x2="71" y2="138" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#DD28D3"/>
|
||||||
|
<stop offset="1" stop-color="#8420A7"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'encodingLoader',
|
||||||
|
props: {
|
||||||
|
percent: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: () => ({
|
||||||
|
progressPerimeter: 432.3168640136719
|
||||||
|
}),
|
||||||
|
computed: {
|
||||||
|
pathDashOffset () {
|
||||||
|
if (this.percent) {
|
||||||
|
let to = this.progressPerimeter * ((100 - this.percent) / 100)
|
||||||
|
return Math.max(0, to) // Prevent negative number
|
||||||
|
}
|
||||||
|
return this.progressPerimeter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,29 +0,0 @@
|
||||||
<template lang="html">
|
|
||||||
<div class="encoding">
|
|
||||||
<div class="encoding-illu">
|
|
||||||
<img src="/assets/img/video-encoding.svg" alt="">
|
|
||||||
</div>
|
|
||||||
<div class="encoding-label">Encoding</div>
|
|
||||||
<div class="encoding-progressBar">
|
|
||||||
<div class="encoding-progressBar__state" :style="'width: ' + percentage + '%;'"></div>
|
|
||||||
</div>
|
|
||||||
<div class="encoding-percent">{{ roundedPercentage }}%</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'encodingOverlay',
|
|
||||||
props: {
|
|
||||||
value: Number
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
percentage () {
|
|
||||||
return this.value * 100
|
|
||||||
},
|
|
||||||
roundedPercentage () {
|
|
||||||
return Math.round(this.percentage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
10
src/views/icons/flower.vue
Normal file
10
src/views/icons/flower.vue
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<template>
|
||||||
|
<svg width="71" height="79" viewBox="0 0 71 79" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M7.687 78.493s11.14-19.695 27.93-25.373A34.35 34.35 0 0 0 53.01 40.137a57.882 57.882 0 0 0 5.115-9.197" stroke="#535461" stroke-width="2" stroke-miterlimit="10"/>
|
||||||
|
<path d="M68.664 27.284c-1.913 1.85-10.815 3.765-10.815 3.765s2.185-8.822 4.097-10.675a4.825 4.825 0 0 1 5.272-.964 4.826 4.826 0 0 1 2.57 2.644 4.807 4.807 0 0 1-1.124 5.23zM63.64 43.253c-2.613.518-11.13-2.707-11.13-2.707s6.64-6.222 9.252-6.74a4.834 4.834 0 0 1 3.554.776 4.81 4.81 0 0 1 1.311 6.599 4.826 4.826 0 0 1-2.987 2.072zM45.301 60.534c-2.517-.871-8.241-7.944-8.241-7.944s8.881-2.025 11.398-1.157a4.823 4.823 0 0 1 2.68 2.46 4.81 4.81 0 0 1-2.207 6.36 4.834 4.834 0 0 1-3.63.281zM28.475 70.49c-2.627-.435-9.464-6.441-9.464-6.441s8.407-3.494 11.034-3.06a4.825 4.825 0 0 1 3.135 1.946 4.807 4.807 0 0 1-1.11 6.717 4.83 4.83 0 0 1-3.595.837zM45.085 33.65c0 2.661 4.82 10.376 4.82 10.376s4.825-7.711 4.829-10.369a4.813 4.813 0 0 0-1.459-3.321 4.83 4.83 0 0 0-6.732 0 4.813 4.813 0 0 0-1.458 3.321v-.007zM25.555 45.543c.796 2.54 7.708 8.47 7.708 8.47s2.294-8.798 1.499-11.335a4.817 4.817 0 0 0-2.397-2.657 4.831 4.831 0 0 0-6.347 1.986 4.806 4.806 0 0 0-.449 3.547l-.014-.011zM8.164 59.705c.354 2.632 6.166 9.634 6.166 9.634s3.751-8.283 3.398-10.919a4.816 4.816 0 0 0-1.93-2.975 4.833 4.833 0 0 0-6.544.88 4.811 4.811 0 0 0-1.072 3.38h-.018z" fill="#DD28D3"/>
|
||||||
|
<path opacity=".25" d="M68.664 27.284c-1.913 1.85-10.815 3.765-10.815 3.765s2.185-8.822 4.097-10.675a4.825 4.825 0 0 1 5.272-.964 4.826 4.826 0 0 1 2.57 2.644 4.807 4.807 0 0 1-1.124 5.23zM63.64 43.253c-2.613.518-11.13-2.707-11.13-2.707s6.64-6.222 9.252-6.74a4.834 4.834 0 0 1 3.554.776 4.81 4.81 0 0 1 1.311 6.599 4.826 4.826 0 0 1-2.987 2.072zM45.301 60.534c-2.517-.871-8.241-7.944-8.241-7.944s8.881-2.025 11.398-1.157a4.823 4.823 0 0 1 2.68 2.46 4.81 4.81 0 0 1-2.207 6.36 4.834 4.834 0 0 1-3.63.281zM28.475 70.49c-2.627-.435-9.464-6.441-9.464-6.441s8.407-3.494 11.034-3.06a4.825 4.825 0 0 1 3.135 1.946 4.807 4.807 0 0 1-1.11 6.717 4.83 4.83 0 0 1-3.595.837zM45.085 33.65c0 2.661 4.82 10.376 4.82 10.376s4.825-7.711 4.829-10.369a4.813 4.813 0 0 0-1.459-3.321 4.83 4.83 0 0 0-6.732 0 4.813 4.813 0 0 0-1.458 3.321v-.007zM25.555 45.543c.796 2.54 7.708 8.47 7.708 8.47s2.294-8.798 1.499-11.335a4.817 4.817 0 0 0-2.397-2.657 4.831 4.831 0 0 0-6.347 1.986 4.806 4.806 0 0 0-.449 3.547l-.014-.011zM8.164 59.705c.354 2.632 6.166 9.634 6.166 9.634s3.751-8.283 3.398-10.919a4.816 4.816 0 0 0-1.93-2.975 4.833 4.833 0 0 0-6.544.88 4.811 4.811 0 0 0-1.072 3.38h-.018z" fill="#000"/>
|
||||||
|
<path d="M8.327 78.101s2.188-22.511 15.202-34.488a34.253 34.253 0 0 0 10.628-18.905c.638-3.462.956-6.975.951-10.495" stroke="#535461" stroke-width="2" stroke-miterlimit="10"/>
|
||||||
|
<path d="M43.293 6.615c-.997 2.47-8.358 7.82-8.358 7.82s-1.584-8.953-.59-11.42A4.82 4.82 0 0 1 36.93.385a4.832 4.832 0 0 1 3.692-.036 4.82 4.82 0 0 1 2.635 2.58c.501 1.176.514 2.501.036 3.686zM45.174 23.254c-2.182 1.528-11.275 2.029-11.275 2.029s3.535-8.374 5.724-9.906a4.83 4.83 0 0 1 6.721 1.168 4.808 4.808 0 0 1-1.17 6.709zM35.43 46.468c-2.655.222-10.759-3.928-10.759-3.928s7.294-5.445 9.95-5.668a4.83 4.83 0 0 1 3.517 1.12 4.812 4.812 0 0 1-2.708 8.476zM24.084 62.376c-2.58.667-11.267-2.057-11.267-2.057s6.265-6.596 8.838-7.266a4.834 4.834 0 0 1 3.602.562 4.81 4.81 0 0 1 1.694 6.522 4.825 4.825 0 0 1-2.874 2.24h.007zM24.314 21.98c1.079 2.431 8.616 7.534 8.616 7.534s1.284-8.999.205-11.43a4.82 4.82 0 0 0-2.669-2.55 4.836 4.836 0 0 0-5.238 1.158 4.818 4.818 0 0 0-.931 5.274l.017.014zM11.286 40.75c1.767 2.002 10.482 4.617 10.482 4.617s-1.474-8.971-3.231-10.969a4.823 4.823 0 0 0-3.312-1.628 4.834 4.834 0 0 0-3.496 1.185 4.817 4.817 0 0 0-1.631 3.306 4.806 4.806 0 0 0 1.188 3.49zM1.135 60.732c1.414 2.265 9.546 6.317 9.546 6.317s.067-9.091-1.33-11.357a4.816 4.816 0 0 0-2.99-2.217 4.832 4.832 0 0 0-5.073 1.864 4.809 4.809 0 0 0-.153 5.393z" fill="#DD28D3"/>
|
||||||
|
<path opacity=".1" d="M13.747 16.447s-4.187 2.117-3.36 3c.828.881 3.36-3 3.36-3z" fill="#000"/>
|
||||||
|
</svg>
|
||||||
|
</template>
|
5
src/views/icons/ico-close-overlay.vue
Normal file
5
src/views/icons/ico-close-overlay.vue
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<template>
|
||||||
|
<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M39.657 21.74a1.02 1.02 0 0 0-1.445-1.44l-8.235 8.257-8.235-8.257a1.02 1.02 0 1 0-1.444 1.44l8.239 8.262-8.24 8.261a1.02 1.02 0 1 0 1.445 1.44l8.235-8.257 8.235 8.258a1.02 1.02 0 0 0 1.445-1.44l-8.239-8.262 8.239-8.262z"/>
|
||||||
|
</svg>
|
||||||
|
</template>
|
5
src/views/icons/ico-download.vue
Normal file
5
src/views/icons/ico-download.vue
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<template>
|
||||||
|
<svg width="10" height="16" viewBox="0 0 10 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="currentColor" d="M4.23 15.71a1 1 0 0 0 1.41 0l4-4a1 1 0 0 0-1.41-1.41l-2.29 2.29V1a1 1 0 0 0-2 0v11.59l-2.29-2.3A1 1 0 0 0 .24 11.7l3.99 4.01z"/>
|
||||||
|
</svg>
|
||||||
|
</template>
|
26
src/views/icons/ico-notif.vue
Normal file
26
src/views/icons/ico-notif.vue
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<template>
|
||||||
|
<svg width="51" height="51" viewBox="0 0 51 51" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="25.5" cy="25.5" r="19.5" fill="url(#paint0_linear)"/>
|
||||||
|
<circle opacity=".5" cx="25.5" cy="25.5" r="24.5" stroke="url(#paint1_linear)" stroke-width="2"/>
|
||||||
|
<path d="M27.007 19.843c-.068-.617-.579-.843-1.199-.843-.62 0-1.131.227-1.199.843-1.829.534-3.168 2.259-3.168 4.305 0 3.296-1.441 4.553-1.441 5.034-.002.605 1.342.978 3.97 1.237.236.815.965 1.412 1.837 1.412.871 0 1.6-.598 1.836-1.412 2.628-.259 3.973-.632 3.973-1.237 0-.48-1.44-1.738-1.44-5.034 0-2.047-1.34-3.77-3.17-4.305z" fill="#fff" filter="url(#filter0_d)"/>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_d" x="17.952" y="16.952" width="15.712" height="16.927" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
|
||||||
|
<feOffset/>
|
||||||
|
<feGaussianBlur stdDeviation="1.024"/>
|
||||||
|
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
|
||||||
|
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/>
|
||||||
|
<feBlend in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
<linearGradient id="paint0_linear" x1="6" y1="6" x2="48.313" y2="10.006" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#DD28D3"/>
|
||||||
|
<stop offset="1" stop-color="#8420A7"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint1_linear" x2="55.332" y2="5.239" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#DD28D3"/>
|
||||||
|
<stop offset="1" stop-color="#8420A7"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
</template>
|
30
src/views/layout/overlay.vue
Normal file
30
src/views/layout/overlay.vue
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<template>
|
||||||
|
<div class="layoutOverlay">
|
||||||
|
<button v-if="close" class="layoutOverlay-close" aria-label="Close" @click="close">
|
||||||
|
<icon-close></icon-close>
|
||||||
|
</button>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import iconClose from '/views/icons/ico-close-overlay'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
iconClose
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
close: {
|
||||||
|
type: Function,
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted: function () {
|
||||||
|
document.body.classList.add('layoutOverlay-body')
|
||||||
|
},
|
||||||
|
destroyed: function () {
|
||||||
|
document.body.classList.remove('layoutOverlay-body')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,30 +1,47 @@
|
||||||
<template lang="html">
|
<template lang="html">
|
||||||
<layout-default>
|
<layout-overlay :close="back">
|
||||||
<div class="download">
|
<encoding-screen v-if="encoding" :value="encodingProgress"></encoding-screen>
|
||||||
<div class="options">
|
<div v-if="gif" class="download">
|
||||||
<span></span>
|
<div class="download-preview">
|
||||||
<button class="options__btn" @click="back">← back</button>
|
<img class="download-preview__visual" :src="objectUrl" alt="">
|
||||||
|
<illu-flower class="download-preview__flower"></illu-flower>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="layoutOverlay-content">
|
||||||
<div class="preview preview--novideo">
|
<div class="layoutOverlay-title">Ready just for you~</div>
|
||||||
<img class="preview-visualImg" :src="objectUrl" alt="">
|
<div class="layoutOverlay-subtitle">
|
||||||
|
Thank you for your patience.<br>
|
||||||
|
You can now download your souvenir.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a class="download-btn btn btn--primary w100" :href="objectUrl" :download="`souvenir${timestamp}.gif`">Download GIF</a>
|
|
||||||
</div>
|
</div>
|
||||||
</layout-default>
|
<a class="download-btn btn btn--primary w100" :href="objectUrl" :download="`souvenir${timestamp}.gif`"><icon-dl></icon-dl>Save as GIF</a>
|
||||||
|
</div>
|
||||||
|
</layout-overlay>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
|
import { encode } from '/services/encode.js'
|
||||||
|
import encodingScreen from '/views/screens/encoding'
|
||||||
|
import iconDl from '/views/icons/ico-download'
|
||||||
|
import illuFlower from '/views/icons/flower'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'download',
|
name: 'download',
|
||||||
|
components: {
|
||||||
|
encodingScreen,
|
||||||
|
iconDl,
|
||||||
|
illuFlower
|
||||||
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
objectUrl: null
|
encoding: false,
|
||||||
|
encodingProgress: 0,
|
||||||
|
objectUrl: null,
|
||||||
|
downloadReady: false
|
||||||
}),
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
...mapState([
|
...mapState([
|
||||||
|
'capture',
|
||||||
|
'boomerang',
|
||||||
'gif'
|
'gif'
|
||||||
]),
|
]),
|
||||||
timestamp () {
|
timestamp () {
|
||||||
|
@ -36,18 +53,52 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
back () {
|
back () {
|
||||||
this.$router.push({ name: 'capture' })
|
this.$router.push({ name: 'preview' })
|
||||||
|
},
|
||||||
|
backHome () {
|
||||||
|
this.$router.push({ name: 'home' })
|
||||||
|
},
|
||||||
|
fillGIF () {
|
||||||
|
this.objectUrl = URL.createObjectURL(this.gif.blob)
|
||||||
|
},
|
||||||
|
emptyGIF () {
|
||||||
|
URL.revokeObjectURL(this.objectUrl)
|
||||||
|
this.$store.commit('updateGif', null)
|
||||||
|
},
|
||||||
|
startEncoding () {
|
||||||
|
this.encoding = true
|
||||||
|
const encoding = encode(this.capture, { boomerangEffect: this.boomerang })
|
||||||
|
|
||||||
|
encoding.once('error', error => {
|
||||||
|
console.error(error)
|
||||||
|
this.encoding = false
|
||||||
|
this.encodingProgress = 0
|
||||||
|
})
|
||||||
|
|
||||||
|
encoding.on('progress', value => {
|
||||||
|
this.encodingProgress = value
|
||||||
|
})
|
||||||
|
|
||||||
|
encoding.once('done', gif => {
|
||||||
|
this.encoding = false
|
||||||
|
this.encodingProgress = 0
|
||||||
|
this.$store.commit('updateGif', gif)
|
||||||
|
this.fillGIF()
|
||||||
|
this.downloadReady = true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
if (!this.gif) {
|
if (!this.capture) {
|
||||||
this.$router.push({ name: 'home' })
|
this.$router.push({ name: 'home' })
|
||||||
|
} else if (!this.gif) {
|
||||||
|
this.startEncoding()
|
||||||
} else {
|
} else {
|
||||||
this.objectUrl = URL.createObjectURL(this.gif.blob)
|
this.fillGIF()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
destroyed () {
|
destroyed () {
|
||||||
URL.revokeObjectURL(this.objectUrl)
|
this.emptyGIF()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
46
src/views/screens/encoding.vue
Normal file
46
src/views/screens/encoding.vue
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<template lang="html">
|
||||||
|
<div class="encoding">
|
||||||
|
|
||||||
|
<div class="encoding-loader">
|
||||||
|
<encoding-loader :percent="roundedPercentage" class="encoding-progress"></encoding-loader>
|
||||||
|
<preview-canvas class="encoding-loader__preview"></preview-canvas>
|
||||||
|
</div>
|
||||||
|
<div class="encoding-percent">{{ roundedPercentage }}%</div>
|
||||||
|
|
||||||
|
<div class="layoutOverlay-content">
|
||||||
|
<div class="layoutOverlay-title">Almost ready~</div>
|
||||||
|
<div class="layoutOverlay-subtitle">Encoding may take some time depending on your device</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="encoding-notif">
|
||||||
|
<icon-notif class="encoding-notif__icon"></icon-notif>
|
||||||
|
<div>Get notified when It’s done</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import encodingLoader from '/views/components/encoding-loader'
|
||||||
|
import previewCanvas from '/views/components/preview-canvas'
|
||||||
|
import iconNotif from '/views/icons/ico-notif'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'encoding',
|
||||||
|
components: {
|
||||||
|
encodingLoader,
|
||||||
|
previewCanvas,
|
||||||
|
iconNotif
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: Number
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
percentage () {
|
||||||
|
return this.value * 100
|
||||||
|
},
|
||||||
|
roundedPercentage () {
|
||||||
|
return Math.round(this.percentage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -7,16 +7,12 @@
|
||||||
<preview-canvas v-if="capture" class="preview-visual"></preview-canvas>
|
<preview-canvas v-if="capture" class="preview-visual"></preview-canvas>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="download-btn btn btn--primary w100" :class="{ 'btn--loading': encoding }" :disabled="encoding" @click="startEncoding">Generate GIF</button>
|
<button class="download-btn btn btn--primary w100" @click="startEncoding">Generate GIF</button>
|
||||||
|
|
||||||
<encoding-overlay v-if="encoding" :value="encodingProgress"></encoding-overlay>
|
|
||||||
</div>
|
</div>
|
||||||
</layout-default>
|
</layout-default>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { encode } from '/services/encode.js'
|
|
||||||
import encodingOverlay from '/views/components/encoding'
|
|
||||||
import captureOptions from '/views/components/capture-options'
|
import captureOptions from '/views/components/capture-options'
|
||||||
import previewCanvas from '/views/components/preview-canvas'
|
import previewCanvas from '/views/components/preview-canvas'
|
||||||
|
|
||||||
|
@ -25,15 +21,9 @@ import { mapState } from 'vuex'
|
||||||
export default {
|
export default {
|
||||||
name: 'preview',
|
name: 'preview',
|
||||||
components: {
|
components: {
|
||||||
encodingOverlay,
|
|
||||||
captureOptions,
|
captureOptions,
|
||||||
previewCanvas
|
previewCanvas
|
||||||
},
|
},
|
||||||
data: () => ({
|
|
||||||
encoding: false,
|
|
||||||
encodingProgress: 0,
|
|
||||||
previewInterval: null
|
|
||||||
}),
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapState([
|
...mapState([
|
||||||
'camera',
|
'camera',
|
||||||
|
@ -49,25 +39,7 @@ export default {
|
||||||
this.$router.push({ name: 'home' })
|
this.$router.push({ name: 'home' })
|
||||||
},
|
},
|
||||||
startEncoding () {
|
startEncoding () {
|
||||||
this.encoding = true
|
|
||||||
const encoding = encode(this.capture, { boomerangEffect: this.boomerang })
|
|
||||||
|
|
||||||
encoding.once('error', error => {
|
|
||||||
console.error(error)
|
|
||||||
this.encoding = false
|
|
||||||
this.encodingProgress = 0
|
|
||||||
})
|
|
||||||
|
|
||||||
encoding.on('progress', value => {
|
|
||||||
this.encodingProgress = value
|
|
||||||
})
|
|
||||||
|
|
||||||
encoding.once('done', gif => {
|
|
||||||
this.encoding = false
|
|
||||||
this.encodingProgress = 0
|
|
||||||
this.$store.commit('updateGif', gif)
|
|
||||||
this.$router.push({ name: 'download' })
|
this.$router.push({ name: 'download' })
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
|
|
Loading…
Reference in a new issue