Skip to content

Commit

Permalink
Added icons, sticky controls, re-arranged controls, refactored code
Browse files Browse the repository at this point in the history
  • Loading branch information
irshadshalu committed Jun 19, 2020
1 parent 00cd3f3 commit 0f0cde8
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 71 deletions.
1 change: 0 additions & 1 deletion public/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ body {
}

input[type=range] {
width: 20em;
margin: 6.3px 0;
background-color: transparent;
-webkit-appearance: none;
Expand Down
1 change: 1 addition & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<meta property="og:title" content="Music Grid Piano. Create Beautiful Short Music Snippets" />
<meta property="og:url" content="https://music-grid.surge.sh" />
<meta property="og:image" content="/favicon.png" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-169258065-1"></script>
Expand Down
102 changes: 33 additions & 69 deletions src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
<script>
import Row from './Row.svelte';
import ClipboardJS from 'clipboard';
import Controls from './Controls.svelte';
import {initAudio, playRow} from './Music.svelte';
let rows = 16;
export let config = {
playing: false,
speed: 200,
rows: 16
}
let columns = 12;
let grid = [];
let playing = false;
let speed = 200;
let gameInterval;
let curRow = 0;
let lastRow = 0;
let shareMessage = 'Share';
let started = false;
let urlUpdatedRecently = false;
const togglePlaying = async () => {
playing = !playing;
config.playing = !config.playing;
if(!started) {
startPlaying();
}
}
const startPlaying = async () => {
if(!started) {
config.playing = true;
started = true;
await initAudio();
}
}
const stopPlaying = () => {
playing = false;
config.playing = false;
if(lastRow < grid.length) {
grid[lastRow].isPlaying = false;
}
Expand Down Expand Up @@ -55,9 +63,9 @@
}
const initGrid = (hash) => {
playing = false;
config.playing = false;
let array = hash.split('&')[0].slice(1).split('-').map(x => parseInt(x, 10));
rows = array.length - 1;
config.rows = array.length - 1;
grid = []
for (var i = array.length - 2; i >= 0; i--) {
let temp = [... Array(columns).fill(false)];
Expand All @@ -67,62 +75,26 @@
grid.push(temp.reverse());
}
if(hash.split('&').length > 1) {
speed = parseInt(hash.split('&')[1], 10);
config.speed = parseInt(hash.split('&')[1], 10);
}
}
new ClipboardJS('.share', {
text: function() {
encodeGridToUrl(grid);
shareMessage = 'Link copied';
setTimeout(function() {
shareMessage = 'Share';
}, 3000);
return window.location.href;
}
});
const changeSpeed = (bpm) => {
clearInterval(gameInterval);
gameInterval = setInterval(() => {
if(playing) {
if(config.playing) {
grid[lastRow].isPlaying = false;
grid[curRow].isPlaying = true;
playRow(grid[curRow]);
lastRow = curRow;
curRow = (curRow + 1) % grid.length;
}
}, 60*1000 / bpm);
updateUrl(grid);
}
const encodeGridToUrl = (grid) => {
let res = ''
for (var i = grid.length - 1; i >= 0; i--) {
let temp = 0, k = 1;
for (var j = grid[i].length - 1; j >= 0; j--) {
temp = temp + k * grid[i][j];
k = k * 2;
}
res += (temp + '-');
}
history.replaceState({}, '', '#' + res + '&' + speed);
}
const updateUrl = (grid) => {
if(!urlUpdatedRecently) {
encodeGridToUrl(grid);
urlUpdatedRecently = true;
setTimeout(() => {urlUpdatedRecently = false}, 1000);
}
}
$: changeSpeed(speed);
$: updateUrl(grid);
$: changeSpeed(config.speed);
clearGrid(rows);
clearGrid(config.rows);
if(window.location.hash !== '') {
initGrid(window.location.hash);
Expand Down Expand Up @@ -161,29 +133,21 @@
<div class="container" align="center">
<h3>Music Grid</h3>
<span class="tagline">Turn on sound. Tap on the grid. Hit Play button. You'll figure it out ;)</span>
<br/><br/>
<label>
Rows : {rows}<br/>
<input bind:value={rows} on:input={() => resizeGrid(rows)} type="range" min="10" max="100" class="slider">
</label>
<button on:click={togglePlaying}>
{ playing ? "Pause" : "Play" }
</button>&nbsp;&nbsp;&nbsp;&nbsp;
<button on:click={stopPlaying}>Stop</button>&nbsp;&nbsp;&nbsp;&nbsp;
<button on:click={() => clearGrid(rows)}>Clear</button>&nbsp;&nbsp;&nbsp;&nbsp;
<button class="share">{shareMessage}</button>
<table on:click|once={() => playing=true}>
<br/>
<Controls
bind:grid={grid}
bind:config={config}
on:playpause={togglePlaying}
on:stop={stopPlaying}
on:clear={() => clearGrid(config.rows)}
on:rowchange={() => resizeGrid(config.rows)}
/>
<table on:click|once={startPlaying}>
{#each grid as row}
<Row bind:row={row} bind:playing={row.isPlaying} paused={!playing}/>
<Row bind:row={row} bind:playing={row.isPlaying} paused={!config.playing}/>
{/each}
</table>
<br/>
<label>
Speed : {speed} bpm
<br/>
<input bind:value={speed} type="range" min="60" max="500" class="slider">
</label>
<br/>
<div class="footer" align="center">
<a href="https://irshadpi.me/2020-06-15/best-of-music-grid" >Best of Music Grid</a>
<br/>
Expand Down
134 changes: 134 additions & 0 deletions src/Controls.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
<script>
import { createEventDispatcher, onMount } from 'svelte';
import ClipboardJS from 'clipboard';
const dispatch = createEventDispatcher();
export let grid;
export let config;
let urlUpdatedRecently = false;
let settingsOpen = false;
let scrollY = 0;
const encodeGridToUrl = (grid, speed) => {
let res = ''
for (var i = grid.length - 1; i >= 0; i--) {
let temp = 0, k = 1;
for (var j = grid[i].length - 1; j >= 0; j--) {
temp = temp + k * grid[i][j];
k = k * 2;
}
res += (temp + '-');
}
history.replaceState({}, '', '#' + res + '&' + speed);
}
const updateUrl = (grid, speed) => {
if(!urlUpdatedRecently) {
encodeGridToUrl(grid, speed);
urlUpdatedRecently = true;
setTimeout(() => {urlUpdatedRecently = false}, 1000);
}
}
$: updateUrl(grid, config.speed);
let clipboard = new ClipboardJS('.share', {
text: function() {
encodeGridToUrl(grid, config.speed);
return window.location.href;
}
});
let header;
let headerOffset;
let primaryClass = "primary";
onMount(() => {
headerOffset = header.offsetTop;
});
const showSticky = (ignored) => {
if(headerOffset) {
if (window.pageYOffset > headerOffset) {
primaryClass = "primary sticky";
} else {
primaryClass = "primary";
}
}
}
$: showSticky(scrollY);
</script>

<style>
.fa {
transition: 0.06s ease-in;
}
.fa:hover {
transform: scale(1.1);
}
.fa:active {
transform: scale(0.8);
}
a {
margin-left: 1.3em;
margin-right: 1.3em;
padding: 10px;
color: white;
}
.primary, .settings {
padding: 10px;
background: black;
}
.sticky {
position: fixed;
top: 0;
left: 0;
width: 100%;
}
</style>
<svelte:window bind:scrollY={scrollY}/>

<div class="container">
<div class="settings">
<label>
Rows :
<input bind:value={config.rows}
on:input={() => dispatch('rowchange')}
type="range" min="8" max="100" class="slider">
{config.rows}
</label>
<br/>
<label>
Speed :
<input bind:value={config.speed}
type="range" min="60" max="500" class="slider">
{config.speed}
</label>
</div>
<div class={primaryClass} bind:this={header}>
<a on:click={() => dispatch('playpause')}>
{#if config.playing}
<i class="fa fa-lg fa-inverse fa-pause"/>
{:else}
<i class="fa fa-lg fa-inverse fa-play"/>
{/if}
</a>
<a on:click={() => dispatch('stop')}><i class="fa fa-inverse fa-lg fa-stop"/></a>
<a class="share"><i class="fa fa-lg fa-share-alt"/></a>
<a on:click={() => dispatch('clear')}><i class="fa fa-lg fa-trash"/></a>
</div>
{#if settingsOpen}
{/if}
</div>
3 changes: 2 additions & 1 deletion src/Music.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
console.log('audio is ready');
}
export const playRow = (row) => {
export const playRow = async (row) => {
if(!synth) {
console.error("Please initialize audio before playing a row");
await initAudio();
return;
}
Expand Down

0 comments on commit 0f0cde8

Please sign in to comment.