From 9f7b05294c96dad7c16a4b5bc25b89c39aabb392 Mon Sep 17 00:00:00 2001 From: wisplite Date: Mon, 8 Sep 2025 17:43:06 -0500 Subject: [PATCH] dark mode and improved network coloring --- CompleteMoveOnEdge.js | 1 + README.md | 2 +- index.html | 10 +- script.js | 38 +++++++- style-dark.css | 207 ++++++++++++++++++++++++++++++++++++++++++ style.css | 4 + 6 files changed, 256 insertions(+), 6 deletions(-) create mode 100644 style-dark.css diff --git a/CompleteMoveOnEdge.js b/CompleteMoveOnEdge.js index cce286f..d1879ec 100644 --- a/CompleteMoveOnEdge.js +++ b/CompleteMoveOnEdge.js @@ -402,6 +402,7 @@ class CompleteNodeOnEdgeEngine { ratio: init_ratio, reversed: path[1], fixed: true, + font: node.font, }; var edge = this.network.body.edges[newDotNode.edge]; diff --git a/README.md b/README.md index 4a4f478..769d99a 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ You can: When sending packets, the colors of each node will change to reflect the TTL of the packet. The more green a node is, the closer it was to the origin of the packet, the more red a node is, the further it is from the origin. Nodes that were unable to receive the packet will turn white (this is often due to low TTL on large networks). -I have also found that this simulation can vary wildly in performance depending on the machine it's running on. Make sure your browser supports GPU acceleration, or else this will run very poorly with large networks. +I have also found that this simulation can vary wildly in performance depending on the machine and browser it's running on. Make sure your browser supports GPU acceleration, or else this will run very poorly with large networks. I have personally found that Chrome works the best for this by a huge margin, as much as I love Firefox. You should be able to run this simulation by opening the `index.html` file in your browser, there's no fancy stack or anything, just pure HTML, CSS, and JavaScript. diff --git a/index.html b/index.html index 3d19718..5c4212c 100644 --- a/index.html +++ b/index.html @@ -7,13 +7,13 @@ - +
Simulation Properties
-
+
Simple Settings
@@ -43,6 +43,12 @@
+
+
+
+ + +
diff --git a/script.js b/script.js index dce0b26..d7a62dd 100644 --- a/script.js +++ b/script.js @@ -100,16 +100,21 @@ var onEdgeEngine = new CompleteNodeOnEdgeEngine(network, nodes, dotNodes, edges, onEdgeEngine.createEdgesTable(); onEdgeEngine.initMovement(); onEdgeEngine.setArrivalCallback(({ from, to, dot }) => { + var ttl = parseInt(dot.id.split('-')[2]); + if (document.getElementById('showTTL').checked) { + edges.update({id: `${from}->${to}`, color: {color: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1), highlight: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1)}}); + } else { + edges.update({id: `${from}->${to}`, color: {color: '#2b7ce9', highlight: '#2b7ce9'}}); + } if (nodeTable[to].packetCache.includes(dot.id.split('-')[0])) { return; } // update color of receiving node for visualization nodeTable[to].packetCache.push(dot.id.split('-')[0]); var packetId = dot.id.split('-')[0]; - var ttl = parseInt(dot.id.split('-')[2]); ttl--; if (document.getElementById('showTTL').checked) { - nodes.update({id: to, color: {background: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl)}}); + nodes.update({id: to, color: {background: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl)}}); } else { nodes.update({id: to, color: {background: '#97c2fc'}}); } @@ -127,6 +132,9 @@ onEdgeEngine.setArrivalCallback(({ from, to, dot }) => { shape: dot.shape, size: dot.size, color: dot.color, + font: { + color: document.getElementById('darkMode').checked ? '#e0e0e0' : '#000' + } }; onEdgeEngine.createDotNode(movingNode, to, neighbor); } @@ -155,6 +163,7 @@ const markNeighborsAsFailed = (nodeId, from, packetId, visited = new Set()) => { continue; } nodes.update({id: neighbor, color: {background: 'white'}}); + edges.update({id: `${nodeId}->${neighbor}`, color: {color: 'white', highlight: '#97c2fc'}}); markNeighborsAsFailed(neighbor, nodeId, packetId, visited); } } @@ -465,6 +474,9 @@ document.getElementById('sendPacket').addEventListener('click', function() { background: 'white', border: 'black' }, + font: { + color: document.getElementById('darkMode').checked ? '#e0e0e0' : '#000' + } }; onEdgeEngine.createDotNode(movingNode, selectedNode, connection); nodeTable[selectedNode].packetCache.push(packetId); @@ -476,6 +488,10 @@ document.getElementById('resetTTLColors').addEventListener('click', function() { for (let node of nodes.get()) { nodes.update({id: node.id, color: {background: '#97c2fc'}}); } + + for (let edge of edges.get()) { + edges.update({id: edge.id, color: {color: '#2b7ce9', highlight: '#2b7ce9'}}); + } }); document.getElementById('updateInterval').addEventListener('change', function() { @@ -543,4 +559,20 @@ document.getElementById('createRandomGraphConfirm').addEventListener('click', fu } }, 10); document.getElementById('randomGraphModal').style.display = 'none'; -}); \ No newline at end of file +}); + +document.getElementById('darkMode').addEventListener('change', function() { + if (this.checked) { + document.getElementById('styleSheet').href = 'style-dark.css'; + } else { + document.getElementById('styleSheet').href = 'style.css'; + } +}); + +window.onload = function() { + if (document.getElementById('darkMode').checked) { + document.getElementById('styleSheet').href = 'style-dark.css'; + } else { + document.getElementById('styleSheet').href = 'style.css'; + } +} \ No newline at end of file diff --git a/style-dark.css b/style-dark.css new file mode 100644 index 0000000..12e273b --- /dev/null +++ b/style-dark.css @@ -0,0 +1,207 @@ +#simContainer { + width: 100%; + height: 90%; + margin: 0 auto; + border: 1px solid #404040; + box-sizing: border-box; + position: relative; + padding: 0; + overflow: hidden; + background-color: #1a1a1a; +} + +#controlContainer { + width: 100%; + height: 10%; + margin: 0 auto; + border: 1px solid #404040; + padding: 5px; + box-sizing: border-box; + display: flex; + gap: 5px; + flex-direction: column; + justify-content: center; + align-items: center; + background-color: #2d2d2d; +} + +#connectionViewer, #propertyViewer { + width: 15%; + height: 90%; + margin: 0 auto; + border: 1px solid #404040; + padding: 5px; + display: flex; + flex-direction: column; + justify-content: start; + align-items: start; + background-color: #252525; + color: #e0e0e0; +} + +.controlButton { + width: 100%; + height: 100%; + cursor: pointer; + background-color: #3a3a3a; + color: #e0e0e0; + border: 1px solid #555555; + border-radius: 4px; + transition: background-color 0.2s ease; +} + +.controlButton:hover { + background-color: #4a4a4a; +} + +.controlButton:active { + background-color: #2a2a2a; +} +html, body { + width: 100vw; + height: 100vh; + margin: 0; + padding: 0; + box-sizing: border-box; + background-color: #1a1a1a; + color: #e0e0e0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; +} + +.rangeVis { + position: absolute; + border: 1px solid #666666; + border-radius: 50%; + z-index: 1000; + opacity: 0.3; + background-color: #ff6b6b; + pointer-events: none; +} + +#controlButtons { + display: flex; + flex-direction: row; + flex-grow: 1; + gap: 10px; +} + +#simToggles { + display: flex; + flex-direction: row; + flex-shrink: 1; + gap: 10px; +} + +#simpleSettingsContent, #engineSettingsContent, #hardwareConstraintsContent { + display: flex; + flex-direction: column; + gap: 10px; + padding-left: 20px; + padding-top: 10px; +} + +#simpleSettings, #hardwareConstraints, #engineSettings { + margin-bottom: 10px; +} + +#randomGraphModal, #warningModal { + display: none; + position: absolute; + top: 0%; + left: 0%; + transform: translate(0%, 0%); + background-color: rgba(0, 0, 0, 0.8); + padding: 20px; + border: none; + width: 100%; + height: 100%; +} + +#warningModalContent { + padding: 20px; + background-color: #2d2d2d; + border: 2px solid #ffaa00; + border-radius: 8px; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: #e0e0e0; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5); +} + +#randomGraphModalContent { + padding: 20px; + background-color: #2d2d2d; + border: 1px solid #555555; + border-radius: 8px; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: #e0e0e0; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5); +} + +#createRandomGraphConfirm { + margin-top: 10px; + background-color: #4a9eff; + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.2s ease; +} + +#createRandomGraphConfirm:hover { + background-color: #3a8eef; +} + +#createRandomGraphConfirm:active { + background-color: #2a7edf; +} + +/* Input and form styling for dark mode */ +input, select, textarea { + background-color: #3a3a3a; + color: #e0e0e0; + border: 1px solid #555555; + border-radius: 4px; + padding: 4px 8px; +} + +input:focus, select:focus, textarea:focus { + outline: none; + border-color: #4a9eff; + box-shadow: 0 0 0 2px rgba(74, 158, 255, 0.2); +} + +/* Label styling */ +label { + color: #e0e0e0; +} + +/* Button styling */ +button { + background-color: #3a3a3a; + color: #e0e0e0; + border: 1px solid #555555; + border-radius: 4px; + padding: 6px 12px; + cursor: pointer; + transition: background-color 0.2s ease; +} + +button:hover { + background-color: #4a4a4a; +} + +button:active { + background-color: #2a2a2a; +} + +/* Checkbox and radio button styling */ +input[type="checkbox"], input[type="radio"] { + accent-color: #4a9eff; +} \ No newline at end of file diff --git a/style.css b/style.css index e05c155..e3beada 100644 --- a/style.css +++ b/style.css @@ -29,6 +29,10 @@ margin: 0 auto; border: 1px solid #000; padding: 5px; + display: flex; + flex-direction: column; + justify-content: start; + align-items: start; } .controlButton {