mirror of
https://github.com/GuerillaStudio/souvenir.git
synced 2025-01-20 18:50:21 +00:00
feat: Add preview screen before encoding
This commit is contained in:
parent
da154ef249
commit
318c4ef7e1
7 changed files with 159 additions and 36 deletions
|
@ -56,6 +56,45 @@
|
|||
background: var(--btn-primary);
|
||||
}
|
||||
|
||||
/* Loading state
|
||||
-------------------------------------------------------------- */
|
||||
|
||||
.btn--loading,
|
||||
.btn--loading:link,
|
||||
.btn--loading:visited {
|
||||
position: relative;
|
||||
color: transparent;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.btn--loading svg {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.btn--loading::after {
|
||||
position: absolute;
|
||||
top: calc(50% - (2em / 2));
|
||||
left: calc(50% - (2em / 2));
|
||||
display: block;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
border: .2rem solid transparent;
|
||||
border-color: transparent transparent #fff #fff;
|
||||
border-radius: 42rem;
|
||||
content: "";
|
||||
animation: spinAround 500ms infinite linear;
|
||||
}
|
||||
|
||||
@keyframes spinAround {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* size
|
||||
-------------------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
flex-direction: row;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
.capture-progress {
|
||||
|
@ -105,12 +106,13 @@
|
|||
.download {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
.download-btn,
|
||||
.download-btn:visited {
|
||||
margin: auto 0;
|
||||
margin-right: 2rem;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
width: auto;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import VueRouter from 'vue-router'
|
|||
|
||||
import Welcome from '/views/screens/welcome'
|
||||
import Capture from '/views/screens/capture'
|
||||
import Preview from '/views/screens/preview'
|
||||
import Download from '/views/screens/download'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
@ -12,6 +13,7 @@ export default new VueRouter({
|
|||
routes: [
|
||||
{ name: 'home', path: '/', component: Welcome },
|
||||
{ name: 'capture', path: '/capture', component: Capture },
|
||||
{ name: 'preview', path: '/preview', component: Preview },
|
||||
{ name: 'download', path: '/download', component: Download }
|
||||
]
|
||||
})
|
||||
|
|
|
@ -9,18 +9,14 @@
|
|||
<video ref="preview" class="preview-visual" :class="{ 'preview--flip': shouldFlip }" preload="yes" autoplay muted playsinline webkit-playsinline></video>
|
||||
</div>
|
||||
|
||||
<button class="capture-btn" :class="{ 'capture-btn--capturing': capturing }" :disabled="!camera || encoding" @click.prevent="startCapturing">Capture</button>
|
||||
|
||||
<encoding-overlay v-if="encoding" :value="encodingProgress"></encoding-overlay>
|
||||
<button class="capture-btn" :class="{ 'capture-btn--capturing': capturing }" :disabled="!camera" @click.prevent="startCapturing">Capture</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import captureOptions from '/views/components/capture-options'
|
||||
import captureProgress from '/views/components/capture-progress'
|
||||
import encodingOverlay from '/views/components/encoding'
|
||||
import { capture } from '/services/capture.js'
|
||||
import { encode } from '/services/encode.js'
|
||||
|
||||
import 'objectFitPolyfill'
|
||||
|
||||
|
@ -30,14 +26,11 @@ export default {
|
|||
name: 'capture',
|
||||
components: {
|
||||
captureOptions,
|
||||
captureProgress,
|
||||
encodingOverlay
|
||||
captureProgress
|
||||
},
|
||||
data: () => ({
|
||||
capturing: false,
|
||||
capturingProgress: 0,
|
||||
encoding: false,
|
||||
encodingProgress: 0
|
||||
capturingProgress: 0
|
||||
}),
|
||||
computed: {
|
||||
...mapState([
|
||||
|
@ -82,28 +75,8 @@ export default {
|
|||
this.capturing = false
|
||||
this.capturingProgress = 0
|
||||
this.$store.commit('updateCapture', captureData)
|
||||
this.startEncoding()
|
||||
})
|
||||
},
|
||||
startEncoding () {
|
||||
this.encoding = true
|
||||
const encoding = encode(this.capture)
|
||||
|
||||
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: 'preview' })
|
||||
// this.startEncoding()
|
||||
})
|
||||
},
|
||||
async ensureCamera () {
|
||||
|
|
|
@ -26,7 +26,10 @@ export default {
|
|||
'gif'
|
||||
]),
|
||||
timestamp () {
|
||||
return this.gif.createdAt.getTime()
|
||||
if (this.gif) {
|
||||
return this.gif.createdAt.getTime()
|
||||
}
|
||||
return null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -37,9 +40,9 @@ export default {
|
|||
created () {
|
||||
if (!this.gif) {
|
||||
this.$router.push({ name: 'home' })
|
||||
} else {
|
||||
this.objectUrl = URL.createObjectURL(this.gif.blob)
|
||||
}
|
||||
|
||||
this.objectUrl = URL.createObjectURL(this.gif.blob)
|
||||
},
|
||||
destroyed () {
|
||||
URL.revokeObjectURL(this.objectUrl)
|
||||
|
|
103
src/views/screens/preview.vue
Normal file
103
src/views/screens/preview.vue
Normal file
|
@ -0,0 +1,103 @@
|
|||
<template lang="html">
|
||||
<div class="download">
|
||||
<div class="options">
|
||||
<span></span>
|
||||
<button class="options__btn" @click="back">← back</button>
|
||||
</div>
|
||||
|
||||
<div class="preview">
|
||||
<canvas ref="previewCanvas" class="preview-visual"></canvas>
|
||||
</div>
|
||||
|
||||
<button class="download-btn btn btn--primary w100" :class="{ 'btn--loading': encoding }" :disabled="encoding" @click="startEncoding">Generate GIF</button>
|
||||
|
||||
<encoding-overlay v-if="encoding" :value="encodingProgress"></encoding-overlay>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { encode } from '/services/encode.js'
|
||||
import encodingOverlay from '/views/components/encoding'
|
||||
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'preview',
|
||||
components: {
|
||||
encodingOverlay
|
||||
},
|
||||
data: () => ({
|
||||
encoding: false,
|
||||
encodingProgress: 0,
|
||||
previewTimeout: null
|
||||
}),
|
||||
computed: {
|
||||
...mapState([
|
||||
'camera',
|
||||
'capture'
|
||||
])
|
||||
},
|
||||
methods: {
|
||||
back () {
|
||||
this.$router.push({ name: 'capture' })
|
||||
},
|
||||
backHome () {
|
||||
this.$router.push({ name: 'home' })
|
||||
},
|
||||
printPreview (context, frameNumber) {
|
||||
this.previewTimeout = setTimeout(() => {
|
||||
// Looper
|
||||
frameNumber < (this.capture.imageDataList.length - 1) ? frameNumber++ : frameNumber = 0
|
||||
// Printer
|
||||
const image = this.capture.imageDataList[frameNumber]
|
||||
context.putImageData(image, 0, 0)
|
||||
this.printPreview(context, frameNumber)
|
||||
}, this.capture.delayTime)
|
||||
},
|
||||
startPreview () {
|
||||
if (!this.capture) {
|
||||
this.backHome()
|
||||
} else {
|
||||
const canvas = this.$refs.previewCanvas
|
||||
canvas.width = this.capture.imageWidth
|
||||
canvas.height = this.capture.imageHeight
|
||||
const canvasContext = canvas.getContext('2d')
|
||||
|
||||
this.printPreview(canvasContext, 0)
|
||||
}
|
||||
},
|
||||
startEncoding () {
|
||||
this.encoding = true
|
||||
const encoding = encode(this.capture)
|
||||
|
||||
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' })
|
||||
})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if (!this.capture) {
|
||||
this.backHome()
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.startPreview()
|
||||
},
|
||||
destroyed () {
|
||||
window.clearTimeout(this.previewTimeout)
|
||||
}
|
||||
}
|
||||
</script>
|
Loading…
Reference in a new issue