ソースを参照

Improve styling, refactor code

Separate styles from template, use png images for better look and feel.
master
コミット
dfcd74ccbc
9個のファイルの変更1059行の追加165行の削除
  1. バイナリ
      accidental.png
  2. +3
    -0
      electron-builder.yml
  3. +3
    -149
      index.html
  4. +11
    -4
      index.js
  5. バイナリ
      natural.png
  6. +4
    -2
      package.json
  7. +112
    -0
      script.js
  8. +83
    -0
      style.css
  9. +843
    -10
      yarn.lock

バイナリ
accidental.png ファイルの表示

変更前 変更後
幅: 12  |  高さ: 41  |  サイズ: 746 B

+ 3
- 0
electron-builder.yml ファイルの表示

@@ -0,0 +1,3 @@
appId: 'sh.modal.apps.pianomidimonitor'
productName: 'Piano MIDI Monitor'
copyright: 'Copyright © 2020 TheoryOfNekomata'

pages/piano.html → index.html ファイルの表示

@@ -7,59 +7,12 @@
http-equiv="Content-Security-Policy"
content="script-src 'self' 'unsafe-inline';"
/>
<style>
html {
height: 100%;
width: 100%;
}

body {
margin: 0;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 100%;
}

svg {
fill: currentColor;
}

.natural {
background-color: #eee;
border: 1px solid;
height: 100%;
box-sizing: border-box;
background-image: url('./piano/natural.png');
}

.accidental {
background-color: #222;
border: 1px solid;
height: 65%;
box-sizing: border-box;
background-image: url('./piano/accidental.png');
}

#pedals {
display: flex;
justify-content: space-between;
align-items: center;
width: 0;
flex: auto;
padding: 0 1rem;
box-sizing: border-box;
background-color: black;
color: white;
height: 100%;
}
</style>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div
id="keyboard"
style="width: 944px; height: 100%; position: relative;"
style="width: 1008px; height: 100%; position: relative;"
></div>
<div id="pedals">
<svg
@@ -126,105 +79,6 @@
</svg>
</div>

<script>
const X_OFFSET = 0
const NATURAL_KEY_WIDTH = 15;
const ACCIDENTAL_KEY_WIDTH = 9;
const accidental_key_x_offsets = [
10.0 / 112.0,
28.0 / 112.0,
57.0 / 112.0,
75.0 / 112.0,
93.0 / 112.0,
]

const { ipcRenderer, } = require('electron')

const renderKeys = () => {
let midi_note = 12
let element
const keyboard = window.document.getElementById('keyboard')
for (let octave = 0; octave < 9; octave += 1) {
for (let natural_key = 0; natural_key < 7; natural_key += 1) {
element = window.document.createElement('div')
element.setAttribute('id', 'n' + midi_note)
element.classList.add('natural')
element.style.position = 'absolute'
element.style.top = 0
element.style.left = X_OFFSET + (octave * NATURAL_KEY_WIDTH * 7) + (natural_key * NATURAL_KEY_WIDTH - 1) +
'px'
element.style.width = NATURAL_KEY_WIDTH + 1 + 'px'
keyboard.appendChild(element)

switch (natural_key) {
case 0:
case 1:
case 3:
case 4:
case 5:
midi_note += 2;
break;
case 2:
case 6:
midi_note += 1;
break;
default:
break;
}
}

midi_note -= 11;

for (let accidental_key = 0; accidental_key < 5; accidental_key += 1) {
element = window.document.createElement('div')
element.classList.add('accidental')
element.setAttribute('id', 'n' + midi_note)
element.style.position = 'absolute'
element.style.top = 0
element.style.left = X_OFFSET + (octave * NATURAL_KEY_WIDTH * 7) + (NATURAL_KEY_WIDTH * 7 *
accidental_key_x_offsets[accidental_key]) + 'px'
element.style.width = ACCIDENTAL_KEY_WIDTH + 'px'
keyboard.appendChild(element)

switch (accidental_key) {
case 0:
case 2:
case 3:
midi_note += 2;
break;
case 1:
case 4:
midi_note += 3;
break;
default:
break;
}
}

midi_note -= 1;
}
}

ipcRenderer.on('note', (event, message) => {
const [key, value, ] = message.split(':')
window.document.getElementById('n' + key).style.backgroundColor = value > 0 ? 'red' : null
})

renderKeys(null, null)

ipcRenderer.on('pedal', (event, message) => {
console.log(message)
const [which, value, ] = message.split(':')
const pedalIds = {
64: 'sustain',
66: 'sostenuto',
67: 'unacorda',
}

console.log(window.document.getElementById(pedalIds[which]))

window.document.getElementById(pedalIds[which]).style.opacity = value / 127 * 0.75 + 0.25
})
</script>
<script src="./script.js"></script>
</body>
</html>

+ 11
- 4
index.js ファイルの表示

@@ -1,19 +1,26 @@
const { app, BrowserWindow } = require('electron')
const midi = require('midi')

const SCREEN_HEIGHT = 96
const SCREEN_WIDTH = 1152
const SCREEN_HEIGHT = 64
const SCREEN_WIDTH = 1200

