commit 8edaf7524534d5c62709afe2ea150305789810a2
Author: root <root@hub.scroll.pub> Date: 2025-01-15 23:54:12 +0000 Subject: Initial commit diff --git a/index.scroll b/index.scroll new file mode 100644 index 0000000..ef12b61 --- /dev/null +++ b/index.scroll @@ -0,0 +1,98 @@ +buildHtml +baseUrl https://viz.scroll.pub +metaTags +editButton /edit.html +title Graph Visualizer +style.css +header + class hero + nav + div GraphViz + class logo + div + class nav-links + a Editor + href #editor + a Examples + href #examples + a About + href #about + div + class hero-content + h1 Interactive Graph Visualization + p Create, edit, and visualize graphs in real-time with our powerful web-based tool +main + section + id editor + class graph-editor + h2 Graph Editor + div + class editor-container + div + class controls + button New Node + id addNode + button New Edge + id addEdge + button Clear + id clear + div + class canvas-container + canvas + id graphCanvas + section + id examples + class example-graphs + h2 Example Graphs + div + class example-grid + div + class example-card + h3 Binary Tree + canvas + class mini-canvas + data-type binary + div + class example-card + h3 Neural Network + canvas + class mini-canvas + data-type neural + div + class example-card + h3 Social Network + canvas + class mini-canvas + data-type social + section + id about + class about-section + h2 About GraphViz + p A powerful, browser-based graph visualization tool built with pure JavaScript and Canvas + div + class features-grid + div + class feature + h3 Real-time Rendering + p Smooth, interactive graph manipulation + div + class feature + h3 No Dependencies + p Built with vanilla JavaScript + div + class feature + h3 Customizable + p Adjust layouts and styles +footer + div + class footer-content + p Built with modern web technologies + div + class footer-links + a Documentation + href /docs + a Examples + href #examples + a GitHub + href https://github.com/graphviz +script.js \ No newline at end of file diff --git a/prompt.json b/prompt.json new file mode 100644 index 0000000..91f35ff --- /dev/null +++ b/prompt.json @@ -0,0 +1,20 @@ +{ + "id": "msg_01C5sXVqGuYAHnfYb2NzuTaE", + "type": "message", + "role": "assistant", + "model": "claude-3-5-sonnet-20241022", + "content": [ + { + "type": "text", + "text": "For a graph visualization website, I suggest the domain \"viz.scroll.pub\" - it's short, memorable, and clearly indicates the purpose.\n\n---domain---\nviz.scroll.pub\n---index.scroll---\nbuildHtml\nbaseUrl https://viz.scroll.pub\nmetaTags\neditButton /edit.html\ntitle Graph Visualizer\nstyle.css\nheader\n class hero\n nav\n div GraphViz\n class logo\n div\n class nav-links\n a Editor\n href #editor\n a Examples\n href #examples\n a About\n href #about\n div\n class hero-content\n h1 Interactive Graph Visualization\n p Create, edit, and visualize graphs in real-time with our powerful web-based tool\nmain\n section\n id editor\n class graph-editor\n h2 Graph Editor\n div\n class editor-container\n div\n class controls\n button New Node\n id addNode\n button New Edge\n id addEdge\n button Clear\n id clear\n div\n class canvas-container\n canvas\n id graphCanvas\n section\n id examples\n class example-graphs\n h2 Example Graphs\n div\n class example-grid\n div\n class example-card\n h3 Binary Tree\n canvas\n class mini-canvas\n data-type binary\n div\n class example-card\n h3 Neural Network\n canvas\n class mini-canvas\n data-type neural\n div\n class example-card\n h3 Social Network\n canvas\n class mini-canvas\n data-type social\n section\n id about\n class about-section\n h2 About GraphViz\n p A powerful, browser-based graph visualization tool built with pure JavaScript and Canvas\n div\n class features-grid\n div\n class feature\n h3 Real-time Rendering\n p Smooth, interactive graph manipulation\n div\n class feature\n h3 No Dependencies\n p Built with vanilla JavaScript\n div\n class feature\n h3 Customizable\n p Adjust layouts and styles\nfooter\n div\n class footer-content\n p Built with modern web technologies\n div\n class footer-links\n a Documentation\n href /docs\n a Examples\n href #examples\n a GitHub\n href https://github.com/graphviz\nscript.js\n---style.css---\n:root {\n --primary-color: #2a6bd1;\n --secondary-color: #1d4a94;\n --background-color: #f8faff;\n --text-color: #2c3e50;\n --accent-color: #e74c3c;\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: 'Segoe UI', system-ui, sans-serif;\n line-height: 1.6;\n color: var(--text-color);\n background: var(--background-color);\n}\n\n.hero {\n background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));\n color: white;\n padding: 2rem;\n min-height: 60vh;\n display: flex;\n flex-direction: column;\n}\n\nnav {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1rem 0;\n}\n\n.logo {\n font-size: 1.8rem;\n font-weight: bold;\n background: linear-gradient(45deg, #fff, #e0e0e0);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n}\n\n.nav-links {\n display: flex;\n gap: 2rem;\n}\n\n.nav-links a {\n color: white;\n text-decoration: none;\n transition: all 0.3s ease;\n}\n\n.nav-links a:hover {\n transform: translateY(-2px);\n text-shadow: 0 0 10px rgba(255,255,255,0.5);\n}\n\n.hero-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n text-align: center;\n gap: 1.5rem;\n}\n\n.hero-content h1 {\n font-size: 3.5rem;\n margin-bottom: 1rem;\n text-shadow: 2px 2px 4px rgba(0,0,0,0.2);\n}\n\n.graph-editor {\n padding: 2rem;\n background: white;\n border-radius: 10px;\n margin: 2rem auto;\n max-width: 1200px;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n}\n\n.editor-container {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.controls {\n display: flex;\n gap: 1rem;\n}\n\nbutton {\n padding: 0.8rem 1.5rem;\n border: none;\n border-radius: 5px;\n background: var(--primary-color);\n color: white;\n cursor: pointer;\n transition: all 0.3s ease;\n}\n\nbutton:hover {\n background: var(--secondary-color);\n transform: translateY(-2px);\n}\n\n.canvas-container {\n aspect-ratio: 16/9;\n width: 100%;\n background: #fafafa;\n border-radius: 8px;\n border: 2px solid #eee;\n}\n\n.example-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n gap: 2rem;\n padding: 2rem;\n}\n\n.example-card {\n background: white;\n padding: 1.5rem;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n transition: all 0.3s ease;\n}\n\n.example-card:hover {\n transform: translateY(-5px);\n box-shadow: 0 5px 15px rgba(0,0,0,0.2);\n}\n\n.mini-canvas {\n width: 100%;\n aspect-ratio: 1;\n background: #fafafa;\n border-radius: 4px;\n}\n\nfooter {\n background: var(--secondary-color);\n color: white;\n padding: 2rem;\n margin-top: 4rem;\n}\n\n@media (max-width: 768px) {\n .hero-content h1 {\n font-size: 2.5rem;\n }\n \n .nav-links {\n display: none;\n }\n \n .controls {\n flex-wrap: wrap;\n }\n}\n---script.js---\nclass GraphVisualizer {\n constructor(canvasId) {\n this.canvas = document.getElementById(canvasId);\n this.ctx = this.canvas.getContext('2d');\n this.nodes = [];\n this.edges = [];\n this.isDragging = false;\n this.selectedNode = null;\n \n this.initializeCanvas();\n this.addEventListeners();\n }\n\n initializeCanvas() {\n this.resizeCanvas();\n window.addEventListener('resize', () => this.resizeCanvas());\n }\n\n resizeCanvas() {\n const container = this.canvas.parentElement;\n this.canvas.width = container.clientWidth;\n this.canvas.height = container.clientHeight;\n this.render();\n }\n\n addEventListeners() {\n this.canvas.addEventListener('mousedown', (e) => this.handleMouseDown(e));\n this.canvas.addEventListener('mousemove', (e) => this.handleMouseMove(e));\n this.canvas.addEventListener('mouseup', () => this.handleMouseUp());\n this.canvas.addEventListener('touchstart', (e) => this.handleTouchStart(e));\n this.canvas.addEventListener('touchmove', (e) => this.handleTouchMove(e));\n this.canvas.addEventListener('touchend', () => this.handleTouchEnd());\n }\n\n addNode(x, y) {\n const node = {\n x: x || Math.random() * this.canvas.width,\n y: y || Math.random() * this.canvas.height,\n radius: 20,\n color: `hsl(${Math.random() * 360}, 70%, 50%)`\n };\n this.nodes.push(node);\n this.render();\n }\n\n render() {\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n \n // Draw edges\n this.edges.forEach(edge => {\n this.ctx.beginPath();\n this.ctx.moveTo(edge.start.x, edge.start.y);\n this.ctx.lineTo(edge.end.x, edge.end.y);\n this.ctx.strokeStyle = '#999';\n this.ctx.lineWidth = 2;\n this.ctx.stroke();\n });\n\n // Draw nodes\n this.nodes.forEach(node => {\n this.ctx.beginPath();\n this.ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2);\n this.ctx.fillStyle = node.color;\n this.ctx.fill();\n this.ctx.strokeStyle = '#fff';\n this.ctx.lineWidth = 3;\n this.ctx.stroke();\n });\n }\n\n handleMouseDown(e) {\n const rect = this.canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n \n this.selectedNode = this.nodes.find(node => {\n const dx = node.x - x;\n const dy = node.y - y;\n return Math.sqrt(dx * dx + dy * dy) < node.radius;\n });\n\n if (this.selectedNode) {\n this.isDragging = true;\n }\n }\n\n handleMouseMove(e) {\n if (this.isDragging && this.selectedNode) {\n const rect = this.canvas.getBoundingClientRect();\n this.selectedNode.x = e.clientX - rect.left;\n this.selectedNode.y = e.clientY - rect.top;\n this.render();\n }\n }\n\n handleMouseUp() {\n this.isDragging = false;\n this.selectedNode = null;\n }\n\n // Touch event handlers\n handleTouchStart(e) {\n e.preventDefault();\n const touch = e.touches[0];\n const mouseEvent = new MouseEvent('mousedown', {\n clientX: touch.clientX,\n clientY: touch.clientY\n });\n this.handleMouseDown(mouseEvent);\n }\n\n handleTouchMove(e) {\n e.preventDefault();\n const touch = e.touches[0];\n const mouseEvent = new MouseEvent('mousemove', {\n clientX: touch.clientX,\n clientY: touch.clientY\n });\n this.handleMouseMove(mouseEvent);\n }\n\n handleTouchEnd() {\n this.handleMouseUp();\n }\n}\n\n// Initialize the application\ndocument.addEventListener('DOMContentLoaded', () => {\n const graphViz = new GraphVisualizer('graphCanvas');\n \n // Add button event listeners\n document.getElementById('addNode').addEventListener('click', () => {\n graphViz.addNode();\n });\n\n document.getElementById('clear').addEventListener('click', () => {\n graphViz.nodes = [];\n graphViz.edges = [];\n graphViz.render();\n });\n\n // Add some initial nodes\n for (let i = 0; i < 5; i++) {\n graphViz.addNode();\n }\n});\n---end---" + } + ], + "stop_reason": "end_turn", + "stop_sequence": null, + "usage": { + "input_tokens": 818, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "output_tokens": 3053 + } +} \ No newline at end of file diff --git a/readme.scroll b/readme.scroll new file mode 100644 index 0000000..dad0429 --- /dev/null +++ b/readme.scroll @@ -0,0 +1,3 @@ +# viz2.scroll.pub + +website generated by Claude from prompt: graph viz \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..d30338c --- /dev/null +++ b/script.js @@ -0,0 +1,146 @@ +class GraphVisualizer { + constructor(canvasId) { + this.canvas = document.getElementById(canvasId); + this.ctx = this.canvas.getContext('2d'); + this.nodes = []; + this.edges = []; + this.isDragging = false; + this.selectedNode = null; + + this.initializeCanvas(); + this.addEventListeners(); + } + + initializeCanvas() { + this.resizeCanvas(); + window.addEventListener('resize', () => this.resizeCanvas()); + } + + resizeCanvas() { + const container = this.canvas.parentElement; + this.canvas.width = container.clientWidth; + this.canvas.height = container.clientHeight; + this.render(); + } + + addEventListeners() { + this.canvas.addEventListener('mousedown', (e) => this.handleMouseDown(e)); + this.canvas.addEventListener('mousemove', (e) => this.handleMouseMove(e)); + this.canvas.addEventListener('mouseup', () => this.handleMouseUp()); + this.canvas.addEventListener('touchstart', (e) => this.handleTouchStart(e)); + this.canvas.addEventListener('touchmove', (e) => this.handleTouchMove(e)); + this.canvas.addEventListener('touchend', () => this.handleTouchEnd()); + } + + addNode(x, y) { + const node = { + x: x || Math.random() * this.canvas.width, + y: y || Math.random() * this.canvas.height, + radius: 20, + color: `hsl(${Math.random() * 360}, 70%, 50%)` + }; + this.nodes.push(node); + this.render(); + } + + render() { + this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); + + // Draw edges + this.edges.forEach(edge => { + this.ctx.beginPath(); + this.ctx.moveTo(edge.start.x, edge.start.y); + this.ctx.lineTo(edge.end.x, edge.end.y); + this.ctx.strokeStyle = '#999'; + this.ctx.lineWidth = 2; + this.ctx.stroke(); + }); + + // Draw nodes + this.nodes.forEach(node => { + this.ctx.beginPath(); + this.ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2); + this.ctx.fillStyle = node.color; + this.ctx.fill(); + this.ctx.strokeStyle = '#fff'; + this.ctx.lineWidth = 3; + this.ctx.stroke(); + }); + } + + handleMouseDown(e) { + const rect = this.canvas.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + + this.selectedNode = this.nodes.find(node => { + const dx = node.x - x; + const dy = node.y - y; + return Math.sqrt(dx * dx + dy * dy) < node.radius; + }); + + if (this.selectedNode) { + this.isDragging = true; + } + } + + handleMouseMove(e) { + if (this.isDragging && this.selectedNode) { + const rect = this.canvas.getBoundingClientRect(); + this.selectedNode.x = e.clientX - rect.left; + this.selectedNode.y = e.clientY - rect.top; + this.render(); + } + } + + handleMouseUp() { + this.isDragging = false; + this.selectedNode = null; + } + + // Touch event handlers + handleTouchStart(e) { + e.preventDefault(); + const touch = e.touches[0]; + const mouseEvent = new MouseEvent('mousedown', { + clientX: touch.clientX, + clientY: touch.clientY + }); + this.handleMouseDown(mouseEvent); + } + + handleTouchMove(e) { + e.preventDefault(); + const touch = e.touches[0]; + const mouseEvent = new MouseEvent('mousemove', { + clientX: touch.clientX, + clientY: touch.clientY + }); + this.handleMouseMove(mouseEvent); + } + + handleTouchEnd() { + this.handleMouseUp(); + } +} + +// Initialize the application +document.addEventListener('DOMContentLoaded', () => { + const graphViz = new GraphVisualizer('graphCanvas'); + + // Add button event listeners + document.getElementById('addNode').addEventListener('click', () => { + graphViz.addNode(); + }); + + document.getElementById('clear').addEventListener('click', () => { + graphViz.nodes = []; + graphViz.edges = []; + graphViz.render(); + }); + + // Add some initial nodes + for (let i = 0; i < 5; i++) { + graphViz.addNode(); + } +}); \ No newline at end of file diff --git a/style.css b/style.css new file mode 100644 index 0000000..22a841e --- /dev/null +++ b/style.css @@ -0,0 +1,167 @@ +:root { + --primary-color: #2a6bd1; + --secondary-color: #1d4a94; + --background-color: #f8faff; + --text-color: #2c3e50; + --accent-color: #e74c3c; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', system-ui, sans-serif; + line-height: 1.6; + color: var(--text-color); + background: var(--background-color); +} + +.hero { + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + color: white; + padding: 2rem; + min-height: 60vh; + display: flex; + flex-direction: column; +} + +nav { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 0; +} + +.logo { + font-size: 1.8rem; + font-weight: bold; + background: linear-gradient(45deg, #fff, #e0e0e0); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + +.nav-links { + display: flex; + gap: 2rem; +} + +.nav-links a { + color: white; + text-decoration: none; + transition: all 0.3s ease; +} + +.nav-links a:hover { + transform: translateY(-2px); + text-shadow: 0 0 10px rgba(255,255,255,0.5); +} + +.hero-content { + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; + gap: 1.5rem; +} + +.hero-content h1 { + font-size: 3.5rem; + margin-bottom: 1rem; + text-shadow: 2px 2px 4px rgba(0,0,0,0.2); +} + +.graph-editor { + padding: 2rem; + background: white; + border-radius: 10px; + margin: 2rem auto; + max-width: 1200px; + box-shadow: 0 4px 6px rgba(0,0,0,0.1); +} + +.editor-container { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.controls { + display: flex; + gap: 1rem; +} + +button { + padding: 0.8rem 1.5rem; + border: none; + border-radius: 5px; + background: var(--primary-color); + color: white; + cursor: pointer; + transition: all 0.3s ease; +} + +button:hover { + background: var(--secondary-color); + transform: translateY(-2px); +} + +.canvas-container { + aspect-ratio: 16/9; + width: 100%; + background: #fafafa; + border-radius: 8px; + border: 2px solid #eee; +} + +.example-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 2rem; + padding: 2rem; +} + +.example-card { + background: white; + padding: 1.5rem; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); + transition: all 0.3s ease; +} + +.example-card:hover { + transform: translateY(-5px); + box-shadow: 0 5px 15px rgba(0,0,0,0.2); +} + +.mini-canvas { + width: 100%; + aspect-ratio: 1; + background: #fafafa; + border-radius: 4px; +} + +footer { + background: var(--secondary-color); + color: white; + padding: 2rem; + margin-top: 4rem; +} + +@media (max-width: 768px) { + .hero-content h1 { + font-size: 2.5rem; + } + + .nav-links { + display: none; + } + + .controls { + flex-wrap: wrap; + } +} \ No newline at end of file