diff --git a/package.json b/package.json index be1d1b7..5a1b6c2 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,8 @@ "description": "赵家小站", "main": "server.js", "scripts": { - "dev": "nodemon server", - "start": "PORT=8080 pm2 start server.js --name 'Zhao Server:8080' --watch", + "start": "nodemon server", + "install": "PORT=8080 pm2 start server.js --name 'Zhao Server:8080' --watch", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { diff --git a/public/js/sensehat.js b/public/js/sensehat.js new file mode 100644 index 0000000..7e97593 --- /dev/null +++ b/public/js/sensehat.js @@ -0,0 +1,36 @@ +/** + * Sense HAT 客户端 + */ + +const client = io.connect('ws://pi', { path: '/sensehat/socket.io' }) +let current_color = [255, 255, 255] + +client.on('action', ({ action, x, y, color, pixels }) => { + let leds = document.querySelectorAll('.led') + switch (action) { + case 'clear': + color = color || [0, 0, 0] + leds.forEach((led, i) => { + led.style.backgroundColor = `rgb(${String(color)})` + }) + break + case 'setPixel': + leds[y * 8 + x].style.backgroundColor = `rgb(${String(color)})` + break + case 'setPixels': + leds.forEach((led, i) => { + led.style.backgroundColor = `rgb(${String(pixels[i])})` + }) + break + default: + break + } +}) + +document.querySelectorAll('.led').forEach(led => { + led.addEventListener('click', (event) => { + const { x, y } = event.target.dataset + const color = current_color + client.emit('action', { action: 'setPixel', x, y, color }) + }) +}) diff --git a/public/sensehat/index.html b/public/sensehat/index.html deleted file mode 100644 index 0287e15..0000000 --- a/public/sensehat/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - Sense Hat - - - -

Sense HAT 交互界面

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

- - -

-

- - -

-

- - -

- - -
-
-

-

绿

-

-
-
-
-
- - - - - - diff --git a/public/sensehat/sensehat.css b/public/sensehat/sensehat.css deleted file mode 100644 index 51323d9..0000000 --- a/public/sensehat/sensehat.css +++ /dev/null @@ -1,30 +0,0 @@ -#matrix { - display: flex; - flex-direction: column; - gap: 2px; -} - -.row { - display: flex; - width: 254px; - gap: 2px; -} - -.led { - width: 30px; - height: 30px; - border: 1px solid gray; - background-color: whitesmoke; - cursor: pointer; - border-radius: 2px; -} - -.led.on { - background-color: blue; -} - -button { - width: 100px; - margin-top: 1rem; - /* flex: 1 1 auto; */ -} diff --git a/public/sensehat/sensehat.js b/public/sensehat/sensehat.js deleted file mode 100644 index 972c9c1..0000000 --- a/public/sensehat/sensehat.js +++ /dev/null @@ -1,43 +0,0 @@ -const client = io.connect('ws://pi', { path: '/sensehat/socket.io', }) - -client.on('action', ({ action, x, y, color, pixels }) => { - var leds = document.querySelectorAll('.led') - if (color == undefined || color == [0, 0, 0]) color = [255, 255, 255] - var [r, g, b] = color - if (r == 0 && g == 0 && b == 0) [r, g, b] = [255, 255, 255] - switch (action) { - case 'clear': - for (let i = 0; i < 64; i++) { - leds[i].style.backgroundColor = `rgb(${r}, ${g}, ${b})` - } - break - case 'setPixel': - leds[y * 8 + x].style.backgroundColor = `rgb(${r}, ${g}, ${b})` - break - case 'setPixels': - for (let i = 0; i < 64; i++) { - var [r, g, b] = pixels[i] - if (r == 0 && g == 0 && b == 0) [r, g, b] = [255, 255, 255] - leds[i].style.backgroundColor = `rgb(${r}, ${g}, ${b})` - } - break - default: - break - } -}) - -function setPixel(led) { - const { x, y } = led.dataset - const r = Number(red.value) - const g = Number(green.value) - const b = Number(blue.value) - client.emit('action', { action: 'setPixel', x, y, color: [r, g, b] }) -} - -red.onchange = change_color -green.onchange = change_color -blue.onchange = change_color -function change_color() { - selected_color.style.backgroundColor = `rgb(${red.value},${green.value},${blue.value})` -} -change_color() diff --git a/routers/home.js b/routers/home.js index 4685340..97aa40d 100644 --- a/routers/home.js +++ b/routers/home.js @@ -1,4 +1,5 @@ const router = require('express').Router() router.get('/', (req, res) => res.render('home')) router.get('/poems', (req, res) => res.render('poems')) +router.get('/sensehat', (req, res) => res.render('sensehat')) module.exports = router diff --git a/server.js b/server.js index 3403315..b46c15c 100644 --- a/server.js +++ b/server.js @@ -16,7 +16,7 @@ const server = app.listen(PORT, () => console.log(`zhao server running at port $ const moment = require('moment') moment.locale('zh-cn') -const filesize = require('filesize').partial({base: 2, standard: "jedec"}) +const filesize = require('filesize').partial({ base: 2, standard: "jedec" }) app.locals.moment = moment app.locals.filesize = filesize diff --git a/views/layout.pug b/views/layout.pug index 15eb881..fe0ee24 100644 --- a/views/layout.pug +++ b/views/layout.pug @@ -6,8 +6,7 @@ html(lang='zh') meta(name='viewport', content='width=device-width, initial-scale=1.0') link(rel='stylesheet', href='/css/bootstrap.min.css') link(rel='stylesheet', href='/css/zhao.css') - script(src='/socket.io/socket.io.min.js', defer) - script(src='/js/bootstrap.bundle.min.js', defer) + block styles title 赵家小站 body nav.navbar.navbar-expand-sm.navbar-light.bg-light @@ -22,5 +21,5 @@ html(lang='zh') include nav.pug .container-md.py-3 block main - + script(src='/js/bootstrap.bundle.min.js', defer) block scripts diff --git a/views/nav.pug b/views/nav.pug index fb06a38..b35f0b2 100644 --- a/views/nav.pug +++ b/views/nav.pug @@ -1,7 +1,7 @@ li.nav-item a.nav-link(href='/poems') 背诗词 li.nav-item - a.nav-link(href='/sensehat/', target='_blank') SenseHAT + a.nav-link(href='/sensehat') SenseHAT li.nav-item li.nav-item.dropdown a.nav-link.dropdown-toggle(data-bs-toggle='dropdown', href='#', role='button', aria-haspopup='true', aria-expanded='false') 数学 diff --git a/views/sensehat.pug b/views/sensehat.pug index fe176b2..d036647 100644 --- a/views/sensehat.pug +++ b/views/sensehat.pug @@ -1,5 +1,117 @@ -extends layout +extends layout.pug + +block styles + style. + .led-matrix { + max-width: 384px; + min-width: 240px; + } + + .led-row {} + + .led { + margin: 1px; + aspect-ratio: 1; + cursor: pointer; + border-radius: 4px; + border: 1px solid gray; + background-color: #ddd; + } block main .container - h1 SenseHAT + h1.h6.text-muted Sense HAT 交互界面 + .container-fluid.bg-success + .led-matrix.w-auto.mx-auto.p-3 + .led-row.row + .led.col(data-y='0' data-x='0') + .led.col(data-y='0' data-x='1') + .led.col(data-y='0' data-x='2') + .led.col(data-y='0' data-x='3') + .led.col(data-y='0' data-x='4') + .led.col(data-y='0' data-x='5') + .led.col(data-y='0' data-x='6') + .led.col(data-y='0' data-x='7') + .led-row.row + .led.col(data-y='1' data-x='0') + .led.col(data-y='1' data-x='1') + .led.col(data-y='1' data-x='2') + .led.col(data-y='1' data-x='3') + .led.col(data-y='1' data-x='4') + .led.col(data-y='1' data-x='5') + .led.col(data-y='1' data-x='6') + .led.col(data-y='1' data-x='7') + .led-row.row + .led.col(data-y='2' data-x='0') + .led.col(data-y='2' data-x='1') + .led.col(data-y='2' data-x='2') + .led.col(data-y='2' data-x='3') + .led.col(data-y='2' data-x='4') + .led.col(data-y='2' data-x='5') + .led.col(data-y='2' data-x='6') + .led.col(data-y='2' data-x='7') + .led-row.row + .led.col(data-y='3' data-x='0') + .led.col(data-y='3' data-x='1') + .led.col(data-y='3' data-x='2') + .led.col(data-y='3' data-x='3') + .led.col(data-y='3' data-x='4') + .led.col(data-y='3' data-x='5') + .led.col(data-y='3' data-x='6') + .led.col(data-y='3' data-x='7') + .led-row.row + .led.col(data-y='4' data-x='0') + .led.col(data-y='4' data-x='1') + .led.col(data-y='4' data-x='2') + .led.col(data-y='4' data-x='3') + .led.col(data-y='4' data-x='4') + .led.col(data-y='4' data-x='5') + .led.col(data-y='4' data-x='6') + .led.col(data-y='4' data-x='7') + .led-row.row + .led.col(data-y='5' data-x='0') + .led.col(data-y='5' data-x='1') + .led.col(data-y='5' data-x='2') + .led.col(data-y='5' data-x='3') + .led.col(data-y='5' data-x='4') + .led.col(data-y='5' data-x='5') + .led.col(data-y='5' data-x='6') + .led.col(data-y='5' data-x='7') + .led-row.row + .led.col(data-y='6' data-x='0') + .led.col(data-y='6' data-x='1') + .led.col(data-y='6' data-x='2') + .led.col(data-y='6' data-x='3') + .led.col(data-y='6' data-x='4') + .led.col(data-y='6' data-x='5') + .led.col(data-y='6' data-x='6') + .led.col(data-y='6' data-x='7') + .led-row.row + .led.col(data-y='7' data-x='0') + .led.col(data-y='7' data-x='1') + .led.col(data-y='7' data-x='2') + .led.col(data-y='7' data-x='3') + .led.col(data-y='7' data-x='4') + .led.col(data-y='7' data-x='5') + .led.col(data-y='7' data-x='6') + .led.col(data-y='7' data-x='7') + .container-fluid.p-3.bg-light + .row.gap-1.my-3 + button.col.btn.btn-primary(onclick="client.emit('action', {action:'clear'});") 清空 + button.col.btn.btn-primary(onclick="client.emit('action', {action:'flash', color:current_color});") 闪光 + button.col.btn.btn-primary(onclick="client.emit('action', {action:'loadImage', image:'heart'});") 空心 + button.col.btn.btn-primary(onclick="client.emit('action', {action:'loadImage', image:'heart_full'});") 红心 + button.col.btn.btn-primary(onclick="client.emit('action', {action:'flipH'});") 左右镜像 + button.col.btn.btn-primary(onclick="client.emit('action', {action:'flipV'});") 上下镜像 + button.col.btn.btn-primary(onclick="client.emit('action', {action:'showMessage', text:'Hello'})") Hello + .row.gap-1.my-3 + button.col.btn.btn-dark(onclick="current_color=[0,0,0];") 黑 + button.col.btn.btn-white(onclick="current_color=[255,255,255];") 白 + button.col.btn.btn-danger(onclick="current_color=[255,0,0];") 红 + button.col.btn.btn-success(onclick="current_color=[0,255,0];") 绿 + button.col.btn.btn-primary(onclick="current_color=[0,0,255];") 蓝 + button.col.btn.btn-warning(onclick="current_color=[255,255,0];") 黄 + +block scripts + script(src="http://pi/sensehat/socket.io/socket.io.js") + script(src="/js/sensehat.js")