Compare commits
61
Commits
148b240bb7
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0352efbc34 | ||
|
|
911049a2fe | ||
|
|
60bb918f54 | ||
|
|
0f16a93a7e | ||
|
|
8cde0ef01e | ||
|
|
62cac7c459 | ||
|
|
be551e8844 | ||
|
|
d56266d1f3 | ||
|
|
c74daf7337 | ||
|
|
a9808ba9d4 | ||
|
|
303c76cbd6 | ||
|
|
8c1e56c3f9 | ||
|
|
82ce27c10d | ||
|
|
10e8782798 | ||
|
|
fe24e5aa23 | ||
|
|
702e428ee5 | ||
|
|
f236665829 | ||
|
|
21f18d1b2a | ||
|
|
daa0505504 | ||
|
|
69b45e386f | ||
|
|
8accaf4ab2 | ||
|
|
cf8c4b0e47 | ||
|
|
710cd0506d | ||
|
|
7a7c04dbe4 | ||
|
|
1e04b86236 | ||
|
|
6a8463fab5 | ||
|
|
9cf7c74f9c | ||
|
|
825acfe48b | ||
|
|
cadb42d693 | ||
|
|
024338d4dc | ||
|
|
a33466d6d9 | ||
|
|
ebc97c8930 | ||
|
|
0e8efa0902 | ||
|
|
4eadf7dc7e | ||
|
|
9033c8ad20 | ||
|
|
ac89ce77e6 | ||
|
|
2b54c71eae | ||
|
|
e957de4d86 | ||
|
|
61f68ca41f | ||
|
|
bdd82be393 | ||
|
|
a9c1f21fe3 | ||
|
|
98f3a4a02f | ||
|
|
80002351ad | ||
|
|
533cd1052e | ||
|
|
3b7b46f25b | ||
|
|
0252347f65 | ||
|
|
c3bf6811ea | ||
|
|
b2f9e5abb5 | ||
|
|
1088699977 | ||
|
|
44ec586c1e | ||
|
|
82f4868f78 | ||
|
|
41717509f8 | ||
|
|
f3c09a00ad | ||
|
|
cafeed83b5 | ||
|
|
0a3a79aca9 | ||
|
|
f969bf638c | ||
|
|
9250353c1c | ||
|
|
c63d1cc49e | ||
|
|
d4300b6963 | ||
|
|
897b244d16 | ||
|
|
838201bb58 |
@@ -1,14 +0,0 @@
|
|||||||
const socket = io();
|
|
||||||
|
|
||||||
var myAudio = document.createElement('audio');
|
|
||||||
myAudio.setAttribute('src','muddy_files.mp3');
|
|
||||||
|
|
||||||
socket.on('speed', (speed) => {
|
|
||||||
console.log('recieved speed', speed);
|
|
||||||
|
|
||||||
myAudio.playbackRate = speed;
|
|
||||||
});
|
|
||||||
|
|
||||||
myAudio.playbackRate = 0.1;
|
|
||||||
|
|
||||||
myAudio.play();
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="fr">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>LOOP</title>
|
|
||||||
<base href="./">
|
|
||||||
<script src="https://kit.fontawesome.com/96dcb489df.js" crossorigin="anonymous"></script>
|
|
||||||
<link rel="stylesheet" href="styles.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<header>
|
|
||||||
<a href="file:///C:/Users/elyko/Desktop/loop/index.html"><img src="images/logo.png" class="logo"></a>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<h1>Let your favorite songs play on LOOP.</h1>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="login-container">
|
|
||||||
<input type="text" placeholder="Username" required>
|
|
||||||
<input type="password" placeholder="Password" required>
|
|
||||||
<button>Log In</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>Don't have an account ?<a href="" class="orange"> Sign up now.</a> </span></h2>
|
|
||||||
|
|
||||||
<script src="script.js"></script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
console.log( 'hello')
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
body{
|
|
||||||
background-color: red;
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.4 MiB |
@@ -0,0 +1,54 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||||
|
<title>To Hide Is To Be Seen</title>
|
||||||
|
<link rel="stylesheet" href="stylesrom.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<header class="page-header">
|
||||||
|
<a href="front.html" class="logo-container">
|
||||||
|
<img src="logo.png" alt="Logo" class="logo" />
|
||||||
|
</a>
|
||||||
|
<h1 class="title">To Hide Is To Be Seen</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
|
||||||
|
<main class="vinyl-container">
|
||||||
|
|
||||||
|
<div class="vinyl" id="vinyl">
|
||||||
|
<img src="C9EED782-8F3C-40E5-87C0-5E2032ADAB72.jpeg" alt="Pochette" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="title-under">
|
||||||
|
<span class="song-title">To Hide Is To Be Seen</span><br>
|
||||||
|
<span class="artist-name">Roman</span>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="progress-container">
|
||||||
|
<input type="range" id="progress" value="0" />
|
||||||
|
|
||||||
|
<div class="time-wrapper">
|
||||||
|
<div id="currentTime" class="time">0:00</div>
|
||||||
|
<div id="duration" class="time">1:36</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="buttons-container">
|
||||||
|
<button id="backward">- 10s</button>
|
||||||
|
<button id="loop">LOOP</button>
|
||||||
|
<button id="forward">10s +</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<audio id="audio"
|
||||||
|
src="song_to_song_v4.mp3"
|
||||||
|
data-reverse-src="song_to_song_v4_reverse.mp3"></audio>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script src="socket.io.min.js"></script>
|
||||||
|
<script src="script.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 110 KiB |
@@ -0,0 +1,59 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||||
|
<title>LOOP</title>
|
||||||
|
<base href="./">
|
||||||
|
<script src="https://kit.fontawesome.com/96dcb489df.js" crossorigin="anonymous"></script>
|
||||||
|
<link rel="stylesheet" href="stylesfront.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<a href="main.html"><img src="logo.png" class="logo"></a>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="music-list">
|
||||||
|
|
||||||
|
<a href="muddy_files.html" class="music-card">
|
||||||
|
<img src="Cover.png" alt="muddyfiles">
|
||||||
|
<div class="music-info">
|
||||||
|
<h3>Muddy Files</h3>
|
||||||
|
<p>Ely</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="hell_even.html" class="music-card">
|
||||||
|
<img src="hell even 5.png" alt="helleven">
|
||||||
|
<div class="music-info">
|
||||||
|
<h3>Hell Even</h3>
|
||||||
|
<p>Ely feat. JENNY</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="stamina.html" class="music-card">
|
||||||
|
<img src="WhatsApp Image 2025-04-21 at 15.01.32.jpeg" alt="stamina">
|
||||||
|
<div class="music-info">
|
||||||
|
<h3>Stamina</h3>
|
||||||
|
<p>Corb Nurk</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="Roman.html" class="music-card">
|
||||||
|
<img src="C9EED782-8F3C-40E5-87C0-5E2032ADAB72.jpeg" alt="ToHideIsToBeSeen">
|
||||||
|
<div class="music-info">
|
||||||
|
<h3>To Hide Is To Be Seen</h3>
|
||||||
|
<p>Roman</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- Ajoute autant de titres que nécessaire -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="socket.io.min.js"></script>
|
||||||
|
<script src="script.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
const socket = io();
|
||||||
|
|
||||||
|
let last_position = null;
|
||||||
|
let speed = 1;
|
||||||
|
|
||||||
|
var myAudio = document.createElement('audio');
|
||||||
|
myAudio.setAttribute('src','muddy_files.mp3');
|
||||||
|
|
||||||
|
// socket.on('speed', (speed) => {
|
||||||
|
// console.log('recieved speed', speed);
|
||||||
|
|
||||||
|
// myAudio.playbackRate = speed;
|
||||||
|
// });
|
||||||
|
|
||||||
|
socket.on('position', (position) => {
|
||||||
|
console.log('recieved position', position);
|
||||||
|
// if(!last_position){
|
||||||
|
// last_position = position;
|
||||||
|
// }else{
|
||||||
|
// speed += position > last_position ? 0.1 : -0.1;
|
||||||
|
// }
|
||||||
|
// myAudio.playbackRate = speed;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
myAudio.playbackRate = speed;
|
||||||
|
|
||||||
|
myAudio.play();
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
@@ -0,0 +1,54 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||||
|
<title>Hell Even</title>
|
||||||
|
<link rel="stylesheet" href="styleshe.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<header class="page-header">
|
||||||
|
<a href="front.html" class="logo-container">
|
||||||
|
<img src="logo.png" alt="Logo" class="logo" />
|
||||||
|
</a>
|
||||||
|
<h1 class="title">Hell Even</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
|
||||||
|
<main class="vinyl-container">
|
||||||
|
|
||||||
|
<div class="vinyl" id="vinyl">
|
||||||
|
<img src="hell even 5.png" alt="Pochette" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="title-under">
|
||||||
|
<span class="song-title">Hell Even</span><br>
|
||||||
|
<span class="artist-name">Ely feat. JENNY</span>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="progress-container">
|
||||||
|
<input type="range" id="progress" value="0" />
|
||||||
|
|
||||||
|
<div class="time-wrapper">
|
||||||
|
<div id="currentTime" class="time">0:00</div>
|
||||||
|
<div id="duration" class="time">3:28</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="buttons-container">
|
||||||
|
<button id="backward">- 10s</button>
|
||||||
|
<button id="loop">LOOP</button>
|
||||||
|
<button id="forward">10s +</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<audio id="audio"
|
||||||
|
src="paradisev2.mp3"
|
||||||
|
data-reverse-src="paradisev2_reverse.mp3"></audio>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script src="socket.io.min.js"></script>
|
||||||
|
<script src="script.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
const audio = document.getElementById('audio');
|
||||||
|
const playPauseBtn = document.getElementById('play-pause');
|
||||||
|
const progress = document.getElementById('progress');
|
||||||
|
const time = document.getElementById('time');
|
||||||
|
const vinyl = document.querySelector('.vinyl');
|
||||||
|
|
||||||
|
let isPlaying = false;
|
||||||
|
|
||||||
|
// Play / Pause button
|
||||||
|
playPauseBtn.addEventListener('click', () => {
|
||||||
|
if (isPlaying) {
|
||||||
|
audio.pause();
|
||||||
|
vinyl.style.animationPlayState = 'paused';
|
||||||
|
playPauseBtn.textContent = '▶️';
|
||||||
|
} else {
|
||||||
|
audio.play();
|
||||||
|
vinyl.style.animationPlayState = 'running';
|
||||||
|
playPauseBtn.textContent = '⏸️';
|
||||||
|
}
|
||||||
|
isPlaying = !isPlaying;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update progress and time
|
||||||
|
audio.addEventListener('timeupdate', () => {
|
||||||
|
progress.value = audio.currentTime;
|
||||||
|
updateTimeDisplay();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set duration when audio loads
|
||||||
|
audio.addEventListener('loadedmetadata', () => {
|
||||||
|
progress.max = audio.duration;
|
||||||
|
updateTimeDisplay();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Seek audio
|
||||||
|
progress.addEventListener('input', () => {
|
||||||
|
audio.currentTime = progress.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateTimeDisplay() {
|
||||||
|
const format = (s) => {
|
||||||
|
const m = Math.floor(s / 60);
|
||||||
|
const ss = Math.floor(s % 60);
|
||||||
|
return `${m}:${ss < 10 ? '0' + ss : ss}`;
|
||||||
|
};
|
||||||
|
time.textContent = `${format(audio.currentTime)} / ${format(audio.duration)}`;
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
@@ -0,0 +1,35 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||||
|
<title>LOOP</title>
|
||||||
|
<base href="./">
|
||||||
|
<script src="https://kit.fontawesome.com/96dcb489df.js" crossorigin="anonymous"></script>
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="header-container">
|
||||||
|
<a href="main.html"><img src="logo.png" class="logo"></a>
|
||||||
|
<h1>Let your favorite songs play on LOOP.</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="login-container">
|
||||||
|
<h3 class="login-title">Login Account</h3>
|
||||||
|
<input type="text" id="username" placeholder="Username" required>
|
||||||
|
<input type="password" id="password" placeholder="Password" required>
|
||||||
|
<button id="loginBtn" class="button">Log In</button>
|
||||||
|
<p id="error-message" class="error-message"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Don't have an account ?<a href="" class="orange"> Sign up now.</a> </span></h2>
|
||||||
|
|
||||||
|
<script src="main.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
document.getElementById('loginBtn').addEventListener('click', function(event) {
|
||||||
|
event.preventDefault(); // Empêche le bouton de recharger ou changer de page
|
||||||
|
|
||||||
|
const username = document.getElementById('username').value.trim();
|
||||||
|
const password = document.getElementById('password').value.trim();
|
||||||
|
const errorMessage = document.getElementById('error-message');
|
||||||
|
|
||||||
|
// Identifiants valides en dur (à modifier selon ton besoin)
|
||||||
|
const validUsername = "ELY";
|
||||||
|
const validPassword = "Bilan6";
|
||||||
|
|
||||||
|
if (username === validUsername && password === validPassword) {
|
||||||
|
window.location.href = "front.html"; // Redirige vers la page suivante
|
||||||
|
} else {
|
||||||
|
errorMessage.textContent = "Incorrect username or password.";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||||
|
<title>Muddy Files</title>
|
||||||
|
<link rel="stylesheet" href="stylesmf.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<header class="page-header">
|
||||||
|
<a href="front.html" class="logo-container">
|
||||||
|
<img src="logo.png" alt="Logo" class="logo" />
|
||||||
|
</a>
|
||||||
|
<h1 class="title">Muddy Files</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
|
||||||
|
<main class="vinyl-container">
|
||||||
|
|
||||||
|
<div class="vinyl" id="vinyl">
|
||||||
|
<img src="Cover.png" alt="Pochette" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="title-under">
|
||||||
|
<span class="song-title">Muddy Files</span><br>
|
||||||
|
<span class="artist-name">Ely</span>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="progress-container">
|
||||||
|
<input type="range" id="progress" value="0" max="100" />
|
||||||
|
|
||||||
|
<div class="time-wrapper">
|
||||||
|
<div id="currentTime" class="time">0:00</div>
|
||||||
|
<div id="duration" class="time">1:36</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="buttons-container">
|
||||||
|
<button id="backward">- 10s</button>
|
||||||
|
<button id="loop">LOOP</button>
|
||||||
|
<button id="forward">10s +</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<audio id="audio"
|
||||||
|
src="muddy_files.mp3"
|
||||||
|
data-reverse-src="muddy_files_reverse.mp3"></audio>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="socket.io.min.js"></script>
|
||||||
|
<script src="script.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
const audio = document.getElementById('audio');
|
||||||
|
const playPauseBtn = document.getElementById('play-pause');
|
||||||
|
const progress = document.getElementById('progress');
|
||||||
|
const time = document.getElementById('time');
|
||||||
|
const vinyl = document.querySelector('.vinyl');
|
||||||
|
|
||||||
|
let isPlaying = false;
|
||||||
|
|
||||||
|
// Play / Pause button
|
||||||
|
playPauseBtn.addEventListener('click', () => {
|
||||||
|
if (isPlaying) {
|
||||||
|
audio.pause();
|
||||||
|
vinyl.style.animationPlayState = 'paused';
|
||||||
|
playPauseBtn.textContent = '▶️';
|
||||||
|
} else {
|
||||||
|
audio.play();
|
||||||
|
vinyl.style.animationPlayState = 'running';
|
||||||
|
playPauseBtn.textContent = '⏸️';
|
||||||
|
}
|
||||||
|
isPlaying = !isPlaying;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update progress and time
|
||||||
|
audio.addEventListener('timeupdate', () => {
|
||||||
|
progress.value = audio.currentTime;
|
||||||
|
updateTimeDisplay();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set duration when audio loads
|
||||||
|
audio.addEventListener('loadedmetadata', () => {
|
||||||
|
progress.max = audio.duration;
|
||||||
|
updateTimeDisplay();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Seek audio
|
||||||
|
progress.addEventListener('input', () => {
|
||||||
|
audio.currentTime = progress.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateTimeDisplay() {
|
||||||
|
const format = (s) => {
|
||||||
|
const m = Math.floor(s / 60);
|
||||||
|
const ss = Math.floor(s % 60);
|
||||||
|
return `${m}:${ss < 10 ? '0' + ss : ss}`;
|
||||||
|
};
|
||||||
|
time.textContent = `${format(audio.currentTime)} / ${format(audio.duration)}`;
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,151 @@
|
|||||||
|
// 1. Sélection des éléments DOM
|
||||||
|
const vinyl = document.getElementById('vinyl');
|
||||||
|
const audio = document.getElementById('audio');
|
||||||
|
const progress = document.getElementById('progress');
|
||||||
|
const currentTimeEl = document.getElementById('currentTime');
|
||||||
|
const durationEl = document.getElementById('duration');
|
||||||
|
const backwardBtn = document.getElementById('backward');
|
||||||
|
const forwardBtn = document.getElementById('forward');
|
||||||
|
const loopBtn = document.getElementById('loop');
|
||||||
|
|
||||||
|
// 2. Variables utiles
|
||||||
|
let isPlaying = false;
|
||||||
|
let isLooping = false;
|
||||||
|
let idleTimeout = null;
|
||||||
|
let lastPosition = null;
|
||||||
|
let lastTime = null;
|
||||||
|
|
||||||
|
const rotationsPerTrack = 3; // tours complets du vinyle sur toute la durée
|
||||||
|
let currentRotation = 0; // rotation en degrés actuelle du vinyle
|
||||||
|
|
||||||
|
// 3. Connexion Socket.io
|
||||||
|
const socket = io();
|
||||||
|
|
||||||
|
socket.on('position', (position) => {
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
if (lastPosition !== null && lastTime !== null) {
|
||||||
|
const deltaPos = position - lastPosition;
|
||||||
|
const deltaTime = (now - lastTime) / 1000;
|
||||||
|
|
||||||
|
const speed = deltaPos / deltaTime; // vitesse de rotation
|
||||||
|
|
||||||
|
clearTimeout(idleTimeout);
|
||||||
|
|
||||||
|
// Seuil de mouvement pour arrêt
|
||||||
|
if (Math.abs(speed) < 1) {
|
||||||
|
stopPlayback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (speed < 0) {
|
||||||
|
// Rotation inverse : on recule la timeline
|
||||||
|
audio.pause();
|
||||||
|
isPlaying = false;
|
||||||
|
// recule proportionnellement à la vitesse (sensibilité ajustable)
|
||||||
|
audio.currentTime = Math.max(0, audio.currentTime + speed * 0.0025);
|
||||||
|
} else {
|
||||||
|
// Rotation avant : jouer la piste et ajuster vitesse
|
||||||
|
if (!isPlaying) {
|
||||||
|
audio.play();
|
||||||
|
isPlaying = true;
|
||||||
|
}
|
||||||
|
// SENSIBILITÉ : le facteur diviseur est plus grand → plus doux
|
||||||
|
let playbackSpeed = 0.5 + speed / 600;
|
||||||
|
playbackSpeed = Math.min(Math.max(playbackSpeed, 0.5), 1.1); // plage limitée à x1 max
|
||||||
|
audio.playbackRate = playbackSpeed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPosition = position;
|
||||||
|
lastTime = now;
|
||||||
|
|
||||||
|
// Détection d'inactivité
|
||||||
|
idleTimeout = setTimeout(() => {
|
||||||
|
stopPlayback();
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 4. Fonctions
|
||||||
|
|
||||||
|
function togglePlay() {
|
||||||
|
if (isPlaying) {
|
||||||
|
audio.pause();
|
||||||
|
} else {
|
||||||
|
audio.play();
|
||||||
|
}
|
||||||
|
isPlaying = !isPlaying;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateProgress() {
|
||||||
|
if (!isNaN(audio.duration)) {
|
||||||
|
const progressPercent = (audio.currentTime / audio.duration) * 100;
|
||||||
|
progress.value = progressPercent;
|
||||||
|
currentTimeEl.textContent = formatTime(audio.currentTime);
|
||||||
|
durationEl.textContent = formatTime(audio.duration);
|
||||||
|
|
||||||
|
updateVinylRotation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatTime(time) {
|
||||||
|
const minutes = Math.floor(time / 60);
|
||||||
|
const seconds = Math.floor(time % 60);
|
||||||
|
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setProgress(e) {
|
||||||
|
const width = progress.clientWidth;
|
||||||
|
const clickX = e.offsetX;
|
||||||
|
const duration = audio.duration;
|
||||||
|
audio.currentTime = (clickX / width) * duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopPlayback() {
|
||||||
|
audio.pause();
|
||||||
|
isPlaying = false;
|
||||||
|
audio.playbackRate = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// La rotation est synchronisée avec la timeline audio
|
||||||
|
function updateVinylRotation() {
|
||||||
|
if (audio.duration && audio.currentTime >= 0) {
|
||||||
|
// Rotation proportionnelle au temps courant
|
||||||
|
currentRotation = (audio.currentTime / audio.duration) * 360 * rotationsPerTrack;
|
||||||
|
vinyl.style.transform = `rotate(${currentRotation}deg)`;
|
||||||
|
console.log('Rotation:', currentRotation); // Debug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Événements
|
||||||
|
|
||||||
|
vinyl.addEventListener('click', togglePlay);
|
||||||
|
audio.addEventListener('timeupdate', updateProgress);
|
||||||
|
audio.addEventListener('loadedmetadata', () => {
|
||||||
|
durationEl.textContent = formatTime(audio.duration);
|
||||||
|
console.log('Audio duration:', audio.duration);
|
||||||
|
});
|
||||||
|
progress.addEventListener('click', setProgress);
|
||||||
|
|
||||||
|
backwardBtn.addEventListener('click', () => {
|
||||||
|
audio.currentTime = Math.max(0, audio.currentTime - 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
forwardBtn.addEventListener('click', () => {
|
||||||
|
audio.currentTime = Math.min(audio.duration, audio.currentTime + 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
loopBtn.addEventListener('click', () => {
|
||||||
|
isLooping = !isLooping;
|
||||||
|
loopBtn.style.backgroundColor = isLooping ? 'white' : 'transparent';
|
||||||
|
loopBtn.style.color = isLooping ? '#18344b' : 'white';
|
||||||
|
});
|
||||||
|
|
||||||
|
audio.addEventListener('ended', () => {
|
||||||
|
if (isLooping) {
|
||||||
|
audio.currentTime = 0;
|
||||||
|
audio.play();
|
||||||
|
} else {
|
||||||
|
isPlaying = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,54 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||||
|
<title>Stamina</title>
|
||||||
|
<link rel="stylesheet" href="stylestam.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<header class="page-header">
|
||||||
|
<a href="front.html" class="logo-container">
|
||||||
|
<img src="logo.png" alt="Logo" class="logo" />
|
||||||
|
</a>
|
||||||
|
<h1 class="title">Stamina</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
|
||||||
|
<main class="vinyl-container">
|
||||||
|
|
||||||
|
<div class="vinyl" id="vinyl">
|
||||||
|
<img src="WhatsApp Image 2025-04-21 at 15.01.32.jpeg" alt="Pochette" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="title-under">
|
||||||
|
<span class="song-title">Stamina</span><br>
|
||||||
|
<span class="artist-name">Corb Nurk</span>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="progress-container">
|
||||||
|
<input type="range" id="progress" value="0" />
|
||||||
|
|
||||||
|
<div class="time-wrapper">
|
||||||
|
<div id="currentTime" class="time">0:00</div>
|
||||||
|
<div id="duration" class="time">4:43</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="buttons-container">
|
||||||
|
<button id="backward">- 10s</button>
|
||||||
|
<button id="loop">LOOP</button>
|
||||||
|
<button id="forward">10s +</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<audio id="audio"
|
||||||
|
src="stamina-v17.mp3"
|
||||||
|
data-reverse-src="stamina-v17_reverse.mp3"></audio>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script src="socket.io.min.js"></script>
|
||||||
|
<script src="script.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -31,27 +31,36 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-container {
|
||||||
|
|
||||||
.logo{
|
|
||||||
margin-top: 40px;
|
|
||||||
max-width: 180px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
margin-bottom: 30px; /* pour séparer du reste */
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
display: block;
|
||||||
|
margin-top: 40px;
|
||||||
|
margin-right: auto;
|
||||||
|
max-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-size: 70%;
|
font-size: 70%;
|
||||||
|
margin-top: 10px; /* espace entre logo et h1 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-size: 40%;
|
font-size: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-title {
|
||||||
|
color: black;
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.orange {
|
.orange {
|
||||||
@@ -73,7 +82,6 @@ h2 {
|
|||||||
text-align: center
|
text-align: center
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Champs de texte */
|
|
||||||
.login-container input {
|
.login-container input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
@@ -83,10 +91,16 @@ h2 {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bouton */
|
.login-container input:focus {
|
||||||
.login-container button {
|
border: 2px solid #ffa600; /* ou la couleur que tu veux */
|
||||||
width: 100%;
|
outline: none; /* enlève le contour bleu par défaut */
|
||||||
padding: 10px;
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%; /* pareil que les input */
|
||||||
|
padding: 12px;
|
||||||
|
margin-top: 40px; /* plus de marge */
|
||||||
background-color:#ffa600;
|
background-color:#ffa600;
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
@@ -94,11 +108,17 @@ h2 {
|
|||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background 0.3s ease;
|
transition: background 0.3s ease;
|
||||||
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-container button:hover {
|
|
||||||
|
.button:hover {
|
||||||
background-color: #dd3000;
|
background-color: #dd3000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error-message {
|
||||||
|
color: red;
|
||||||
|
margin-top: 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300&display=swap');
|
||||||
|
*{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: 'Poppins', sans-serif;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: linear-gradient(to bottom, #ffa600, #dd3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Structure de base */
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start; /* Aligne à gauche */
|
||||||
|
align-items: center; /* Centré verticalement si tu ajoutes du texte à côté */
|
||||||
|
padding: 10px 20px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style du logo */
|
||||||
|
.logo {
|
||||||
|
width: 120px; /* Ajuste la taille selon ton design */
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive pour smartphone */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.logo {
|
||||||
|
width: 100px; /* Un peu plus petit sur mobile si nécessaire */
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
padding: 20px;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-card {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-decoration: none;
|
||||||
|
color: white;
|
||||||
|
transition: background-color 0.3s, transform 0.2s;
|
||||||
|
box-shadow: 0 4px 10px rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-card:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-card img {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-info {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-info h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-info p {
|
||||||
|
margin: 5px 0 0;
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300&display=swap');
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: linear-gradient(to bottom, #500000, #000000);
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.page-header {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
pointer-events: none; /* pour que seul le logo reste cliquable */
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-container {
|
||||||
|
position: absolute;
|
||||||
|
left: 20px;
|
||||||
|
pointer-events: auto; /* permet au logo d'être cliquable malgré pointer-events: none plus haut */
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: 120px;
|
||||||
|
height: auto;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: white;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.vinyl-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Titre du bas avec un <br> stylé */
|
||||||
|
|
||||||
|
.title-under {
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.song-title {
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.artist-name {
|
||||||
|
margin: none;
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 400;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl {
|
||||||
|
width: 600px;
|
||||||
|
height: 600px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: radial-gradient(circle at center, #444 0%, #111 60%, #000 100%);
|
||||||
|
/*animation: spin 5s linear infinite paused;*/
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl.reverse {
|
||||||
|
animation: spin-reverse 4s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl img {
|
||||||
|
width: 40%;
|
||||||
|
border-radius: 50%;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style pour la barre de progression */
|
||||||
|
.progress-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
width: 80%;
|
||||||
|
max-width: 500px;
|
||||||
|
margin-inline: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress {
|
||||||
|
width: 100%;
|
||||||
|
height: 6px;
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 5px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress::-moz-range-thumb {
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Position des timestamps */
|
||||||
|
|
||||||
|
.time-wrapper {
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 20px;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px; /* <-- ajoute ceci pour écarter duration du bouton */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.buttons-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
width: 80%;
|
||||||
|
max-width: 500px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 16px;
|
||||||
|
background: none;
|
||||||
|
border: 1px solid white;
|
||||||
|
color: white;
|
||||||
|
padding: 6px 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.vinyl {
|
||||||
|
width: 70vw;
|
||||||
|
height: 70vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl img {
|
||||||
|
width: 45%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress {
|
||||||
|
width: 85vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-container {
|
||||||
|
width: 85vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300&display=swap');
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: linear-gradient(to bottom, #3d78a8, #00182e);
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.page-header {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
pointer-events: none; /* pour que seul le logo reste cliquable */
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-container {
|
||||||
|
position: absolute;
|
||||||
|
left: 20px;
|
||||||
|
pointer-events: auto; /* permet au logo d'être cliquable malgré pointer-events: none plus haut */
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: 120px;
|
||||||
|
height: auto;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: white;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.vinyl-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Titre du bas avec un <br> stylé */
|
||||||
|
|
||||||
|
.title-under {
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.song-title {
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.artist-name {
|
||||||
|
margin: none;
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 400;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl {
|
||||||
|
width: 600px;
|
||||||
|
height: 600px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: radial-gradient(circle at center, #444 0%, #111 60%, #000 100%);
|
||||||
|
/*animation: spin 4s linear infinite;
|
||||||
|
animation-play-state: paused;*/
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: transform 0.3s linear;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.vinyl.reverse {
|
||||||
|
animation: spin-reverse 4s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl img {
|
||||||
|
width: 40%;
|
||||||
|
border-radius: 50%;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style pour la barre de progression */
|
||||||
|
.progress-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
width: 80%;
|
||||||
|
max-width: 500px;
|
||||||
|
margin-inline: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress {
|
||||||
|
width: 100%;
|
||||||
|
height: 6px;
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 5px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress::-moz-range-thumb {
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Position des timestamps */
|
||||||
|
|
||||||
|
.time-wrapper {
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 20px;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px; /* <-- ajoute ceci pour écarter duration du bouton */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.buttons-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
width: 80%;
|
||||||
|
max-width: 500px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 16px;
|
||||||
|
background: none;
|
||||||
|
border: 1px solid white;
|
||||||
|
color: white;
|
||||||
|
padding: 6px 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
from { transform: rotate(0deg); }
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin-reverse {
|
||||||
|
from { transform: rotate(0deg); }
|
||||||
|
to { transform: rotate(-360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.vinyl {
|
||||||
|
width: 70vw;
|
||||||
|
height: 70vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl img {
|
||||||
|
width: 45%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress {
|
||||||
|
width: 85vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-container {
|
||||||
|
width: 85vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300&display=swap');
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: linear-gradient(to bottom, #000e33, #002f96);
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.page-header {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
pointer-events: none; /* pour que seul le logo reste cliquable */
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-container {
|
||||||
|
position: absolute;
|
||||||
|
left: 20px;
|
||||||
|
pointer-events: auto; /* permet au logo d'être cliquable malgré pointer-events: none plus haut */
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: 120px;
|
||||||
|
height: auto;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: white;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.vinyl-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Titre du bas avec un <br> stylé */
|
||||||
|
|
||||||
|
.title-under {
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.song-title {
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.artist-name {
|
||||||
|
margin: none;
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 400;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl {
|
||||||
|
width: 600px;
|
||||||
|
height: 600px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: radial-gradient(circle at center, #444 0%, #111 60%, #000 100%);
|
||||||
|
/*animation: spin 5s linear infinite paused;*/
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl.reverse {
|
||||||
|
animation: spin-reverse 4s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl img {
|
||||||
|
width: 40%;
|
||||||
|
border-radius: 50%;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style pour la barre de progression */
|
||||||
|
.progress-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
width: 80%;
|
||||||
|
max-width: 500px;
|
||||||
|
margin-inline: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress {
|
||||||
|
width: 100%;
|
||||||
|
height: 6px;
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 5px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress::-moz-range-thumb {
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Position des timestamps */
|
||||||
|
|
||||||
|
.time-wrapper {
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 20px;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px; /* <-- ajoute ceci pour écarter duration du bouton */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.buttons-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
width: 80%;
|
||||||
|
max-width: 500px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 16px;
|
||||||
|
background: none;
|
||||||
|
border: 1px solid white;
|
||||||
|
color: white;
|
||||||
|
padding: 6px 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.vinyl {
|
||||||
|
width: 70vw;
|
||||||
|
height: 70vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl img {
|
||||||
|
width: 45%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress {
|
||||||
|
width: 85vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-container {
|
||||||
|
width: 85vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300&display=swap');
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: linear-gradient(to bottom, #000000, #4e4e4e);
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.page-header {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
pointer-events: none; /* pour que seul le logo reste cliquable */
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-container {
|
||||||
|
position: absolute;
|
||||||
|
left: 20px;
|
||||||
|
pointer-events: auto; /* permet au logo d'être cliquable malgré pointer-events: none plus haut */
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: 120px;
|
||||||
|
height: auto;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: white;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.vinyl-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Titre du bas avec un <br> stylé */
|
||||||
|
|
||||||
|
.title-under {
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.song-title {
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.artist-name {
|
||||||
|
margin: none;
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 400;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl {
|
||||||
|
width: 600px;
|
||||||
|
height: 600px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: radial-gradient(circle at center, #444 0%, #111 60%, #000 100%);
|
||||||
|
/*animation: spin 5s linear infinite paused;*/
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl.reverse {
|
||||||
|
animation: spin-reverse 4s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl img {
|
||||||
|
width: 40%;
|
||||||
|
border-radius: 50%;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style pour la barre de progression */
|
||||||
|
.progress-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
width: 80%;
|
||||||
|
max-width: 500px;
|
||||||
|
margin-inline: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress {
|
||||||
|
width: 100%;
|
||||||
|
height: 6px;
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 5px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress::-moz-range-thumb {
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Position des timestamps */
|
||||||
|
|
||||||
|
.time-wrapper {
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 20px;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px; /* <-- ajoute ceci pour écarter duration du bouton */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.buttons-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
width: 80%;
|
||||||
|
max-width: 500px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 16px;
|
||||||
|
background: none;
|
||||||
|
border: 1px solid white;
|
||||||
|
color: white;
|
||||||
|
padding: 6px 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.vinyl {
|
||||||
|
width: 70vw;
|
||||||
|
height: 70vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vinyl img {
|
||||||
|
width: 45%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress {
|
||||||
|
width: 85vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-container {
|
||||||
|
width: 85vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+346
@@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"pug": "^3.0.3",
|
"pug": "^3.0.3",
|
||||||
|
"serialport": "^13.0.0",
|
||||||
"socket.io": "^4.8.1"
|
"socket.io": "^4.8.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -60,6 +61,280 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@serialport/binding-mock": {
|
||||||
|
"version": "10.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-10.2.2.tgz",
|
||||||
|
"integrity": "sha512-HAFzGhk9OuFMpuor7aT5G1ChPgn5qSsklTFOTUX72Rl6p0xwcSVsRtG/xaGp6bxpN7fI9D/S8THLBWbBgS6ldw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@serialport/bindings-interface": "^1.2.1",
|
||||||
|
"debug": "^4.3.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/binding-mock/node_modules/debug": {
|
||||||
|
"version": "4.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||||
|
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/binding-mock/node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/bindings-cpp": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/bindings-cpp/-/bindings-cpp-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-r25o4Bk/vaO1LyUfY/ulR6hCg/aWiN6Wo2ljVlb4Pj5bqWGcSRC4Vse4a9AcapuAu/FeBzHCbKMvRQeCuKjzIQ==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@serialport/bindings-interface": "1.2.2",
|
||||||
|
"@serialport/parser-readline": "12.0.0",
|
||||||
|
"debug": "4.4.0",
|
||||||
|
"node-addon-api": "8.3.0",
|
||||||
|
"node-gyp-build": "4.8.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/serialport/donate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/bindings-cpp/node_modules/@serialport/parser-delimiter": {
|
||||||
|
"version": "12.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-12.0.0.tgz",
|
||||||
|
"integrity": "sha512-gu26tVt5lQoybhorLTPsH2j2LnX3AOP2x/34+DUSTNaUTzu2fBXw+isVjQJpUBFWu6aeQRZw5bJol5X9Gxjblw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/serialport/donate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/bindings-cpp/node_modules/@serialport/parser-readline": {
|
||||||
|
"version": "12.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-12.0.0.tgz",
|
||||||
|
"integrity": "sha512-O7cywCWC8PiOMvo/gglEBfAkLjp/SENEML46BXDykfKP5mTPM46XMaX1L0waWU6DXJpBgjaL7+yX6VriVPbN4w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@serialport/parser-delimiter": "12.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/serialport/donate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/bindings-cpp/node_modules/debug": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/bindings-cpp/node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/bindings-interface": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/bindings-interface/-/bindings-interface-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-CJaUd5bLvtM9c5dmO9rPBHPXTa9R2UwpkJ0wdh9JCYcbrPWsKz+ErvR0hBLeo7NPeiFdjFO4sonRljiw4d2XiA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.22 || ^14.13 || >=16"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/parser-byte-length": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-32yvqeTAqJzAEtX5zCrN1Mej56GJ5h/cVFsCDPbF9S1ZSC9FWjOqNAgtByseHfFTSTs/4ZBQZZcZBpolt8sUng==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/serialport/donate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/parser-cctalk": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-RErAe57g9gvnlieVYGIn1xymb1bzNXb2QtUQd14FpmbQQYlcrmuRnJwKa1BgTCujoCkhtaTtgHlbBWOxm8U2uA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/serialport/donate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/parser-delimiter": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-Qqyb0FX1avs3XabQqNaZSivyVbl/yl0jywImp7ePvfZKLwx7jBZjvL+Hawt9wIG6tfq6zbFM24vzCCK7REMUig==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/serialport/donate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/parser-inter-byte-timeout": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-a0w0WecTW7bD2YHWrpTz1uyiWA2fDNym0kjmPeNSwZ2XCP+JbirZt31l43m2ey6qXItTYVuQBthm75sPVeHnGA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/serialport/donate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/parser-packet-length": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/parser-packet-length/-/parser-packet-length-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-60ZDDIqYRi0Xs2SPZUo4Jr5LLIjtb+rvzPKMJCohrO6tAqSDponcNpcB1O4W21mKTxYjqInSz+eMrtk0LLfZIg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/parser-readline": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-dov3zYoyf0dt1Sudd1q42VVYQ4WlliF0MYvAMA3MOyiU1IeG4hl0J6buBA2w4gl3DOCC05tGgLDN/3yIL81gsA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@serialport/parser-delimiter": "13.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/serialport/donate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/parser-ready": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-JNUQA+y2Rfs4bU+cGYNqOPnNMAcayhhW+XJZihSLQXOHcZsFnOa2F9YtMg9VXRWIcnHldHYtisp62Etjlw24bw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/serialport/donate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/parser-regex": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-m7HpIf56G5XcuDdA3DB34Z0pJiwxNRakThEHjSa4mG05OnWYv0IG8l2oUyYfuGMowQWaVnQ+8r+brlPxGVH+eA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/serialport/donate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/parser-slip-encoder": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/parser-slip-encoder/-/parser-slip-encoder-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-fUHZEExm6izJ7rg0A1yjXwu4sOzeBkPAjDZPfb+XQoqgtKAk+s+HfICiYn7N2QU9gyaeCO8VKgWwi+b/DowYOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/serialport/donate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/parser-spacepacket": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/parser-spacepacket/-/parser-spacepacket-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-DoXJ3mFYmyD8X/8931agJvrBPxqTaYDsPoly9/cwQSeh/q4EjQND9ySXBxpWz5WcpyCU4jOuusqCSAPsbB30Eg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/serialport/donate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/stream": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-F7xLJKsjGo2WuEWMSEO1SimRcOA+WtWICsY13r0ahx8s2SecPQH06338g28OT7cW7uRXI7oEQAk62qh5gHJW3g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@serialport/bindings-interface": "1.2.2",
|
||||||
|
"debug": "4.4.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/serialport/donate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/stream/node_modules/debug": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@serialport/stream/node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@socket.io/component-emitter": {
|
"node_modules/@socket.io/component-emitter": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
|
||||||
@@ -818,6 +1093,26 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-addon-api": {
|
||||||
|
"version": "8.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.0.tgz",
|
||||||
|
"integrity": "sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "^18 || ^20 || >= 21"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-gyp-build": {
|
||||||
|
"version": "4.8.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
|
||||||
|
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"node-gyp-build": "bin.js",
|
||||||
|
"node-gyp-build-optional": "optional.js",
|
||||||
|
"node-gyp-build-test": "build-test.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/object-assign": {
|
"node_modules/object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
@@ -1142,6 +1437,57 @@
|
|||||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/serialport": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/serialport/-/serialport-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-PHpnTd8isMGPfFTZNCzOZp9m4mAJSNWle9Jxu6BPTcWq7YXl5qN7tp8Sgn0h+WIGcD6JFz5QDgixC2s4VW7vzg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@serialport/binding-mock": "10.2.2",
|
||||||
|
"@serialport/bindings-cpp": "13.0.0",
|
||||||
|
"@serialport/parser-byte-length": "13.0.0",
|
||||||
|
"@serialport/parser-cctalk": "13.0.0",
|
||||||
|
"@serialport/parser-delimiter": "13.0.0",
|
||||||
|
"@serialport/parser-inter-byte-timeout": "13.0.0",
|
||||||
|
"@serialport/parser-packet-length": "13.0.0",
|
||||||
|
"@serialport/parser-readline": "13.0.0",
|
||||||
|
"@serialport/parser-ready": "13.0.0",
|
||||||
|
"@serialport/parser-regex": "13.0.0",
|
||||||
|
"@serialport/parser-slip-encoder": "13.0.0",
|
||||||
|
"@serialport/parser-spacepacket": "13.0.0",
|
||||||
|
"@serialport/stream": "13.0.0",
|
||||||
|
"debug": "4.4.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/serialport/donate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/serialport/node_modules/debug": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/serialport/node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/serve-static": {
|
"node_modules/serve-static": {
|
||||||
"version": "1.16.2",
|
"version": "1.16.2",
|
||||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
|
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"pug": "^3.0.3",
|
"pug": "^3.0.3",
|
||||||
|
"serialport": "^13.0.0",
|
||||||
"socket.io": "^4.8.1"
|
"socket.io": "^4.8.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
loop
|
||||||
|
====
|
||||||
|
```shell
|
||||||
|
git clone
|
||||||
|
npm install
|
||||||
|
node server.js
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
https://serialport.io/docs/guide-usage
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const { createServer } = require('node:http');
|
||||||
|
// socket
|
||||||
|
const { Server } = require('socket.io');
|
||||||
|
// usb serial (arduino)
|
||||||
|
var { SerialPort } = require("serialport");
|
||||||
|
const { ReadlineParser } = require('@serialport/parser-readline')
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const server = createServer(app);
|
||||||
|
const io = new Server(server);
|
||||||
|
|
||||||
|
const port = 3000
|
||||||
|
|
||||||
|
// https://serialport.io/docs/guide-usage
|
||||||
|
|
||||||
|
var arduinoCOMPort = "/dev/ttyUSB0";
|
||||||
|
var arduinoSerialPort = new SerialPort({
|
||||||
|
path: arduinoCOMPort,
|
||||||
|
baudRate: 9600
|
||||||
|
});
|
||||||
|
|
||||||
|
arduinoSerialPort.on('open',function() {
|
||||||
|
console.log('Serial Port ' + arduinoCOMPort + ' is opened.');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// // Read data that is available but keep the stream in "paused mode"
|
||||||
|
// arduinoSerialPort.on('readable', function () {
|
||||||
|
// console.log('Data:', arduinoSerialPort.read())
|
||||||
|
// })
|
||||||
|
|
||||||
|
// // Switches the port into "flowing mode"
|
||||||
|
// arduinoSerialPort.on('data', function (data) {
|
||||||
|
// console.log('Data:', data)
|
||||||
|
// })
|
||||||
|
|
||||||
|
// const serialParser = arduinoSerialPort.pipe(new Readline({ delimiter: '\n' }));
|
||||||
|
|
||||||
|
// serialParser.on('data', data =>{
|
||||||
|
// console.log('got word from arduino:', data);
|
||||||
|
// });
|
||||||
|
|
||||||
|
app.set('view engine', 'pug')
|
||||||
|
app.use(express.static('assets'))
|
||||||
|
|
||||||
|
app.get('/', (req, res) => {
|
||||||
|
// res.send('Hello World!')
|
||||||
|
// res.render('index', { title: 'Hey', message: 'Hello there PUG!' })
|
||||||
|
res.sendFile('assets/main.html', { root : __dirname});
|
||||||
|
})
|
||||||
|
|
||||||
|
io.on('connection', (socket) => {
|
||||||
|
console.log('a user connected');
|
||||||
|
// let speed = 0.1;
|
||||||
|
// setInterval(() => {
|
||||||
|
// speed+=0.1;
|
||||||
|
// socket.emit('speed', speed);
|
||||||
|
// }, 2000);
|
||||||
|
|
||||||
|
// Listening to arduino through serial port
|
||||||
|
const parser = arduinoSerialPort.pipe(new ReadlineParser({ delimiter: '\n' }))
|
||||||
|
parser.on('data', data => {
|
||||||
|
console.log('got word from arduino:', data);
|
||||||
|
socket.emit('position', data);
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(port, () => {
|
||||||
|
console.log(`Example app listening on port ${port}`)
|
||||||
|
})
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,7 +1,9 @@
|
|||||||
loop
|
Loop
|
||||||
====
|
====
|
||||||
```shell
|
|
||||||
git clone
|
# Node
|
||||||
npm install
|
https://gitea.esadhar.fr/el-yazide.mohamed/loop
|
||||||
node server.js
|
|
||||||
```
|
# Arduino
|
||||||
|
https://arduinogetstarted.com/tutorials/arduino-dc-motor
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const { createServer } = require('node:http');
|
|
||||||
const { Server } = require('socket.io');
|
|
||||||
|
|
||||||
const app = express();
|
|
||||||
const server = createServer(app);
|
|
||||||
const io = new Server(server);
|
|
||||||
|
|
||||||
|
|
||||||
const port = 3000
|
|
||||||
|
|
||||||
|
|
||||||
app.set('view engine', 'pug')
|
|
||||||
app.use(express.static('assets'))
|
|
||||||
|
|
||||||
app.get('/', (req, res) => {
|
|
||||||
// res.send('Hello World!')
|
|
||||||
// res.render('index', { title: 'Hey', message: 'Hello there PUG!' })
|
|
||||||
res.sendFile('index.html');
|
|
||||||
})
|
|
||||||
|
|
||||||
io.on('connection', (socket) => {
|
|
||||||
console.log('a user connected');
|
|
||||||
let speed = 0.1;
|
|
||||||
setInterval(() => {
|
|
||||||
speed+=0.1;
|
|
||||||
socket.emit('speed', speed);
|
|
||||||
}, 2000);
|
|
||||||
});
|
|
||||||
|
|
||||||
server.listen(port, () => {
|
|
||||||
console.log(`Example app listening on port ${port}`)
|
|
||||||
})
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
.vscode
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#include <Encoder.h>
|
||||||
|
|
||||||
|
long last_position = 0;
|
||||||
|
|
||||||
|
Encoder myEnc(2, 3); // pins for A and B
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
long position = myEnc.read();
|
||||||
|
if(position != last_position){
|
||||||
|
last_position = position;
|
||||||
|
Serial.println(position);
|
||||||
|
}
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user