You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
5.9 KiB

6 days ago
6 days ago
6 days ago
6 days ago
6 days ago
6 days ago
6 days ago
6 days ago
6 days ago
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>Projector View</title>
  7. <style>
  8. body {
  9. font-family: Futura, sans-serif;
  10. font-size: 32px;
  11. background-color: green;
  12. color: white;
  13. text-align: center; /* Align text to the left */
  14. margin: 0;
  15. padding: 0;
  16. -webkit-text-fill-color: white;
  17. -webkit-text-stroke-color: black;
  18. /*-webkit-text-stroke-width: 6.00px; */
  19. paint-order: stroke fill;
  20. }
  21. #container {
  22. overflow: hidden;
  23. height: 200px; /* Ensure container is tall enough for 4 lines */
  24. width: 42ch;
  25. position: relative;
  26. padding-left: 20px; /* Add some padding to the left */
  27. margin-left: auto;
  28. margin-right: auto;
  29. }
  30. #content {
  31. position: relative;
  32. top: 0;
  33. left: auto;
  34. right: auto;
  35. /*transition: top 0.5s ease;*/ /* Smooth scrolling */
  36. }
  37. .line {
  38. opacity: 1;
  39. min-height: 44px;
  40. white-space: normal; /* Allow lines to wrap */
  41. word-wrap: break-word; /* Break long words if needed */
  42. margin: 5px 0;
  43. line-height: 48px;
  44. }
  45. .line span {
  46. background-color: rgba(0, 0, 0, 0.7);
  47. padding: 2px;
  48. }
  49. .currentLine {
  50. font-weight: bold;
  51. opacity: 1;
  52. }
  53. /* Ensure there's space for 4 lines to be displayed */
  54. #container {
  55. max-height: 400px;
  56. }
  57. </style>
  58. </head>
  59. <body>
  60. <div id="container">
  61. <div id="content"></div>
  62. </div>
  63. <script src="/socket.io/socket.io.js"></script>
  64. <script>
  65. const socket = io();
  66. const contentElement = document.getElementById('content');
  67. let speechLines = [];
  68. let currentLineIndex = 0;
  69. // Display 4 lines (previous, current, next, and an extra one above the current line)
  70. function updateDisplay() {
  71. contentElement.innerHTML = ''; // Clear previous lines
  72. const start = Math.max(0, currentLineIndex - 2); // Show 2 lines before current
  73. const end = Math.min(speechLines.length, currentLineIndex + 2); // Show 2 lines after current
  74. // Create a new block of lines
  75. const displayLines = speechLines.slice(start, end).map((line, index) => {
  76. const div = document.createElement('div');
  77. div.classList.add('line');
  78. if (index === 2) div.classList.add('currentLine'); // Highlight the current line
  79. const span = document.createElement('span');
  80. span.textContent = line;
  81. div.appendChild(span);
  82. return div;
  83. });
  84. displayLines.forEach(div => contentElement.appendChild(div));
  85. // Scroll animation based on the height of each line
  86. const lineHeight = document.querySelector('.line').offsetHeight;
  87. const previousLinesHeight = (currentLineIndex - start - 1) * lineHeight; // Offset for lines above the current line
  88. contentElement.style.top = `-${previousLinesHeight}px`;
  89. }
  90. // Receive updates from the server
  91. socket.on('update_caption', (newPosition) => {
  92. currentLineIndex = newPosition;
  93. updateDisplay();
  94. });
  95. // Load the speech when a new client connects
  96. socket.on('load_speech', (lines) => {
  97. speechLines = lines;
  98. currentLineIndex = 0;
  99. updateDisplay(); // Display the initial lines
  100. });
  101. // Update audience text based on live typing
  102. socket.on('live_typing', (text) => {
  103. const lines = text.split('\n'); // Split by new lines
  104. const fullLines = lines.slice(-3); // Get the last three lines
  105. // Check if the last line is complete
  106. let lastLine = fullLines[fullLines.length - 1];
  107. const isLastWordComplete = lastLine.endsWith(' ') || lastLine.endsWith('.') || lastLine.endsWith(',') || lastLine.endsWith('!') || lastLine.endsWith('?') || lastLine.endsWith('\n');
  108. // If the last word is not complete, hide it
  109. if (!isLastWordComplete) {
  110. lastLine = lastLine.trim().split(' ').slice(0, -1).join(' '); // Remove the last word
  111. }
  112. // Join back the lines and update content
  113. contentElement.innerHTML = '';
  114. // Create a new block of lines
  115. let displayLines = (fullLines.slice(0, -1)).map((line, index) => {
  116. const div = document.createElement('div');
  117. div.classList.add('line');
  118. const span = document.createElement('span');
  119. span.textContent = line;
  120. div.appendChild(span);
  121. return div;
  122. });
  123. const lastLineDiv = document.createElement('div');
  124. lastLineDiv.classList.add('line');
  125. lastLineDiv.classList.add('currentLine');
  126. const lastLineSpan = document.createElement('span');
  127. lastLineSpan.textContent = lastLine;
  128. lastLineDiv.appendChild(lastLineSpan);
  129. displayLines.push(lastLineDiv)
  130. displayLines.forEach(div => contentElement.appendChild(div));
  131. // Scroll animation based on the height of each line
  132. //const lineHeight = document.querySelector('.line').offsetHeight;
  133. //const previousLinesHeight = (currentLineIndex - start - 1) * lineHeight; // Offset for lines above the current line
  134. const previousLinesHeight = document.querySelectorAll('.line')[1].offsetHeight;
  135. contentElement.style.top = `-${previousLinesHeight}px`;
  136. });
  137. </script>
  138. </body>
  139. </html>