├── README.md ├── app.js ├── index.html ├── sounds ├── beach.mp3 └── rain.mp3 ├── style.css ├── svg ├── beach.svg ├── moving-outline.svg ├── pause.svg ├── play.svg ├── rain.svg ├── replay.svg └── track-outline.svg └── video ├── beach.mp4 └── rain.mp4 /README.md: -------------------------------------------------------------------------------- 1 | # meditation-app 2 | Meditation app tutorial 3 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const song = document.querySelector(".song"); 2 | const play = document.querySelector(".play"); 3 | const replay = document.querySelector(".replay"); 4 | const outline = document.querySelector(".moving-outline circle"); 5 | const video = document.querySelector(".vid-container video"); 6 | //Sounds 7 | const sounds = document.querySelectorAll(".sound-picker button"); 8 | //Time Display 9 | const timeDisplay = document.querySelector(".time-display"); 10 | const outlineLength = outline.getTotalLength(); 11 | //Duration 12 | const timeSelect = document.querySelectorAll(".time-select button"); 13 | let fakeDuration = 600; 14 | 15 | outline.style.strokeDashoffset = outlineLength; 16 | outline.style.strokeDasharray = outlineLength; 17 | timeDisplay.textContent = `${Math.floor(fakeDuration / 60)}:${Math.floor( 18 | fakeDuration % 60 19 | )}`; 20 | 21 | sounds.forEach(sound => { 22 | sound.addEventListener("click", function() { 23 | song.src = this.getAttribute("data-sound"); 24 | video.src = this.getAttribute("data-video"); 25 | checkPlaying(song); 26 | }); 27 | }); 28 | 29 | play.addEventListener("click", function() { 30 | checkPlaying(song); 31 | }); 32 | 33 | replay.addEventListener("click", function() { 34 | restartSong(song); 35 | 36 | }); 37 | 38 | 39 | const restartSong = song =>{ 40 | let currentTime = song.currentTime; 41 | song.currentTime = 0; 42 | console.log("ciao") 43 | 44 | } 45 | 46 | timeSelect.forEach(option => { 47 | option.addEventListener("click", function() { 48 | fakeDuration = this.getAttribute("data-time"); 49 | timeDisplay.textContent = `${Math.floor(fakeDuration / 60)}:${Math.floor( 50 | fakeDuration % 60 51 | )}`; 52 | }); 53 | }); 54 | 55 | const checkPlaying = song => { 56 | if (song.paused) { 57 | song.play(); 58 | video.play(); 59 | play.src = "./svg/pause.svg"; 60 | } else { 61 | song.pause(); 62 | video.pause(); 63 | play.src = "./svg/play.svg"; 64 | } 65 | }; 66 | 67 | song.ontimeupdate = function() { 68 | let currentTime = song.currentTime; 69 | let elapsed = fakeDuration - currentTime; 70 | let seconds = Math.floor(elapsed % 60); 71 | let minutes = Math.floor(elapsed / 60); 72 | timeDisplay.textContent = `${minutes}:${seconds}`; 73 | let progress = outlineLength - (currentTime / fakeDuration) * outlineLength; 74 | outline.style.strokeDashoffset = progress; 75 | 76 | if (currentTime >= fakeDuration) { 77 | song.pause(); 78 | song.currentTime = 0; 79 | play.src = "./svg/play.svg"; 80 | video.pause(); 81 | } 82 | }; -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Audio App 10 | 11 | 12 |
13 |
14 | 17 |
18 |
19 | 20 | 21 | 22 |
23 |
24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |

0:00

37 |
38 |
39 | 40 | 41 |
42 |
43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /sounds/beach.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/developedbyed/meditation-app/ecac767b7b2bf4c11249a32748093cc373a218bb/sounds/beach.mp3 -------------------------------------------------------------------------------- /sounds/rain.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/developedbyed/meditation-app/ecac767b7b2bf4c11249a32748093cc373a218bb/sounds/rain.mp3 -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | .app { 8 | height: 100vh; 9 | display: flex; 10 | justify-content: space-evenly; 11 | align-items: center; 12 | font-family: "Montserrat", sans-serif; 13 | } 14 | 15 | .time-select, 16 | .sound-picker { 17 | height: 80%; 18 | display: flex; 19 | justify-content: space-evenly; 20 | align-items: center; 21 | flex-direction: column; 22 | flex: 1; 23 | } 24 | .time-select button, 25 | .sound-picker button { 26 | color: white; 27 | width: 30%; 28 | height: 10%; 29 | background: none; 30 | font-size: 20px; 31 | border-radius: 5px; 32 | cursor: pointer; 33 | border: 2px solid white; 34 | transition: all 0.5s ease; 35 | } 36 | 37 | .sound-picker button { 38 | border: none; 39 | height: 120px; 40 | width: 120px; 41 | padding: 30px; 42 | border-radius: 50%; 43 | } 44 | .sound-picker button:nth-child(1) { 45 | background: #4972a1; 46 | } 47 | .sound-picker button:nth-child(2) { 48 | background: #a14f49; 49 | } 50 | .sound-picker button img { 51 | height: 100%; 52 | } 53 | 54 | .time-select button:hover { 55 | background: white; 56 | color: black; 57 | } 58 | 59 | .player-container { 60 | position: relative; 61 | height: 80%; 62 | display: flex; 63 | justify-content: space-evenly; 64 | align-items: center; 65 | flex-direction: column; 66 | flex: 1; 67 | } 68 | 69 | .player-container svg { 70 | position: absolute; 71 | height: 50%; 72 | top: 50%; 73 | left: 50%; 74 | transform: translate(-50%, -50%) rotate(-90deg); 75 | pointer-events: none; 76 | } 77 | .player-container svg circle { 78 | transition: all 0.2s ease-in-out; 79 | } 80 | .time-display { 81 | color: white; 82 | position: absolute; 83 | font-size: 50px; 84 | bottom: 10%; 85 | } 86 | 87 | video { 88 | position: fixed; 89 | top: 0%; 90 | left: 0%; 91 | width: 100%; 92 | z-index: -10; 93 | } 94 | -------------------------------------------------------------------------------- /svg/beach.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /svg/moving-outline.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /svg/pause.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /svg/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /svg/rain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /svg/replay.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /svg/track-outline.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /video/beach.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/developedbyed/meditation-app/ecac767b7b2bf4c11249a32748093cc373a218bb/video/beach.mp4 -------------------------------------------------------------------------------- /video/rain.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/developedbyed/meditation-app/ecac767b7b2bf4c11249a32748093cc373a218bb/video/rain.mp4 --------------------------------------------------------------------------------