mirror of
https://github.com/GuerillaStudio/souvenir.git
synced 2024-11-08 11:51:53 +00:00
feat: Add capture screen's design
This commit is contained in:
parent
4c8147feb6
commit
96de8e6005
14 changed files with 238 additions and 9 deletions
3
public/img/ico-arrow.svg
Normal file
3
public/img/ico-arrow.svg
Normal 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 |
15
src/App.vue
15
src/App.vue
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
39
src/assets/css/4-modules/preview.css
Normal file
39
src/assets/css/4-modules/preview.css
Normal 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);
|
||||
}
|
||||
}
|
79
src/assets/css/5-screens/capture.css
Normal file
79
src/assets/css/5-screens/capture.css
Normal 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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 |
39
src/components/capture-options.vue
Normal file
39
src/components/capture-options.vue
Normal 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
5
src/icons/ico-switch.vue
Normal 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>
|
13
src/store.js
13
src/store.js
|
@ -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
23
src/views/capture.vue
Normal 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>
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue