feat: Add capture screen's design

This commit is contained in:
Tixie 2019-03-09 22:54:07 +01:00
parent 4c8147feb6
commit 96de8e6005
14 changed files with 238 additions and 9 deletions

3
public/img/ico-arrow.svg Normal file
View file

@ -0,0 +1,3 @@
<svg width="12" height="22" viewBox="0 0 12 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.8977 10.1034C10.7599 9.96554 10.5359 9.96554 10.3981 10.1034L6.00483 14.5052L1.60299 10.1034C1.46517 9.96554 1.2412 9.96554 1.10337 10.1034C0.965543 10.2412 0.965543 10.4652 1.10337 10.603L5.74641 15.246C5.81532 15.3149 5.90146 15.3494 5.99622 15.3494C6.08236 15.3494 6.17712 15.3149 6.24603 15.246L10.8891 10.603C11.0355 10.4652 11.0355 10.2412 10.8977 10.1034Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 495 B

View file

@ -1,16 +1,27 @@
<template>
<div class="layout">
<welcome-screen/>
<welcome-screen v-if="!welcomed"/>
<capture-screen v-else/>
</div>
</template>
<script>
import welcomeScreen from '@/views/welcome'
import captureScreen from '@/views/capture'
import { mapState } from 'vuex'
export default {
name: 'souvenir',
components: {
welcomeScreen
welcomeScreen,
captureScreen
},
computed: {
...mapState([
'welcomed'
])
}
}
</script>

View file

@ -2,11 +2,15 @@
/* == main */
/* ----------------------------------------------------------- */
html {
height: 100%;
}
body {
display: flex;
flex-direction: column;
justify-content: center;
min-height: 100vh;
min-height: 100%;
background: var(--color-tertiary) url("/img/dotgrid.png");
color: var(--color-light-text);
font-family: var(--fontstack);

View file

@ -0,0 +1,39 @@
/* ----------------------------------------------------------- */
/* == Preview module */
/* ----------------------------------------------------------- */
.preview {
position: relative;
margin-bottom: 2rem;
}
.preview-visual {
position: relative;
width: 100%;
border-radius: 5px;
background-color: rgba(0, 0, 0, .5);
box-shadow: 0px 4px 50px rgba(0, 0, 0, .5);
}
.preview::after {
position: absolute;
top: calc(50% - (3em / 2));
left: calc(50% - (3em / 2));
display: block;
width: 3em;
height: 3em;
border: .2rem solid transparent;
border-color: transparent transparent rgba(255, 255, 255, .8) rgba(255, 255, 255, .8);
border-radius: 42rem;
content: "";
animation: previewSpinAround 1200ms infinite linear;
}
@keyframes previewSpinAround {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(359deg);
}
}

View file

@ -0,0 +1,79 @@
/* ----------------------------------------------------------- */
/* == Capture screen */
/* ----------------------------------------------------------- */
.capture {
display: flex;
flex-direction: column;
flex-grow: 1;
}
/* Options
-------------------------------------------------------------- */
.capture-options {
display: flex;
justify-content: space-between;
align-items: center;
padding: 2.2rem 0;
}
.capture-options__select,
.capture-options__switch {
padding: 2rem;
border: .1rem solid transparent;
border-radius: .3rem;
background: transparent;
color: #fff;
line-height: 2.2rem;
cursor: pointer;
appearance: none;
}
.capture-options__select:focus,
.capture-options__switch:focus {
outline: none;
box-shadow: var(--focus-ring);
}
.capture-options__select {
padding-right: 4.4rem;
background: url("/img/ico-arrow.svg") no-repeat;
background-position: calc(100% - 2rem) center;
}
.capture-options__switch svg {
margin-right: 1.5rem;
}
/* Capture button
-------------------------------------------------------------- */
.capture-btn,
.capture-btn:visited {
align-self: center;
margin-top: auto;
margin-bottom: 4rem;
padding: 0;
width: 8rem;
height: 8rem;
border: none;
border-radius: 8rem;
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
box-shadow: 2px 4px 15px rgba(0, 0, 0, .25);
font-size: 0;
cursor: pointer;
user-select: none;
}
.capture-btn:active {
background: linear-gradient(135deg, var(--color-secondary) 0%, var(--color-primary) 100%);
box-shadow: none;
}
.capture-btn:focus {
outline: none;
box-shadow: var(--focus-ring);
}

View file

@ -7,6 +7,9 @@
flex-grow: inherit;
}
/* Welcome screen
-------------------------------------------------------------- */
.welcome {
justify-content: center;
}
@ -15,4 +18,12 @@
margin-top: 0;
margin-bottom: 4rem;
}
/* Capture screen
-------------------------------------------------------------- */
.capture-btn,
.capture-btn:visited {
margin-top: 0;
}
}

View file

@ -19,5 +19,5 @@
-------------------------------------------------------------- */
:root {
--focus-ring: 0 0 0 .3rem rgba(33, 133, 208, .5);
--focus-ring: 0 0 0 .2rem rgba(221, 40, 211, .5);
}

View file

@ -30,13 +30,14 @@
/* == modules */
/* ----------------------------------------------------------- */
/* @import "4-modules/..."; */
@import "4-modules/preview.css";
/* ----------------------------------------------------------- */
/* == screens */
/* ----------------------------------------------------------- */
@import "5-screens/welcome.css";
@import "5-screens/capture.css";
/* ----------------------------------------------------------- */
/* == helpers */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

View file

@ -0,0 +1,39 @@
<template lang="html">
<div class="capture-options">
<select class="capture-options__select" v-model="timer.selected" @change="updateTimer(timer.selected)">
<option v-for="time in timer.list" :key="time" :value="time">
{{ timeLabel(time) }}
</option>
</select>
<button class="capture-options__switch" @click="back"><icon-switch/>switch</button>
</div>
</template>
<script>
import { mapState } from 'vuex'
import iconSwitch from '@/icons/ico-switch'
export default {
name: 'captureOptions',
components: {
iconSwitch
},
computed: {
...mapState([
'timer'
])
},
methods: {
back () {
this.$store.commit('welcome', false)
},
timeLabel (time) {
return time + 's'
},
updateTimer (time) {
this.$store.commit('updateTimer', time)
}
}
}
</script>

5
src/icons/ico-switch.vue Normal file
View file

@ -0,0 +1,5 @@
<template>
<svg width="15" height="10" viewBox="0 0 15 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill="currentColor" d="M13.051 3.12l-2.325 2.115.344.302c1.49-1.225 2.309-1.795 3.93-2.769-1.621-.956-2.456-1.543-3.93-2.768l-.344.302 2.325 2.114H.344v.705H13.05zM1.95 7.585h12.707v-.705H1.95l2.325-2.114-.344-.302C2.44 5.688 1.621 6.258 0 7.232 1.638 8.205 2.44 8.775 3.93 10l.344-.302-2.325-2.114z"/>
</svg>
</template>

View file

@ -5,10 +5,19 @@ Vue.use(Vuex)
export default new Vuex.Store({
state: {
welcomed: false,
timer: {
selected: 2,
list: [2, 3, 5]
}
},
mutations: {
welcome (store, value) {
store.welcomed = value
},
updateTimer (store, time) {
store.timer.selected = time
}
},
actions: {

23
src/views/capture.vue Normal file
View file

@ -0,0 +1,23 @@
<template>
<div class="capture">
<capture-options/>
<div class="preview">
<video class="preview-visual" height="200px"></video>
</div>
<button class="capture-btn">Capture</button>
</div>
</template>
<script>
import captureOptions from '@/components/capture-options'
export default {
name: 'capture',
components: {
captureOptions
}
}
</script>

View file

@ -8,12 +8,17 @@
<li class="welcome-steps__item">Save as a GIF</li>
</ol>
</div>
<button class="btn btn--primary">Start Capturing</button>
<button class="btn btn--primary" @click="welcome">Start Capturing</button>
</div>
</template>
<script>
export default {
name: 'welcome'
name: 'welcome',
methods: {
welcome () {
this.$store.commit('welcome', true)
}
}
}
</script>