<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<!DOCTYPE html><html class=''>
<head><script src='//production-assets.codepen.io/assets/editor/live/console_runner-079c09a0e3b9ff743e39ee2d5637b9216b3545af0de366d4b9aad9dc87e26bfd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/events_runner-73716630c22bbc8cff4bd0f07b135f00a0bdc5d14629260c3ec49e5606f98fdd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/css_live_reload_init-2c0dc5167d60a5af3ee189d570b1835129687ea2a61bee3513dee3a50c115a77.js'></script><meta charset='UTF-8'><meta name="robots" content="noindex"><link rel="shortcut icon" type="image/x-icon" href="//production-assets.codepen.io/assets/favicon/favicon-8ea04875e70c4b0bb41da869e81236e54394d63638a1ef12fa558a4a835f1164.ico" /><link rel="mask-icon" type="" href="//production-assets.codepen.io/assets/favicon/logo-pin-f2d2b6d2c61838f7e76325261b7195c27224080bc099486ddd6dccb469b8e8e6.svg" color="#111" /><link rel="canonical" href="https://codepen.io/ispal/pen/LxjgEj?depth=everything&order=popularity&page=12&q=translate&show_forks=false" />
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style class="cp-pen-styles">@import url("https://fonts.googleapis.com/css?family=Roboto:100,400");
*, *::after, *::before {
box-sizing: border-box;
}
html, body {
height: 100%;
min-height: 100%;
}
body {
margin: 0;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
font-family: 'Roboto', sans-serif;
background: -webkit-linear-gradient(top left, #c8c897, #6590A2);
background: linear-gradient(to bottom right, #c8c897, #6590A2);
}
[v-cloak] {
display: none;
}
a {
-webkit-tap-highlight-color: transparent;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
::-webkit-scrollbar {
display: none;
}
.stage {
position: relative;
overflow: hidden;
width: 100%;
height: 100%;
background: #fff;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
background: #1E384C;
-webkit-transition: background-color .3s;
transition: background-color .3s;
}
@media (min-width: 500px) {
.stage {
border-radius: 5px;
max-height: 550px;
max-width: 350px;
}
}
.stage.menu-open .microphone {
-webkit-transform: translate3d(-1em, 0, 0);
transform: translate3d(-1em, 0, 0);
opacity: 0;
}
.stage.menu-open .voices-menu__button {
z-index: 40;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
.stage.menu-open .menu {
z-index: 25;
}
.stage.menu-open .time {
-webkit-transform: translate3d(0, -200%, 0);
transform: translate3d(0, -200%, 0);
-webkit-transition: .5s opacity, .5s transform;
transition: .5s opacity, .5s transform;
opacity: 0;
}
.stage.menu-open button {
-webkit-transform: translate3d(0, 200%, 0);
transform: translate3d(0, 200%, 0);
-webkit-transition-delay: 0s;
transition-delay: 0s;
opacity: 0;
}
.stage.menu-open .percent {
-webkit-transition: .4s opacity, .4s transform;
transition: .4s opacity, .4s transform;
-webkit-transform: translate3d(0, 50%, 0);
transform: translate3d(0, 50%, 0);
opacity: 0;
}
.stage.menu-open .menu__item {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.stage.menu-open .menu__item:nth-child(1) {
-webkit-transition-delay: .2s;
transition-delay: .2s;
}
.stage.menu-open .menu__item:nth-child(2) {
-webkit-transition-delay: .3s;
transition-delay: .3s;
}
.stage.menu-open .menu__item:nth-child(3) {
-webkit-transition-delay: .4s;
transition-delay: .4s;
}
.stage.menu-open .menu__item:nth-child(4) {
-webkit-transition-delay: .5s;
transition-delay: .5s;
}
.stage.voices-open .voices-menu {
z-index: 35;
}
.stage.voices-open .voices-menu__bg {
-webkit-transform: scale(6);
transform: scale(6);
}
.stage.voices-open .voices-menu__close {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0) rotate(0);
transform: translate3d(0, 0, 0) rotate(0);
}
.stage.voices-open .voices-list-wrapper {
opacity: 1;
}
.stage.voices-open .voices-list__item {
opacity: 1;
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
-webkit-transition: opacity .15s, -webkit-transform .2s;
transition: opacity .15s, -webkit-transform .2s;
transition: opacity .15s, transform .2s;
transition: opacity .15s, transform .2s, -webkit-transform .2s;
}
.stage.voices-open .voices-list__item:nth-child(1) {
-webkit-transition-delay: 75ms;
transition-delay: 75ms;
}
.stage.voices-open .voices-list__item:nth-child(2) {
-webkit-transition-delay: 150ms;
transition-delay: 150ms;
}
.stage.voices-open .voices-list__item:nth-child(3) {
-webkit-transition-delay: 225ms;
transition-delay: 225ms;
}
.stage.voices-open .voices-list__item:nth-child(4) {
-webkit-transition-delay: 300ms;
transition-delay: 300ms;
}
.stage.voices-open .voices-list__item:nth-child(5) {
-webkit-transition-delay: 375ms;
transition-delay: 375ms;
}
.stage.voices-open .voices-list__item:nth-child(6) {
-webkit-transition-delay: 450ms;
transition-delay: 450ms;
}
.stage.voices-open .voices-list__item:nth-child(7) {
-webkit-transition-delay: 525ms;
transition-delay: 525ms;
}
.stage.voices-open .voices-list__item:nth-child(8) {
-webkit-transition-delay: 600ms;
transition-delay: 600ms;
}
.stage.voices-open .voices-list__item:nth-child(9) {
-webkit-transition-delay: 675ms;
transition-delay: 675ms;
}
.stage.voices-open .voices-list__item:nth-child(10) {
-webkit-transition-delay: 750ms;
transition-delay: 750ms;
}
.microphone {
z-index: 30;
position: absolute;
top: -.5em;
left: -.8em;
width: 70px;
height: 70px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
cursor: pointer;
color: rgba(255, 255, 255, 0.5);
-webkit-transition: opacity .3s, color .2s, -webkit-transform .3s;
transition: opacity .3s, color .2s, -webkit-transform .3s;
transition: opacity .3s, transform .3s, color .2s;
transition: opacity .3s, transform .3s, color .2s, -webkit-transform .3s;
}
.microphone:hover {
color: rgba(255, 255, 255, 0.8);
}
.microphone svg {
z-index: 2;
position: relative;
font-size: 2em;
width: 1em;
height: 1em;
}
.microphone:before, .microphone:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
opacity: 0;
}
.microphone:after {
z-index: 1;
background: rgba(255, 255, 255, 0.1);
-webkit-transition: opacity .3s;
transition: opacity .3s;
}
.microphone:before {
z-index: 2;
border: 3px solid rgba(255, 255, 255, 0.1);
opacity: 0;
}
.microphone.is-listening {
color: #d82e2e;
}
.microphone.is-listening:before {
-webkit-animation: pulseAway 1s infinite;
animation: pulseAway 1s infinite;
}
.microphone.is-listening:after {
opacity: 1;
-webkit-animation: pulse 1.5s linear infinite;
animation: pulse 1.5s linear infinite;
}
.microphone .voice-tooltip {
position: absolute;
top: 110%;
left: 25px;
padding: .4em .6em;
color: rgba(255, 255, 255, 0.8);
font-size: .8em;
font-weight: 300;
text-transform: uppercase;
white-space: nowrap;
background: rgba(255, 255, 255, 0.1);
border-radius: 3px;
}
.microphone .voice-tooltip:before {
content: '';
position: absolute;
bottom: 100%;
left: 5px;
width: 0;
height: 0;
border-style: solid;
border-width: 0 5px 5px 5px;
border-color: transparent transparent rgba(255, 255, 255, 0.1) transparent;
}
.fade-enter-active,
.fade-leave-active {
-webkit-transition: all .15s ease;
transition: all .15s ease;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
.voices-menu {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
@media (min-width: 500px) {
.voices-menu {
border-radius: 5px;
overflow: hidden;
}
}
.voices-menu__bg {
position: absolute;
top: -15em;
left: -15em;
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%;
width: 20em;
height: 20em;
color: #222;
-webkit-transform: scale(0.2);
transform: scale(0.2);
-webkit-transition: -webkit-transform .3s;
transition: -webkit-transform .3s;
transition: transform .3s;
transition: transform .3s, -webkit-transform .3s;
}
.voices-menu__button {
position: absolute;
top: 0;
left: 0;
padding: .8em .6em;
color: rgba(255, 255, 255, 0.5);
opacity: 0;
cursor: pointer;
-webkit-transform: translate3d(1em, 0, 0);
transform: translate3d(1em, 0, 0);
-webkit-transition: opacity .3s, color .2s, -webkit-transform .3s;
transition: opacity .3s, color .2s, -webkit-transform .3s;
transition: opacity .3s, transform .3s, color .2s;
transition: opacity .3s, transform .3s, color .2s, -webkit-transform .3s;
}
.voices-menu__button:hover {
color: rgba(255, 255, 255, 0.8);
}
.voices-menu__button > * {
vertical-align: middle;
font-weight: 300;
letter-spacing: 1px;
}
.voices-menu__button svg {
width: 1.8em;
height: 1.8em;
}
.voices-menu__close {
position: absolute;
top: 0;
right: 0;
padding: 10px 10px;
font-size: 2em;
font-weight: 300;
color: rgba(255, 255, 255, 0.5);
opacity: 0;
cursor: pointer;
-webkit-transform: translate3d(1em, 0, 0) rotate(45deg);
transform: translate3d(1em, 0, 0) rotate(45deg);
-webkit-transition: opacity .3s, color .2s, -webkit-transform .3s;
transition: opacity .3s, color .2s, -webkit-transform .3s;
transition: opacity .3s, transform .3s, color .2s;
transition: opacity .3s, transform .3s, color .2s, -webkit-transform .3s;
}
.voices-menu__close svg {
width: 1em;
height: 1em;
}
.voices-menu__close:hover {
color: rgba(255, 255, 255, 0.8);
}
.voices-list-wrapper {
position: absolute;
top: 60px;
left: 0;
bottom: 0;
right: 0;
overflow-y: auto;
opacity: 0;
}
.voices-list {
margin: 0;
padding: 0;
}
.voices-list__item {
display: block;
opacity: 0;
-webkit-transform: translate(0, 1em);
transform: translate(0, 1em);
}
.voices-list__item.is-selected .voices-list__icon {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0) rotate(0);
transform: translate3d(0, 0, 0) rotate(0);
}
.voices-list__icon {
position: relative;
margin-right: 20px;
color: #02C39A;
opacity: 0;
-webkit-transform: translate3d(-1em, 0, 0) rotate(-30deg);
transform: translate3d(-1em, 0, 0) rotate(-30deg);
-webkit-transition: opacity .2s, -webkit-transform .2s;
transition: opacity .2s, -webkit-transform .2s;
transition: opacity .2s, transform .2s;
transition: opacity .2s, transform .2s, -webkit-transform .2s;
}
.voices-list__icon svg {
width: 1.2em;
height: 1.2em;
}
.voices-list__link {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
padding: .5em 1.1em;
font-size: 1.3em;
font-weight: 300;
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
}
.voices-list__link:hover {
background: rgba(255, 255, 255, 0.05);
}
.voices-list__link span {
display: inline-block;
vertical-align: middle;
}
.voices-list__content {
line-height: 1;
}
.voices-list__content span {
font-size: .5em;
}
.voices-list__default {
color: #02C39A;
}
.menu {
z-index: 10;
position: absolute;
width: 100%;
height: 100%;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.menu__button {
z-index: 30;
position: absolute;
top: 0;
right: 0;
display: inline-block;
padding: 1.5em 1em;
cursor: pointer;
}
.menu__button:hover .menu__dot,
.menu__button:hover .menu__dot:before,
.menu__button:hover .menu__dot:after {
background: rgba(255, 255, 255, 0.8);
}
.menu__dot {
position: relative;
border-radius: 50%;
width: 6px;
height: 6px;
background: rgba(255, 255, 255, 0.5);
-webkit-transition: background .2s;
transition: background .2s;
}
.menu__dot:before, .menu__dot:after {
position: absolute;
content: '';
border-radius: 50%;
width: 6px;
height: 6px;
background: rgba(255, 255, 255, 0.5);
-webkit-transition: background .2s;
transition: background .2s;
}
.menu__dot:before {
top: 10px;
}
.menu__dot:after {
bottom: 10px;
}
.menu__list {
list-style: none;
padding: 0;
margin: 0;
width: 100%;
}
.menu__item {
overflow: hidden;
opacity: 0;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
-webkit-transition: .4s transform, .4s opacity;
transition: .4s transform, .4s opacity;
}
.menu__item a {
font-size: 1.8em;
font-weight: 300;
display: block;
color: rgba(255, 255, 255, 0.5);
text-transform: uppercase;
text-decoration: none;
padding: .5em 1.5em;
}
.menu__item a span {
display: inline-block;
vertical-align: middle;
-webkit-transition: -webkit-transform .3s;
transition: -webkit-transform .3s;
transition: transform .3s;
transition: transform .3s, -webkit-transform .3s;
}
.menu__item a:hover svg, .menu__item a:focus svg {
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
.menu__item a:hover .water-glass__water, .menu__item a:focus .water-glass__water {
fill: #32BAFA;
-webkit-transform: scale(1, 0.8);
transform: scale(1, 0.8);
}
.menu__item a:hover .coffee-cup__coffee, .menu__item a:focus .coffee-cup__coffee {
fill: #BF9E87;
-webkit-transform: scale(1, 0.8);
transform: scale(1, 0.8);
}
.menu__item a:hover .beer-glass__beer, .menu__item a:focus .beer-glass__beer {
fill: #E18E02;
-webkit-transform: scale(1, 0.8);
transform: scale(1, 0.8);
}
.menu__item a:hover .clock__short, .menu__item a:focus .clock__short {
fill: #02C39A;
-webkit-transform-origin: 0% 50%;
transform-origin: 0% 50%;
-webkit-transform: rotate(20deg);
transform: rotate(20deg);
-webkit-transition: color .2s, -webkit-transform 1s;
transition: color .2s, -webkit-transform 1s;
transition: transform 1s, color .2s;
transition: transform 1s, color .2s, -webkit-transform 1s;
}
.menu__item a:hover .clock__long, .menu__item a:focus .clock__long {
fill: #02C39A;
-webkit-transition: color .2s, -webkit-transform 1s;
transition: color .2s, -webkit-transform 1s;
transition: transform 1s, color .2s;
transition: transform 1s, color .2s, -webkit-transform 1s;
-webkit-transform-origin: 50% 95%;
transform-origin: 50% 95%;
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
.menu__item svg {
display: inline-block;
vertical-align: middle;
width: 1em;
height: 1em;
margin-right: 1em;
-webkit-transition: -webkit-transform .3s;
transition: -webkit-transform .3s;
transition: transform .3s;
transition: transform .3s, -webkit-transform .3s;
}
.menu__item svg path {
fill: #fff;
-webkit-transition: all .3s;
transition: all .3s;
-webkit-transform-origin: 100% 100%;
transform-origin: 100% 100%;
}
.browser-support {
color: #fff;
font-size: .8rem;
text-align: center;
padding: .5rem;
}
.content {
z-index: 20;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
.time {
overflow: hidden;
padding: 1em;
font-size: 1.1em;
text-align: center;
-webkit-transition: .5s .2s opacity, .5s transform .2s;
transition: .5s .2s opacity, .5s transform .2s;
}
.timer__item {
-webkit-transition: all 1s;
transition: all 1s;
margin-right: 10px;
color: rgba(255, 255, 255, 0.8);
}
.timer__item:first-child, .timer__item:nth-child(3) {
color: rgba(255, 255, 255, 0.2);
}
.timer-enter, .timer-leave-to {
opacity: 0;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
.timer-leave-to {
-webkit-transition-duration: .5s;
transition-duration: .5s;
}
.timer-leave-active {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.percent {
z-index: 2;
position: relative;
font-size: 7em;
font-weight: 100;
color: rgba(255, 255, 255, 0.7);
-webkit-transition: .4s .2s opacity, .4s .2s transform;
transition: .4s .2s opacity, .4s .2s transform;
}
.percent > div {
display: inline-block;
}
.percent > span {
margin-left: -.4em;
font-size: .5em;
}
.percent-left-enter-active, .percent-left-leave-active {
-webkit-transition: -webkit-transform .1s ease;
transition: -webkit-transform .1s ease;
transition: transform .1s ease;
transition: transform .1s ease, -webkit-transform .1s ease;
}
.percent-left-enter, .percent-left-leave-to {
-webkit-transform: scale(1.05);
transform: scale(1.05);
}
button {
z-index: 20;
position: absolute;
display: block;
width: 70%;
margin: auto;
left: 0;
right: 0;
bottom: 1.5em;
padding: .6em;
color: rgba(255, 255, 255, 0.8);
font-size: 1.1em;
font-weight: 300;
letter-spacing: 1px;
text-transform: uppercase;
background: transparent;
border: 1px solid rgba(255, 255, 255, 0.8);
border-radius: 2em;
outline: none;
-webkit-transition: .2s background, .4s .3s transform, .4s .3s opacity;
transition: .2s background, .4s .3s transform, .4s .3s opacity;
cursor: pointer;
}
button:hover {
background: #fff;
color: currentColor;
}
.waves {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
-webkit-transition: .4s transform ease;
transition: .4s transform ease;
-webkit-transform-origin: bottom center;
transform-origin: bottom center;
}
@media (min-width: 500px) {
.waves {
border-radius: 5px;
}
}
.wave {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
-webkit-animation: wave 1s linear infinite;
animation: wave 1s linear infinite;
}
.wave--front {
z-index: 2;
color: #32BAFA;
}
.wave--back {
z-index: 1;
color: #2C7FBE;
-webkit-animation-direction: reverse;
animation-direction: reverse;
}
.water {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 80%;
background: currentColor;
}
.water svg {
position: absolute;
width: 100%;
left: 0;
right: 0;
bottom: 99.9%;
}
.water:first-of-type {
-webkit-transform: translate(-100%, 0);
transform: translate(-100%, 0);
}
svg {
fill: currentColor;
}
@-webkit-keyframes wave {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
50% {
-webkit-transform: translate3d(50%, 0.5em, 0);
transform: translate3d(50%, 0.5em, 0);
}
100% {
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
}
@keyframes wave {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
50% {
-webkit-transform: translate3d(50%, 0.5em, 0);
transform: translate3d(50%, 0.5em, 0);
}
100% {
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
}
@-webkit-keyframes pulse {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
50% {
-webkit-transform: scale(1.1);
transform: scale(1.1);
}
100% {
-webkit-transform: scale(1);
transform: scale(1);
}
}
@keyframes pulse {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
50% {
-webkit-transform: scale(1.1);
transform: scale(1.1);
}
100% {
-webkit-transform: scale(1);
transform: scale(1);
}
}
@-webkit-keyframes pulseAway {
0% {
opacity: 0;
-webkit-transform: scale(0.5);
transform: scale(0.5);
}
50% {
opacity: 1;
}
100% {
-webkit-transform: scale(1.4);
transform: scale(1.4);
}
}
@keyframes pulseAway {
0% {
opacity: 0;
-webkit-transform: scale(0.5);
transform: scale(0.5);
}
50% {
opacity: 1;
}
100% {
-webkit-transform: scale(1.4);
transform: scale(1.4);
}
}
</style></head><body>
<div id="stage" class="stage" :class="{'menu-open': menuOpen, 'voices-open': voicesOpen}" :style="{ color: activeReminder.waveFrontColor, backgroundColor: stageBg }" v-cloak>
<div class="menu__button" @click="toggleMenu">
<div class="menu__dot"></div>
</div>
<div class="microphone" v-if="supportSpeechRecognition" :class="{'is-listening': isListening }" @click="startListenVoiceCommands">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M12 16c2.206 0 4-1.795 4-4v-6c0-2.206-1.794-4-4-4s-4 1.794-4 4v6c0 2.205 1.794 4 4 4z"></path>
<path d="M19 12v-2c0-0.552-0.447-1-1-1s-1 0.448-1 1v2c0 2.757-2.243 5-5 5s-5-2.243-5-5v-2c0-0.552-0.447-1-1-1s-1 0.448-1 1v2c0 3.52 2.613 6.432 6 6.92v1.080h-3c-0.553 0-1 0.447-1 1s0.447 1 1 1h8c0.553 0 1-0.447 1-1s-0.447-1-1-1h-3v-1.080c3.387-0.488 6-3.4 6-6.92z"></path>
</svg>
<div class="voice-tooltip" v-show="isListening">
<transition name="fade" mode="out-in">
<span :key="tooltipText">{{ tooltipText }}</span>
</transition>
</div>
</div>
<div class="voices-menu">
<svg class="voices-menu__bg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><title>sphere</title><circle cx="25" cy="25" r="25"/></svg>
<div class="voices-menu__button" @click="toggleVoicesMenu">
<svg xmlns="http://www.w3.org/2000/svg" width="768" height="768" viewBox="0 0 768 768">
<path d="M523.5 448.5h108c4.5-21 9-42 9-64.5s-4.5-43.5-9-64.5h-108c3 21 4.5 42 4.5 64.5s-1.5 43.5-4.5 64.5zM466.5 625.5c58.5-19.5 109.5-61.5 139.5-114h-94.5c-10.5 40.5-25.5 78-45 114zM459 448.5c3-21 4.5-42 4.5-64.5s-1.5-43.5-4.5-64.5h-150c-3 21-4.5 42-4.5 64.5s1.5 43.5 4.5 64.5h150zM384 639c27-39 48-81 61.5-127.5h-123c13.5 46.5 34.5 88.5 61.5 127.5zM256.5 256.5c10.5-40.5 25.5-78 45-114-58.5 19.5-109.5 61.5-139.5 114h94.5zM162 511.5c30 52.5 81 94.5 139.5 114-19.5-36-34.5-73.5-45-114h-94.5zM136.5 448.5h108c-3-21-4.5-42-4.5-64.5s1.5-43.5 4.5-64.5h-108c-4.5 21-9 42-9 64.5s4.5 43.5 9 64.5zM384 129c-27 39-48 81-61.5 127.5h123c-13.5-46.5-34.5-88.5-61.5-127.5zM606 256.5c-30-52.5-81-94.5-139.5-114 19.5 36 34.5 73.5 45 114h94.5zM384 64.5c177 0 319.5 142.5 319.5 319.5s-142.5 319.5-319.5 319.5-319.5-142.5-319.5-319.5 142.5-319.5 319.5-319.5z"></path>
</svg>
<span>Select voice</span>
</div>
<div class="voices-menu__close" @click="toggleVoicesMenu">
<svg xmlns="http://www.w3.org/2000/svg" width="768" height="768" viewBox="0 0 768 768">
<path d="M607.5 205.5l-178.5 178.5 178.5 178.5-45 45-178.5-178.5-178.5 178.5-45-45 178.5-178.5-178.5-178.5 45-45 178.5 178.5 178.5-178.5z"></path>
</svg>
</div>
<div class="voices-list-wrapper">
<ul class="voices-list">
<li class="voices-list__item" :class="{'is-selected': selectedVoice.name === voice.name }" v-for="voice in voices" :key="voice.lang">
<a href="#" class="voices-list__link" @click.prevent="voiceSelected(voice)">
<span class="voices-list__icon">
<svg xmlns="http://www.w3.org/2000/svg" width="768" height="768" viewBox="0 0 768 768">
<path d="M672 160q13.75 0 22.875 9.125t9.125 22.875q0 13.5-9.25 22.75l-384 384q-9.25 9.25-22.75 9.25t-22.75-9.25l-192-192q-9.25-9.25-9.25-22.75 0-13.75 9.125-22.875t22.875-9.125q13.5 0 22.75 9.25l169.25 169.5 361.25-361.5q9.25-9.25 22.75-9.25z"></path>
</svg>
</span>
<div class="voices-list__content">
<div>{{voice.name}}</div>
<span>{{voice.lang}}</span>
<span v-if="voice.default" class="voices-list__default">Default</span>
</div>
</a>
</li>
</ul>
</div>
</div>
<div class="menu">
<ul class="menu__list">
<li class="menu__item" @mouseover="mouseOver('water')" @mouseout="mouseOut()" @touchstart="mouseOver('water')" @touchend="mouseOut()">
<a href="#" @click.prevent="start('water')">
<svg id="coffee-cup" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50">
<title>coffee-cup-01</title>
<path class="water-glass" d="M39.92,45H25V43.21H38.15L43.14,4l2,.2ZM25,45H10.08L4.89,4.15l2-.2,5,39.26H25Z"/>
<path class="water-glass__water" d="M39.09,6.88s-3.13,2-5.48,0c-4.92,2.65-7.72,0-7.72,0s-4.59,2.76-7.94,0c-4.47,3.09-7,0-7,0l3.91,33.76H35Z"/>
</svg>
<span>Water break</span>
</a>
</li>
<li class="menu__item" @mouseover="mouseOver('coffee')" @mouseout="mouseOut()" @touchstart="mouseOver('coffee')" @touchend="mouseOut()">
<a href="#" @click.prevent="start('coffee')">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50">
<title>coffee-cup</title>
<path class="coffee-cup" d="M49.42,21.07a9.69,9.69,0,0,0-2.17-6.55,10.16,10.16,0,0,0-7.08-3.12c-.14-2.47-.38-4-.38-4H36.58S42,39.54,20.43,39.56C-1.87,39.57,4.16,7.37,4.16,7.37H1.07S-4.29,43,20.43,43c9.31,0,14.35-5.06,17-11.37C40.47,31.4,49.43,29.84,49.42,21.07Zm-11,7.82a49,49,0,0,0,1.81-14.83,8.13,8.13,0,0,1,5.52,2.4,6.76,6.76,0,0,1,1.49,4.63C47.29,26.71,41.58,28.39,38.45,28.89Z"/>
<path class="coffee-cup__coffee" d="M7.07,11.94H33.73s3.72,23.65-13.3,23.65S7.07,11.94,7.07,11.94Z"/>
</svg>
<span>Coffee break</span>
</a>
</li>
<li class="menu__item" @mouseover="mouseOver('break')" @mouseout="mouseOut()" @touchstart="mouseOver('break')" @touchend="mouseOut()">
<a href="#" @click.prevent="start('break')">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50">
<title>clock</title>
<path class="clock" d="M24.62,47.08A21.88,21.88,0,1,1,46.49,25.21,21.9,21.9,0,0,1,24.62,47.08Zm0-41.75A19.88,19.88,0,1,0,44.49,25.21,19.9,19.9,0,0,0,24.62,5.33Z"/>
<path class="clock__short" d="M34.49,26.71H24.62a1.5,1.5,0,0,1,0-3h9.88a1.5,1.5,0,0,1,0,3Z"/>
<path class="clock__long" d="M24.62,26.71a1.5,1.5,0,0,1-1.5-1.5V9.54a1.5,1.5,0,0,1,3,0V25.21A1.5,1.5,0,0,1,24.62,26.71Z"/>
</svg>
<span>Office Break</span>
</a>
</li>
<li class="menu__item" @mouseover="mouseOver('beer')" @mouseout="mouseOut()" @touchstart="mouseOver('beer')" @touchend="mouseOut()">
<a href="#" @click.prevent="start('beer')">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50">
<title>beer</title>
<path class="beer-glass" d="M45.92,15.71c-1.63-1.88-6.55-1.15-9.2-.58-.15-2.82-.25-5.46-.26-7.76h-2c0,3.69.27,8.17.55,12.92.48,8.19,1.21,20.56-.59,21.86-3.17,2.29-29,2.49-31,.23C2,40.7,2.45,23.3,3.69,7.45l-1-.08-1-.08C1.08,15.1-.69,40.8,1.95,43.72c1.39,1.54,8.15,2.19,15.27,2.19,8,0,16.56-.83,18.38-2.14,1.3-.94,1.84-3.56,2-7.66,2-.05,6.17-.29,8.09-1.36.78-.44,1.3-1.49,1.62-3.32C48,27.21,47.61,17.67,45.92,15.71Zm-.4,13.59c-.27,3.16-.85,3.7-.84,3.7-1.4.78-5,1-7.1,1.11,0-3.71-.25-8.38-.58-13.93q-.09-1.53-.17-3c3.26-.71,6.88-.93,7.58-.13S46,24.13,45.52,29.3Z"/>
<path class="beer-glass__beer" d="M5.9,12.92s-2.57,25.8,0,27.71,24.3,1,26.59,0S32,12.92,32,12.92Z"/>
</svg>
<span>Beer Break</span>
</a>
</li>
</ul>
</div>
<div class="browser-support" v-if="!supportSpeechSynth">
Your browser doesn't <strong>support</strong> speech synthesis.
</div>
<div class="time">
<transition-group name="timer" tag="div">
<div v-for="time in timer" class="timer__item" :key="time.id">
{{ time.value }}
</div>
</transition-group>
</div>
<div class="waves" :style="waveStyles">
<div class="wave wave--back" :style="{ color: activeReminder.waveBackColor }">
<div class="water">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 32" preserveAspectRatio="none"><title>wave2</title><path d="M350,17.32V32H0V17.32C116.56,65.94,175-39.51,350,17.32Z"/></svg>
</div>
<div class="water">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 32" preserveAspectRatio="none"><title>wave2</title><path d="M350,17.32V32H0V17.32C116.56,65.94,175-39.51,350,17.32Z"/></svg>
</div>
</div>
<div class="wave wave--front" :style="{ color: activeReminder.waveFrontColor }">
<div class="water">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 32" preserveAspectRatio="none"><title>wave2</title><path d="M350,17.32V32H0V17.32C116.56,65.94,175-39.51,350,17.32Z"/></svg>
</div>
<div class="water">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 32" preserveAspectRatio="none"><title>wave2</title><path d="M350,17.32V32H0V17.32C116.56,65.94,175-39.51,350,17.32Z"/></svg>
</div>
</div>
</div>
<div class="content">
<div class="percent">
<transition name="percent-left" mode="out-in">
<div :key="percentsLeft">{{ percentsLeft }}</div>
</transition>
<span>%</span>
</div>
</div>
<button @click="reset">
{{ percentsLeft > 0 ? activeReminder.buttonTxt : 'Reset' }}
</button>
</div>
<script src='//production-assets.codepen.io/assets/common/stopExecutionOnTimeout-b2a7b3fe212eaa732349046d8416e00a9dec26eb7fd347590fbced3ab38af52e.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/countdown/2.6.0/countdown.min.js'></script><script src='https://unpkg.com/vue/dist/vue.min.js'></script>
<script >'use strict';
var SpeechRecognition = SpeechRecognition || window.webkitSpeechRecognition || undefined;
var numbers = Array.apply(null, Array(101)).map(function (_, i) {
return i;
});
if (SpeechRecognition) {
var SpeechGrammarList = SpeechGrammarList || window.webkitSpeechGrammarList || undefined;
var SpeechRecognitionEvent = SpeechRecognitionEvent || window.webkitSpeechRecognitionEvent || undefined;
var commands = ['reset', 'timer'].concat(numbers);
var grammar = '#JSGF V1.0; grammar colors; public <color> = ' + commands.join(' | ') + ' ;';
var speechRecognitionList = new SpeechGrammarList();
speechRecognitionList.addFromString(grammar, 1);
var recognition = new SpeechRecognition();
recognition.grammars = speechRecognitionList;
//recognition.continuous = false;
recognition.lang = 'en-US';
recognition.interimResults = true;
recognition.maxAlternatives = 1;
}
var speechSynth = new SpeechSynthesisUtterance();
var padDigits = function padDigits(number, digits) {
return Array(Math.max(digits - String(number).length + 1, 0)).join(0) + number;
};
var calculatePercentsLeft = function calculatePercentsLeft(value, from) {
return Math.floor(Math.ceil(value / 1000) / (from * 60) * 100);
};
var calculateScaleFactor = function calculateScaleFactor(percent) {
return 1 - (100 - percent) / 100;
};
function guid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}
var settings = {
water: {
warningMsg: 'Remember to drink',
timeIsUpMsg: 'Time\'s up. You really need to drink now',
buttonTxt: 'Drink',
waveFrontColor: '#32BAFA',
waveBackColor: '#2C7FBE',
stageBg: '#1E384C',
durationInMinutes: 1
},
coffee: {
warningMsg: 'It\'s almost coffee time.',
timeIsUpMsg: 'Time\'s up. Let\'s take a coffee break!',
buttonTxt: 'Drink coffee',
waveFrontColor: '#b39374',
waveBackColor: '#7a6057',
stageBg: '#392a2c',
durationInMinutes: 1
},
break: {
warningMsg: 'It is time to rest your eyes soon!',
timeIsUpMsg: 'Time\'s up. Now, it\'s really time to rest your eyes!',
buttonTxt: 'Take a break',
waveFrontColor: '#02C39A',
waveBackColor: '#028090',
stageBg: '#012F35',
durationInMinutes: 1
},
beer: {
warningMsg: 'I know this sounds scary, but it\'s almost time for another beer',
timeIsUpMsg: 'It\'s been while since the last beer!',
buttonTxt: 'Have a beer',
waveFrontColor: '#F1B10F',
waveBackColor: '#FFFFFF',
stageBg: '#5A3900',
durationInMinutes: 60
}
};
new Vue({
el: '#stage',
data: function data() {
return {
color: '',
percents: [100],
percentsLeft: 100,
secondsLeft: 0,
waveStyles: '',
duration: 1,
timer: [],
voicesOpen: false,
voices: [],
selectedVoice: {},
countdownObj: {},
activeReminder: settings.water,
menuOpen: false,
isListening: false,
tooltipText: 'Say eg. "reset"',
stageBg: settings.water.stageBg
};
},
mounted: function mounted() {
var _this = this;
this.resetTimer();
this.voices = speechSynthesis.getVoices();
if (this.voices.length === 0) {
speechSynthesis.onvoiceschanged = function () {
_this.voices = speechSynthesis.getVoices();
};
}
},
computed: {
supportSpeechSynth: function supportSpeechSynth() {
return 'speechSynthesis' in window;
},
supportSpeechRecognition: function supportSpeechRecognition() {
return SpeechRecognition;
}
},
watch: {
percentsLeft: function percentsLeft(val, oldVal) {
if (val === oldVal) {
return;
}
this.percents.splice(0, 1);
this.percents.push(val);
}
},
methods: {
setActiveReminder: function setActiveReminder(reminder) {
this.activeReminder = settings[reminder];
this.stageBg = this.activeReminder.stageBg;
},
toggleMenu: function toggleMenu() {
this.menuOpen = !this.menuOpen;
if (this.menuOpen) {
this.pauseTimer();
this.waveStyles = 'transform: translate3d(0,100%,0); transition-delay: .25s;';
} else {
this.continueTimer();
}
},
toggleVoicesMenu: function toggleVoicesMenu() {
this.voicesOpen = !this.voicesOpen;
},
voiceSelected: function voiceSelected(voice) {
this.selectedVoice = voice;
speechSynth.voice = voice;
},
start: function start(reminder) {
this.setActiveReminder(reminder);
this.percents = [100];
this.timer = [];
this.menuOpen = false;
this.resetTimer();
},
resetTimer: function resetTimer() {
var durationInSeconds = 60 * this.activeReminder.durationInMinutes;
this.startTimer(durationInSeconds);
},
startTimer: function startTimer(secondsLeft) {
var _this2 = this;
var now = new Date();
// later on, this timer may be stopped
if (this.countdown) {
window.clearInterval(this.countdown);
}
this.countdown = countdown(function (ts) {
_this2.secondsLeft = Math.ceil(ts.value / 1000);
_this2.percentsLeft = calculatePercentsLeft(ts.value, _this2.activeReminder.durationInMinutes);
_this2.waveStyles = 'transform: scale(1,' + calculateScaleFactor(_this2.percentsLeft) + ')';
_this2.updateCountdown(ts);
if (_this2.percentsLeft == 10) {
_this2.giveWarning();
}
if (_this2.percentsLeft <= 0) {
_this2.timeIsUpMessage();
_this2.pauseTimer();
_this2.timer = [];
setTimeout(function () {
_this2.startListenVoiceCommands();
}, 1500);
}
}, now.getTime() + secondsLeft * 1000);
},
updateCountdown: function updateCountdown(ts) {
if (this.timer.length > 2) {
this.timer.splice(2);
}
var newTime = {
id: guid(),
value: padDigits(ts.minutes, 2) + ':' + padDigits(ts.seconds, 2)
};
this.timer.unshift(newTime);
},
pauseTimer: function pauseTimer() {
window.clearInterval(this.countdown);
},
continueTimer: function continueTimer() {
if (this.secondsLeft > 0) {
this.startTimer(this.secondsLeft - 1);
}
},
giveWarning: function giveWarning() {
speechSynth.text = this.activeReminder.warningMsg;
window.speechSynthesis.speak(speechSynth);
},
timeIsUpMessage: function timeIsUpMessage() {
speechSynth.text = this.activeReminder.timeIsUpMsg;
window.speechSynthesis.speak(speechSynth);
},
timerResetMessage: function timerResetMessage() {
speechSynth.text = 'Timer reset. Time left ' + this.activeReminder.durationInMinutes + ' ' + (this.activeReminder.durationInMinutes > 1 ? 'minutes' : 'minute');
window.speechSynthesis.speak(speechSynth);
},
reset: function reset() {
this.resetTimer();
this.timerResetMessage();
},
startListenVoiceCommands: function startListenVoiceCommands() {
var _this3 = this;
if (this.isListening || !this.supportSpeechRecognition) return;
this.isListening = true;
recognition.start();
recognition.onresult = function (event) {
var last = event.results.length - 1;
var transcript = event.results[last][0].transcript;
var splittedTranscript = transcript.split(' ');
var isFinal = event.results[last].isFinal;
_this3.tooltipText = transcript;
if (transcript == "reset") {
_this3.resetTimer();
_this3.timerResetMessage();
}
if (splittedTranscript.length >= 3 && splittedTranscript[0] == 'timer' && isFinal && numbers.includes(Number(splittedTranscript[1])) && (splittedTranscript[2] == 'minute' || splittedTranscript[2] == 'minutes')) {
_this3.activeReminder.durationInMinutes = numbers[splittedTranscript[1]];
_this3.resetTimer();
_this3.timerResetMessage();
}
};
recognition.onend = function () {
_this3.isListening = false;
_this3.tooltipText == '';
recognition.stop();
};
recognition.onsoundend = function () {
_this3.isListening = false;
recognition.stop();
};
},
mouseOver: function mouseOver(type) {
this.stageBg = settings[type].stageBg;
},
mouseOut: function mouseOut() {
this.stageBg = this.activeReminder.stageBg;
}
}
});
//# sourceURL=pen.js
</script>
</body></html>