const createWindow = () => {
const win = new BrowserWindow({
width: SCREEN_WIDTH,
height: SCREEN_HEIGHT,
useContentSize: true,
backgroundColor: '#000000',
resizable: false,
minimizable: false,
maximizable: false,
fullscreenable: false,
webPreferences: {
nodeIntegration: true
//devTools: false,
nodeIntegration: true,
}
})

win.loadFile('pages/piano.html')
win.loadFile('index.html')

const input = new midi.Input()



バイナリ
natural.png ファイルの表示

変更前 変更後
幅: 16  |  高さ: 64  |  サイズ: 743 B

+ 4
- 2
package.json ファイルの表示

@@ -7,11 +7,13 @@
"license": "MIT",
"private": true,
"scripts": {
"start": "electron ."
"start": "electron .",
"pack": "electron-builder --dir",
"build": "electron-builder"
},
"devDependencies": {
"electron": "^9.1.2",
"electron-rebuild": "^1.11.0"
"electron-builder": "^22.8.0"
},
"dependencies": {
"midi": "^1.0.0"


+ 112
- 0
script.js ファイルの表示

@@ -0,0 +1,112 @@
((window, electron) => {
const X_OFFSET = 0
const NATURAL_KEY_WIDTH = 16;
const ACCIDENTAL_KEY_WIDTH = 11;
const accidental_key_x_offsets = [
10.0 / 112.0,
28.0 / 112.0,
57.0 / 112.0,
75.0 / 112.0,
93.0 / 112.0,
]

const { ipcRenderer, } = electron


const renderKeys = () => {
let midi_note = 12
const elements = {}
let element
const keyboard = window.document.getElementById('keyboard')
for (let octave = 0; octave < 9; octave += 1) {
for (let natural_key = 0; natural_key < 7; natural_key += 1) {
element = window.document.createElement('div')
element.classList.add('natural')
element.classList.add('key')
element.style.position = 'absolute'
element.style.top = 0
element.style.left = X_OFFSET + (octave * NATURAL_KEY_WIDTH * 7) + (natural_key * NATURAL_KEY_WIDTH) +
'px'
element.style.width = NATURAL_KEY_WIDTH + 'px'
element.appendChild(window.document.createElement('div'))
elements[midi_note] = element
keyboard.appendChild(element)

switch (natural_key) {
case 0:
case 1:
case 3:
case 4:
case 5:
midi_note += 2;
break;
case 2:
case 6:
midi_note += 1;
break;
default:
break;
}
}

midi_note -= 11;

for (let accidental_key = 0; accidental_key < 5; accidental_key += 1) {
element = window.document.createElement('div')
element.classList.add('accidental')
element.classList.add('key')
element.style.position = 'absolute'
element.style.top = 0
element.style.left = X_OFFSET + (octave * NATURAL_KEY_WIDTH * 7) + (NATURAL_KEY_WIDTH * 7 *
accidental_key_x_offsets[accidental_key]) + 'px'
element.style.width = ACCIDENTAL_KEY_WIDTH + 'px'
element.appendChild(window.document.createElement('div'))
elements[midi_note] = element
keyboard.appendChild(element)

switch (accidental_key) {
case 0:
case 2:
case 3:
midi_note += 2;
break;
case 1:
case 4:
midi_note += 3;
break;
default:
break;
}
}

midi_note -= 1;
}

return elements
}

const elements = renderKeys(null, null)

ipcRenderer.on('note', (event, message) => {
const [key, value, ] = message.split(':')
if (value > 0) {
elements[key].classList.add('pressed')
} else {
elements[key].classList.remove('pressed')
}
})

ipcRenderer.on('pedal', (event, message) => {
console.log(message)
const [which, value, ] = message.split(':')
const pedalIds = {
64: 'sustain',
66: 'sostenuto',
67: 'unacorda',
}

console.log(window.document.getElementById(pedalIds[which]))

window.document.getElementById(pedalIds[which]).style.opacity = value / 127 * 0.75 + 0.25
})
})(window, require('electron'))

+ 83
- 0
style.css ファイルの表示

@@ -0,0 +1,83 @@
html {
height: 100%;
width: 100%;
}

body {
margin: 0;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 100%;
}

svg {
fill: currentColor;
}

.natural {
height: 100%;
box-sizing: border-box;
background-image: url('./natural.png');
background-color: black;
z-index: 0;
}

.accidental {
height: calc(41 / 64 * 100%);
box-sizing: border-box;
background-image: url('./accidental.png');
z-index: 2;
}

.key > * {
width: 100%;
height: 100%;
opacity: 0;
background-color: lime;
border-radius: 0 0 1px 1px;
background-clip: content-box;
box-sizing: border-box;

}

.natural.key > * {
padding: 2px 0 0 1px;
mix-blend-mode: multiply;
}

.accidental.key > * {
padding: 2px 0 1px 1px;
mix-blend-mode: hard-light;
}

.natural.key.pressed {
z-index: 1;
}

.accidental.key.pressed {
z-index: 3;
}

.natural.key.pressed > * {
opacity: 0.85;
}

.accidental.key.pressed > * {
opacity: 0.5;
}

#pedals {
display: flex;
justify-content: space-between;

align-items: center;
width: 0;
flex: auto;
padding: 0 1rem;
box-sizing: border-box;
background-color: black;
color: white;
height: 100%;
}

+ 843
- 10
yarn.lock
ファイル差分が大きすぎるため省略します
ファイルの表示


読み込み中…
キャンセル
保存