commit 393716e918c77bc3926db226eca7a393cba38084
Author: ffff:12.186.22.250 <ffff:12.186.22.250@hub.scroll.pub>
Date: 2024-12-31 01:10:51 +0000
Subject: updated script.js
diff --git a/script.js b/script.js
index 4d87736..b40071c 100644
--- a/script.js
+++ b/script.js
@@ -68,7 +68,7 @@ class ParticleSystem {
});
document.getElementById("colorToggle").addEventListener("click", () => {
- this.colorMode = this.colorMode === "blue" ? "red" : "blue";
+ this.colorMode = this.colorMode === "blue" ? "rainbow" : "blue";
});
}
commit 342fcfd262f9083f7096233e71d512f27b872b52
Author: ffff:12.186.22.250 <ffff:12.186.22.250@hub.scroll.pub>
Date: 2024-12-31 01:10:41 +0000
Subject: updated script.js
diff --git a/script.js b/script.js
index f6ad1d5..4d87736 100644
--- a/script.js
+++ b/script.js
@@ -23,14 +23,14 @@ class Particle {
class ParticleSystem {
constructor() {
- this.canvas = document.getElementById('particleCanvas');
- this.ctx = this.canvas.getContext('2d');
+ this.canvas = document.getElementById("particleCanvas");
+ this.ctx = this.canvas.getContext("2d");
this.particles = [];
- this.colorMode = 'blue';
+ this.colorMode = "blue";
this.particleCount = 200;
this.speed = 5;
this.connectionRadius = 100;
-
+
this.resize();
this.init();
this.setupEventListeners();
@@ -50,29 +50,31 @@ class ParticleSystem {
}
setupEventListeners() {
- window.addEventListener('resize', () => this.resize());
-
- document.getElementById('particleCount').addEventListener('input', (e) => {
+ window.addEventListener("resize", () => this.resize());
+
+ document.getElementById("particleCount").addEventListener("input", (e) => {
this.particleCount = parseInt(e.target.value);
this.init();
});
-
- document.getElementById('particleSpeed').addEventListener('input', (e) => {
+
+ document.getElementById("particleSpeed").addEventListener("input", (e) => {
this.speed = parseInt(e.target.value);
});
-
- document.getElementById('connectionRadius').addEventListener('input', (e) => {
- this.connectionRadius = parseInt(e.target.value);
- });
-
- document.getElementById('colorToggle').addEventListener('click', () => {
- this.colorMode = this.colorMode === 'blue' ? 'rainbow' : 'blue';
+
+ document
+ .getElementById("connectionRadius")
+ .addEventListener("input", (e) => {
+ this.connectionRadius = parseInt(e.target.value);
+ });
+
+ document.getElementById("colorToggle").addEventListener("click", () => {
+ this.colorMode = this.colorMode === "blue" ? "red" : "blue";
});
}
getColor(distance) {
- if (this.colorMode === 'blue') {
- const alpha = 1 - (distance / this.connectionRadius);
+ if (this.colorMode === "blue") {
+ const alpha = 1 - distance / this.connectionRadius;
return `rgba(0, 159, 253, ${alpha})`;
} else {
const hue = (distance / this.connectionRadius) * 360;
@@ -82,16 +84,16 @@ class ParticleSystem {
draw() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
-
+
for (let i = 0; i < this.particles.length; i++) {
const p1 = this.particles[i];
-
+
for (let j = i + 1; j < this.particles.length; j++) {
const p2 = this.particles[j];
const dx = p1.x - p2.x;
const dy = p1.y - p2.y;
const distance = Math.sqrt(dx * dx + dy * dy);
-
+
if (distance < this.connectionRadius) {
this.ctx.beginPath();
this.ctx.strokeStyle = this.getColor(distance);
@@ -101,21 +103,21 @@ class ParticleSystem {
this.ctx.stroke();
}
}
-
+
this.ctx.beginPath();
- this.ctx.fillStyle = '#ffffff';
+ this.ctx.fillStyle = "#ffffff";
this.ctx.arc(p1.x, p1.y, p1.radius, 0, Math.PI * 2);
this.ctx.fill();
}
}
animate() {
- this.particles.forEach(p => p.update(this.speed));
+ this.particles.forEach((p) => p.update(this.speed));
this.draw();
requestAnimationFrame(() => this.animate());
}
}
-document.addEventListener('DOMContentLoaded', () => {
+document.addEventListener("DOMContentLoaded", () => {
new ParticleSystem();
-});
\ No newline at end of file
+});
commit cab0fa0d236bdebfcb43f26856eac2a90ffa9b77
Author: ffff:12.186.22.250 <ffff:12.186.22.250@hub.scroll.pub>
Date: 2024-12-31 01:10:13 +0000
Subject: updated body.html
diff --git a/body.html b/body.html
index c9d2808..990abdb 100644
--- a/body.html
+++ b/body.html
@@ -1,28 +1,34 @@
<main>
<canvas id="particleCanvas"></canvas>
-
+
<div class="controls">
<h1>Particle Symphony</h1>
-
+
<div class="control-group">
<label for="particleCount">Particle Count</label>
- <input type="range" id="particleCount" min="50" max="500" value="200">
+ <input type="range" id="particleCount" min="50" max="500" value="200" />
</div>
-
+
<div class="control-group">
<label for="particleSpeed">Speed</label>
- <input type="range" id="particleSpeed" min="1" max="10" value="5">
+ <input type="range" id="particleSpeed" min="1" max="10" value="5" />
</div>
-
+
<div class="control-group">
<label for="connectionRadius">Connection Radius</label>
- <input type="range" id="connectionRadius" min="50" max="200" value="100">
+ <input
+ type="range"
+ id="connectionRadius"
+ min="50"
+ max="200"
+ value="100"
+ />
</div>
-
+
<button id="colorToggle">Toggle Colors</button>
</div>
</main>
<footer>
- <p>Created with passion for interactive web experiences</p>
-</footer>
\ No newline at end of file
+ <p></p>
+</footer>
commit fe1a88d623b4369e6a2330456351a0fd4f15d60c
Author: root <root@hub.scroll.pub>
Date: 2024-12-31 01:09:21 +0000
Subject: Initial commit
diff --git a/body.html b/body.html
new file mode 100644
index 0000000..c9d2808
--- /dev/null
+++ b/body.html
@@ -0,0 +1,28 @@
+<main>
+ <canvas id="particleCanvas"></canvas>
+
+ <div class="controls">
+ <h1>Particle Symphony</h1>
+
+ <div class="control-group">
+ <label for="particleCount">Particle Count</label>
+ <input type="range" id="particleCount" min="50" max="500" value="200">
+ </div>
+
+ <div class="control-group">
+ <label for="particleSpeed">Speed</label>
+ <input type="range" id="particleSpeed" min="1" max="10" value="5">
+ </div>
+
+ <div class="control-group">
+ <label for="connectionRadius">Connection Radius</label>
+ <input type="range" id="connectionRadius" min="50" max="200" value="100">
+ </div>
+
+ <button id="colorToggle">Toggle Colors</button>
+ </div>
+</main>
+
+<footer>
+ <p>Created with passion for interactive web experiences</p>
+</footer>
\ No newline at end of file
diff --git a/index.scroll b/index.scroll
new file mode 100644
index 0000000..f487a37
--- /dev/null
+++ b/index.scroll
@@ -0,0 +1,8 @@
+buildHtml
+baseUrl https://particles.scroll.pub
+metaTags
+editButton /edit.html
+title Interactive Particle Symphony
+style.css
+body.html
+script.js
\ No newline at end of file
diff --git a/prompt.json b/prompt.json
new file mode 100644
index 0000000..09446d1
--- /dev/null
+++ b/prompt.json
@@ -0,0 +1,20 @@
+{
+ "id": "msg_01Uny8dhmaP52HcMtxpp4hUc",
+ "type": "message",
+ "role": "assistant",
+ "model": "claude-3-5-sonnet-20241022",
+ "content": [
+ {
+ "type": "text",
+ "text": "Let me create an interactive particle website with an elegant design.\n\n---domain---\nparticles.scroll.pub\n---index.scroll---\nbuildHtml\nbaseUrl https://particles.scroll.pub\nmetaTags\neditButton /edit.html\ntitle Interactive Particle Symphony\nstyle.css\nbody.html\nscript.js\n---body.html---\n<main>\n <canvas id=\"particleCanvas\"></canvas>\n \n <div class=\"controls\">\n <h1>Particle Symphony</h1>\n \n <div class=\"control-group\">\n <label for=\"particleCount\">Particle Count</label>\n <input type=\"range\" id=\"particleCount\" min=\"50\" max=\"500\" value=\"200\">\n </div>\n \n <div class=\"control-group\">\n <label for=\"particleSpeed\">Speed</label>\n <input type=\"range\" id=\"particleSpeed\" min=\"1\" max=\"10\" value=\"5\">\n </div>\n \n <div class=\"control-group\">\n <label for=\"connectionRadius\">Connection Radius</label>\n <input type=\"range\" id=\"connectionRadius\" min=\"50\" max=\"200\" value=\"100\">\n </div>\n \n <button id=\"colorToggle\">Toggle Colors</button>\n </div>\n</main>\n\n<footer>\n <p>Created with passion for interactive web experiences</p>\n</footer>\n---style.css---\n:root {\n --primary-color: #2a2a72;\n --secondary-color: #009ffd;\n --text-color: #ffffff;\n --control-bg: rgba(0, 0, 0, 0.7);\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: system-ui, -apple-system, sans-serif;\n background: var(--primary-color);\n color: var(--text-color);\n overflow: hidden;\n height: 100vh;\n}\n\ncanvas {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 1;\n}\n\n.controls {\n position: fixed;\n right: 2rem;\n top: 50%;\n transform: translateY(-50%);\n background: var(--control-bg);\n padding: 2rem;\n border-radius: 1rem;\n z-index: 2;\n backdrop-filter: blur(10px);\n box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);\n}\n\nh1 {\n font-size: 1.5rem;\n margin-bottom: 1.5rem;\n text-align: center;\n background: linear-gradient(45deg, var(--text-color), var(--secondary-color));\n -webkit-background-clip: text;\n background-clip: text;\n color: transparent;\n}\n\n.control-group {\n margin-bottom: 1.5rem;\n}\n\nlabel {\n display: block;\n margin-bottom: 0.5rem;\n font-size: 0.9rem;\n}\n\ninput[type=\"range\"] {\n width: 100%;\n background: var(--secondary-color);\n height: 6px;\n border-radius: 3px;\n appearance: none;\n outline: none;\n}\n\ninput[type=\"range\"]::-webkit-slider-thumb {\n appearance: none;\n width: 16px;\n height: 16px;\n background: var(--text-color);\n border-radius: 50%;\n cursor: pointer;\n transition: transform 0.2s;\n}\n\ninput[type=\"range\"]::-webkit-slider-thumb:hover {\n transform: scale(1.2);\n}\n\nbutton {\n width: 100%;\n padding: 0.8rem;\n background: var(--secondary-color);\n border: none;\n border-radius: 0.5rem;\n color: var(--text-color);\n font-weight: bold;\n cursor: pointer;\n transition: transform 0.2s, background 0.2s;\n}\n\nbutton:hover {\n transform: scale(1.05);\n background: #00b4ff;\n}\n\nfooter {\n position: fixed;\n bottom: 1rem;\n left: 0;\n width: 100%;\n text-align: center;\n z-index: 2;\n font-size: 0.9rem;\n opacity: 0.7;\n}\n\n@media (max-width: 768px) {\n .controls {\n right: 50%;\n transform: translateX(50%);\n bottom: 2rem;\n top: auto;\n width: 90%;\n max-width: 400px;\n }\n \n footer {\n display: none;\n }\n}\n---script.js---\nclass Particle {\n constructor(canvas) {\n this.canvas = canvas;\n this.reset();\n }\n\n reset() {\n this.x = Math.random() * this.canvas.width;\n this.y = Math.random() * this.canvas.height;\n this.vx = (Math.random() - 0.5) * 2;\n this.vy = (Math.random() - 0.5) * 2;\n this.radius = Math.random() * 2 + 1;\n }\n\n update(speed) {\n this.x += this.vx * speed;\n this.y += this.vy * speed;\n\n if (this.x < 0 || this.x > this.canvas.width) this.vx *= -1;\n if (this.y < 0 || this.y > this.canvas.height) this.vy *= -1;\n }\n}\n\nclass ParticleSystem {\n constructor() {\n this.canvas = document.getElementById('particleCanvas');\n this.ctx = this.canvas.getContext('2d');\n this.particles = [];\n this.colorMode = 'blue';\n this.particleCount = 200;\n this.speed = 5;\n this.connectionRadius = 100;\n \n this.resize();\n this.init();\n this.setupEventListeners();\n this.animate();\n }\n\n resize() {\n this.canvas.width = window.innerWidth;\n this.canvas.height = window.innerHeight;\n }\n\n init() {\n this.particles = [];\n for (let i = 0; i < this.particleCount; i++) {\n this.particles.push(new Particle(this.canvas));\n }\n }\n\n setupEventListeners() {\n window.addEventListener('resize', () => this.resize());\n \n document.getElementById('particleCount').addEventListener('input', (e) => {\n this.particleCount = parseInt(e.target.value);\n this.init();\n });\n \n document.getElementById('particleSpeed').addEventListener('input', (e) => {\n this.speed = parseInt(e.target.value);\n });\n \n document.getElementById('connectionRadius').addEventListener('input', (e) => {\n this.connectionRadius = parseInt(e.target.value);\n });\n \n document.getElementById('colorToggle').addEventListener('click', () => {\n this.colorMode = this.colorMode === 'blue' ? 'rainbow' : 'blue';\n });\n }\n\n getColor(distance) {\n if (this.colorMode === 'blue') {\n const alpha = 1 - (distance / this.connectionRadius);\n return `rgba(0, 159, 253, ${alpha})`;\n } else {\n const hue = (distance / this.connectionRadius) * 360;\n return `hsla(${hue}, 100%, 50%, ${1 - distance / this.connectionRadius})`;\n }\n }\n\n draw() {\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n \n for (let i = 0; i < this.particles.length; i++) {\n const p1 = this.particles[i];\n \n for (let j = i + 1; j < this.particles.length; j++) {\n const p2 = this.particles[j];\n const dx = p1.x - p2.x;\n const dy = p1.y - p2.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n \n if (distance < this.connectionRadius) {\n this.ctx.beginPath();\n this.ctx.strokeStyle = this.getColor(distance);\n this.ctx.lineWidth = 1;\n this.ctx.moveTo(p1.x, p1.y);\n this.ctx.lineTo(p2.x, p2.y);\n this.ctx.stroke();\n }\n }\n \n this.ctx.beginPath();\n this.ctx.fillStyle = '#ffffff';\n this.ctx.arc(p1.x, p1.y, p1.radius, 0, Math.PI * 2);\n this.ctx.fill();\n }\n }\n\n animate() {\n this.particles.forEach(p => p.update(this.speed));\n this.draw();\n requestAnimationFrame(() => this.animate());\n }\n}\n\ndocument.addEventListener('DOMContentLoaded', () => {\n new ParticleSystem();\n});\n---end---\n\nThis creates a beautiful, interactive particle system with the following features:\n\n1. Responsive canvas that fills the entire screen\n2. Elegant control panel with blur effect\n3. Adjustable parameters:\n - Particle count\n - Movement speed\n - Connection radius\n - Color mode toggle\n4. Smooth animations and transitions\n5. Mobile-responsive design\n6. Optimized performance\n7. Clean, modern aesthetic\n\nThe particles move naturally and create connections when they're close to each other. The connection lines' opacity changes based on distance, creating a dynamic, organic feel. The color toggle switches between a cool blue theme and a rainbow effect."
+ }
+ ],
+ "stop_reason": "end_turn",
+ "stop_sequence": null,
+ "usage": {
+ "input_tokens": 285,
+ "cache_creation_input_tokens": 0,
+ "cache_read_input_tokens": 0,
+ "output_tokens": 2531
+ }
+}
\ No newline at end of file
diff --git a/readme.scroll b/readme.scroll
new file mode 100644
index 0000000..5deea8e
--- /dev/null
+++ b/readme.scroll
@@ -0,0 +1,2 @@
+# particles3.scroll.pub
+Website generated by Claude from prompt: a particle website showing lots of particles with some cool controls and interactivity
\ No newline at end of file
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..f6ad1d5
--- /dev/null
+++ b/script.js
@@ -0,0 +1,121 @@
+class Particle {
+ constructor(canvas) {
+ this.canvas = canvas;
+ this.reset();
+ }
+
+ reset() {
+ this.x = Math.random() * this.canvas.width;
+ this.y = Math.random() * this.canvas.height;
+ this.vx = (Math.random() - 0.5) * 2;
+ this.vy = (Math.random() - 0.5) * 2;
+ this.radius = Math.random() * 2 + 1;
+ }
+
+ update(speed) {
+ this.x += this.vx * speed;
+ this.y += this.vy * speed;
+
+ if (this.x < 0 || this.x > this.canvas.width) this.vx *= -1;
+ if (this.y < 0 || this.y > this.canvas.height) this.vy *= -1;
+ }
+}
+
+class ParticleSystem {
+ constructor() {
+ this.canvas = document.getElementById('particleCanvas');
+ this.ctx = this.canvas.getContext('2d');
+ this.particles = [];
+ this.colorMode = 'blue';
+ this.particleCount = 200;
+ this.speed = 5;
+ this.connectionRadius = 100;
+
+ this.resize();
+ this.init();
+ this.setupEventListeners();
+ this.animate();
+ }
+
+ resize() {
+ this.canvas.width = window.innerWidth;
+ this.canvas.height = window.innerHeight;
+ }
+
+ init() {
+ this.particles = [];
+ for (let i = 0; i < this.particleCount; i++) {
+ this.particles.push(new Particle(this.canvas));
+ }
+ }
+
+ setupEventListeners() {
+ window.addEventListener('resize', () => this.resize());
+
+ document.getElementById('particleCount').addEventListener('input', (e) => {
+ this.particleCount = parseInt(e.target.value);
+ this.init();
+ });
+
+ document.getElementById('particleSpeed').addEventListener('input', (e) => {
+ this.speed = parseInt(e.target.value);
+ });
+
+ document.getElementById('connectionRadius').addEventListener('input', (e) => {
+ this.connectionRadius = parseInt(e.target.value);
+ });
+
+ document.getElementById('colorToggle').addEventListener('click', () => {
+ this.colorMode = this.colorMode === 'blue' ? 'rainbow' : 'blue';
+ });
+ }
+
+ getColor(distance) {
+ if (this.colorMode === 'blue') {
+ const alpha = 1 - (distance / this.connectionRadius);
+ return `rgba(0, 159, 253, ${alpha})`;
+ } else {
+ const hue = (distance / this.connectionRadius) * 360;
+ return `hsla(${hue}, 100%, 50%, ${1 - distance / this.connectionRadius})`;
+ }
+ }
+
+ draw() {
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+
+ for (let i = 0; i < this.particles.length; i++) {
+ const p1 = this.particles[i];
+
+ for (let j = i + 1; j < this.particles.length; j++) {
+ const p2 = this.particles[j];
+ const dx = p1.x - p2.x;
+ const dy = p1.y - p2.y;
+ const distance = Math.sqrt(dx * dx + dy * dy);
+
+ if (distance < this.connectionRadius) {
+ this.ctx.beginPath();
+ this.ctx.strokeStyle = this.getColor(distance);
+ this.ctx.lineWidth = 1;
+ this.ctx.moveTo(p1.x, p1.y);
+ this.ctx.lineTo(p2.x, p2.y);
+ this.ctx.stroke();
+ }
+ }
+
+ this.ctx.beginPath();
+ this.ctx.fillStyle = '#ffffff';
+ this.ctx.arc(p1.x, p1.y, p1.radius, 0, Math.PI * 2);
+ this.ctx.fill();
+ }
+ }
+
+ animate() {
+ this.particles.forEach(p => p.update(this.speed));
+ this.draw();
+ requestAnimationFrame(() => this.animate());
+ }
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ new ParticleSystem();
+});
\ No newline at end of file
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..6ca5299
--- /dev/null
+++ b/style.css
@@ -0,0 +1,126 @@
+:root {
+ --primary-color: #2a2a72;
+ --secondary-color: #009ffd;
+ --text-color: #ffffff;
+ --control-bg: rgba(0, 0, 0, 0.7);
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: system-ui, -apple-system, sans-serif;
+ background: var(--primary-color);
+ color: var(--text-color);
+ overflow: hidden;
+ height: 100vh;
+}
+
+canvas {
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 1;
+}
+
+.controls {
+ position: fixed;
+ right: 2rem;
+ top: 50%;
+ transform: translateY(-50%);
+ background: var(--control-bg);
+ padding: 2rem;
+ border-radius: 1rem;
+ z-index: 2;
+ backdrop-filter: blur(10px);
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
+}
+
+h1 {
+ font-size: 1.5rem;
+ margin-bottom: 1.5rem;
+ text-align: center;
+ background: linear-gradient(45deg, var(--text-color), var(--secondary-color));
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+}
+
+.control-group {
+ margin-bottom: 1.5rem;
+}
+
+label {
+ display: block;
+ margin-bottom: 0.5rem;
+ font-size: 0.9rem;
+}
+
+input[type="range"] {
+ width: 100%;
+ background: var(--secondary-color);
+ height: 6px;
+ border-radius: 3px;
+ appearance: none;
+ outline: none;
+}
+
+input[type="range"]::-webkit-slider-thumb {
+ appearance: none;
+ width: 16px;
+ height: 16px;
+ background: var(--text-color);
+ border-radius: 50%;
+ cursor: pointer;
+ transition: transform 0.2s;
+}
+
+input[type="range"]::-webkit-slider-thumb:hover {
+ transform: scale(1.2);
+}
+
+button {
+ width: 100%;
+ padding: 0.8rem;
+ background: var(--secondary-color);
+ border: none;
+ border-radius: 0.5rem;
+ color: var(--text-color);
+ font-weight: bold;
+ cursor: pointer;
+ transition: transform 0.2s, background 0.2s;
+}
+
+button:hover {
+ transform: scale(1.05);
+ background: #00b4ff;
+}
+
+footer {
+ position: fixed;
+ bottom: 1rem;
+ left: 0;
+ width: 100%;
+ text-align: center;
+ z-index: 2;
+ font-size: 0.9rem;
+ opacity: 0.7;
+}
+
+@media (max-width: 768px) {
+ .controls {
+ right: 50%;
+ transform: translateX(50%);
+ bottom: 2rem;
+ top: auto;
+ width: 90%;
+ max-width: 400px;
+ }
+
+ footer {
+ display: none;
+ }
+}
\ No newline at end of file