canvas_old.html
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>Canvas Pixel Setter with putImageData</title> 7 <script 8 src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.7.7/axios.min.js" 9 integrity="sha512-DdX/YwF5e41Ok+AI81HI8f5/5UsoxCVT9GKYZRIzpLxb8Twz4ZwPPX+jQMwMhNQ9b5+zDEefc+dcvQoPWGNZ3g==" 10 crossorigin="anonymous" 11 referrerpolicy="no-referrer" 12 ></script> 13 <style> 14 #myCanvas { 15 image-rendering: pixelated; 16 } 17 </style> 18 </head> 19 <body> 20 <canvas 21 id="myCanvas" 22 width="1000" 23 height="1000" 24 style="border: 1px solid #000000" 25 ></canvas> 26 27 <script> 28 // Get the canvas element and its 2D rendering context 29 const canvas = document.getElementById("myCanvas"); 30 31 /* 32 let width = (Math.random() * 300) + 700; 33 let height = 1000000 / width; 34 let remain = (1000000 % width) > 0; 35 if (remain) { 36 height += 1; 37 } 38 */ 39 const ctx = canvas.getContext("2d", (willReadFrequently = true)); 40 41 // Function to set a pixel at (x, y) with the specified color using putImageData 42 43 function setPixel(x, y, color) { 44 // Create an ImageData object with a single pixel 45 const imgData = ctx.createImageData(1, 1); 46 const data = imgData.data; 47 48 // Parse the color string and set the pixel data 49 // Assuming color is in the format '#RRGGBB' 50 const r = parseInt(color.slice(1, 3), 16); 51 const g = parseInt(color.slice(3, 5), 16); 52 const b = parseInt(color.slice(5, 7), 16); 53 const a = 255; // Fully opaque 54 55 // Set the pixel color (R, G, B, A) 56 data[0] = r; 57 data[1] = g; 58 data[2] = b; 59 data[3] = a; 60 61 // Put the ImageData object onto the canvas at (x, y) 62 ctx.putImageData(imgData, x, y); 63 } 64 65 function setPixelAtIndex(index, color) { 66 const imageData = ctx.getImageData(0, 0, 1000, 1000); 67 const data = imageData.data; 68 69 let realIndex = index * 4; 70 71 const r = parseInt(color.slice(1, 3), 16); 72 const g = parseInt(color.slice(3, 5), 16); 73 const b = parseInt(color.slice(5, 7), 16); 74 const a = 255; // Fully opaque 75 76 // Set the pixel color (R, G, B, A) 77 data[realIndex] = r; 78 data[realIndex + 1] = g; 79 data[realIndex + 2] = b; 80 data[realIndex + 3] = a; 81 82 ctx.putImageData(imageData, 0, 0); 83 } 84 85 // Example usage 86 87 /* 88 for (let index = 0; index < 500; index++) { 89 setPixel(500, index, "#AABB00"); 90 } 91 setPixel(500, 500, "#FF0000"); // Set pixel at (500, 500) to red 92 setPixel(100, 100, "#00FF00"); // Set pixel at (100, 100) to green 93 setPixel(900, 900, "#0000FF"); // Set pixel at (900, 900) to blue 94 */ 95 96 function handleCanvasClick(event) { 97 // Get the bounding rectangle of the canvas 98 const rect = canvas.getBoundingClientRect(); 99 // Calculate the coordinates of the click relative to the canvas 100 const x = event.clientX - rect.left; 101 const y = event.clientY - rect.top; 102 103 // Log the coordinates to the console 104 //console.log("Clicked at:", x, y); 105 106 let index = (y * 1000 + x).toString(); 107 //console.log(index); 108 axios.post("/set/" + index).then((d) => { 109 let color; 110 if (d.data == "1") { 111 color = "#000000"; 112 } else { 113 color = "#00ff00"; 114 } 115 116 setPixel(x, y, color); 117 }); 118 119 // Example: Set the pixel at the clicked location to black 120 } 121 122 canvas.addEventListener("click", handleCanvasClick); 123 124 //loadCanvas(); 125 /* 126 axios.post("/set/0").then(() => { 127 //setPixel(x, y, "#000000"); 128 }); 129 */ 130 131 function loadCanvas() { 132 axios.get("/grid").then(function (response) { 133 // handle success 134 //console.log(response); 135 let data = base64ToArrayBuffer(response.data); 136 //console.log(data); 137 loadInitialCanvasData(data); 138 }); 139 } 140 141 function base64ToArrayBuffer(base64) { 142 var binaryString = atob(base64); 143 var bytes = new Uint8Array(binaryString.length); 144 for (var i = 0; i < binaryString.length; i++) { 145 bytes[i] = binaryString.charCodeAt(i); 146 } 147 return bytes.buffer; 148 } 149 150 function loadInitialCanvasData(inputData) { 151 let setCount = 0; 152 const imgData = ctx.createImageData(1000, 1000); 153 let byteInputData = new Uint8Array(inputData); 154 const data = imgData.data; 155 let bit_index = 0; 156 let byte_index = 0; 157 for (let i = 0; i < byteInputData.length * 8; i++) { 158 bit_index = i % 8; 159 byte_index = Math.floor(i / 8); 160 let byte_value = byteInputData[byte_index]; 161 let is_set = is_bit_set(byte_value, bit_index); 162 let color; 163 if (is_set) { 164 //console.log("Found set", byte_index, bit_index); 165 setCount += 1; 166 color = 0; 167 data[i * 4] = 255; //r 168 data[i * 4 + 1] = 0; //g 169 data[i * 4 + 2] = 0; //b 170 } else { 171 color = 255; 172 data[i * 4] = 255; //r 173 data[i * 4 + 1] = 255; //g 174 data[i * 4 + 2] = 255; //b 175 } 176 data[i * 4 + 3] = 255; //a 177 } 178 //console.log(bit_index); 179 ctx.putImageData(imgData, 0, 0); 180 181 console.log(`${setCount} pixels set`); 182 } 183 184 function is_bit_set(byte_value, bit_index) { 185 let mask = 1 << bit_index; 186 return (byte_value & mask) != 0; 187 } 188 189 let socket = null; 190 function ws() { 191 socket = new WebSocket("/ws"); 192 console.log("Connecting"); 193 194 socket.onmessage = (event) => { 195 //console.log(`[message] Данные получены с сервера: ${event.data}`); 196 let data = event.data; 197 data = JSON.parse(data); 198 data.on.forEach((index) => { 199 color = "#ff0000"; 200 let y = Math.floor(index / 1000); 201 let x = index % 1000; 202 setPixel(x, y, color); 203 }); 204 data.off.forEach((index) => { 205 color = "#ffffff"; 206 let y = Math.floor(index / 1000); 207 let x = index % 1000; 208 setPixel(x, y, color); 209 }); 210 }; 211 212 socket.onopen = (e) => { 213 console.log("[open] Соединение установлено"); 214 loadCanvas(); 215 }; 216 217 socket.onclose = (event) => { 218 if (event.wasClean) { 219 console.log( 220 `[close] Соединение закрыто чисто, код=${event.code} причина=${event.reason}` 221 ); 222 } else { 223 // например, сервер убил процесс или сеть недоступна 224 // обычно в этом случае event.code 1006 225 console.log("[close] Соединение прервано"); 226 } 227 }; 228 229 socket.onerror = (error) => { 230 console.log(`[error]`, error); 231 }; 232 } 233 234 ws(); 235 </script> 236 </body> 237 </html>