Changes to canvasplay.scroll.pub

root
root
25 days ago
Initial commit
body.html
Changed around line 1
+
+
+

Canvas Play

+

Create and manipulate 2D objects

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Your browser does not support the canvas element.
+
+
+
+

Instructions

+
    +
  • Click buttons to add shapes
  • +
  • Use arrow keys to move selected shape
  • +
  • Click a shape to select it
  • +
  • Press Delete to remove selected shape
  • +
    +
    +
    +
    +
    +

    Created with love by Canvas Play

    +
    index.scroll
    Changed around line 1
    + buildHtml
    + baseUrl https://canvasplay.scroll.pub
    + metaTags
    + editButton /edit.html
    + title Canvas Play - Interactive 2D Object Manipulator
    + style.css
    + body.html
    + script.js
    prompt.json
    Changed around line 1
    + {
    + "id": "msg_013gQGh6wysn88YpxAwbb6Jw",
    + "type": "message",
    + "role": "assistant",
    + "model": "claude-3-5-sonnet-20241022",
    + "content": [
    + {
    + "type": "text",
    + "text": "I'll create a website for creating and manipulating 2D objects. Let's call it \"Canvas Play\" - a simple, memorable name that describes its purpose.\n\n---domain---\ncanvasplay.scroll.pub\n\n---index.scroll---\nbuildHtml\nbaseUrl https://canvasplay.scroll.pub\nmetaTags\neditButton /edit.html\ntitle Canvas Play - Interactive 2D Object Manipulator\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n
    \n
    \n

    Canvas Play

    \n

    Create and manipulate 2D objects

    \n
    \n \n
    \n
    \n \n \n \n
    \n \n
    \n \n \n
    \n
    \n\n \n Your browser does not support the canvas element.\n \n\n
    \n

    Instructions

    \n
      \n
    • Click buttons to add shapes
    • \n
    • Use arrow keys to move selected shape
    • \n
    • Click a shape to select it
    • \n
    • Press Delete to remove selected shape
    • \n
    \n
    \n
    \n\n
    \n

    Created with love by Canvas Play

    \n
    \n\n---style.css---\n:root {\n --primary-color: #2c3e50;\n --accent-color: #3498db;\n --bg-color: #ecf0f1;\n --text-color: #2c3e50;\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 background: var(--bg-color);\n color: var(--text-color);\n line-height: 1.6;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n}\n\n.container {\n max-width: 1200px;\n margin: 0 auto;\n padding: 2rem;\n}\n\nheader {\n text-align: center;\n margin-bottom: 2rem;\n}\n\nh1 {\n font-size: 2.5rem;\n color: var(--primary-color);\n margin-bottom: 0.5rem;\n text-transform: uppercase;\n letter-spacing: 2px;\n}\n\n.controls {\n display: flex;\n gap: 2rem;\n justify-content: center;\n margin-bottom: 2rem;\n flex-wrap: wrap;\n}\n\nbutton {\n padding: 0.8rem 1.5rem;\n border: none;\n border-radius: 8px;\n background: var(--accent-color);\n color: white;\n cursor: pointer;\n transition: transform 0.2s, background 0.2s;\n}\n\nbutton:hover {\n background: #2980b9;\n transform: translateY(-2px);\n}\n\n#canvas {\n background: white;\n border-radius: 12px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n margin: 0 auto;\n display: block;\n max-width: 100%;\n height: auto;\n}\n\n.instructions {\n margin-top: 2rem;\n padding: 1.5rem;\n background: white;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n\n.instructions h2 {\n margin-bottom: 1rem;\n color: var(--primary-color);\n}\n\n.instructions ul {\n list-style-position: inside;\n color: #666;\n}\n\nfooter {\n margin-top: auto;\n padding: 1rem;\n text-align: center;\n background: var(--primary-color);\n color: white;\n}\n\n@media (max-width: 768px) {\n .container {\n padding: 1rem;\n }\n \n h1 {\n font-size: 2rem;\n }\n \n .controls {\n flex-direction: column;\n align-items: center;\n }\n}\n\n---script.js---\nclass Shape {\n constructor(type, x, y, size, color) {\n this.type = type;\n this.x = x;\n this.y = y;\n this.size = size;\n this.color = color;\n this.selected = false;\n }\n\n draw(ctx) {\n ctx.fillStyle = this.color;\n ctx.strokeStyle = this.selected ? '#2ecc71' : this.color;\n ctx.lineWidth = 3;\n\n switch(this.type) {\n case 'rectangle':\n ctx.fillRect(this.x, this.y, this.size, this.size);\n if (this.selected) {\n ctx.strokeRect(this.x, this.y, this.size, this.size);\n }\n break;\n case 'circle':\n ctx.beginPath();\n ctx.arc(this.x + this.size/2, this.y + this.size/2, this.size/2, 0, Math.PI * 2);\n ctx.fill();\n if (this.selected) {\n ctx.stroke();\n }\n break;\n case 'triangle':\n ctx.beginPath();\n ctx.moveTo(this.x + this.size/2, this.y);\n ctx.lineTo(this.x + this.size, this.y + this.size);\n ctx.lineTo(this.x, this.y + this.size);\n ctx.closePath();\n ctx.fill();\n if (this.selected) {\n ctx.stroke();\n }\n break;\n }\n }\n\n containsPoint(x, y) {\n if (this.type === 'rectangle') {\n return x >= this.x && x <= this.x + this.size &&\n y >= this.y && y <= this.y + this.size;\n } else if (this.type === 'circle') {\n const dx = x - (this.x + this.size/2);\n const dy = y - (this.y + this.size/2);\n return dx * dx + dy * dy <= (this.size/2) * (this.size/2);\n } else if (this.type === 'triangle') {\n // Simple bounding box check for triangle\n return x >= this.x && x <= this.x + this.size &&\n y >= this.y && y <= this.y + this.size;\n }\n return false;\n }\n}\n\ndocument.addEventListener('DOMContentLoaded', () => {\n const canvas = document.getElementById('canvas');\n const ctx = canvas.getContext('2d');\n const shapes = [];\n let selectedShape = null;\n\n // Set canvas size\n function resizeCanvas() {\n canvas.width = Math.min(800, window.innerWidth - 40);\n canvas.height = Math.min(600, window.innerHeight - 200);\n }\n resizeCanvas();\n window.addEventListener('resize', resizeCanvas);\n\n function draw() {\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n shapes.forEach(shape => shape.draw(ctx));\n }\n\n function addShape(type) {\n const color = document.getElementById('colorPicker').value;\n const size = parseInt(document.getElementById('sizeSlider').value);\n const x = canvas.width/2 - size/2;\n const y = canvas.height/2 - size/2;\n \n const shape = new Shape(type, x, y, size, color);\n shapes.push(shape);\n selectedShape = shape;\n shapes.forEach(s => s.selected = (s === selectedShape));\n draw();\n }\n\n document.getElementById('addRectangle').addEventListener('click', () => addShape('rectangle'));\n document.getElementById('addCircle').addEventListener('click', () => addShape('circle'));\n document.getElementById('addTriangle').addEventListener('click', () => addShape('triangle'));\n\n canvas.addEventListener('click', (e) => {\n const rect = canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n selectedShape = null;\n for (let i = shapes.length - 1; i >= 0; i--) {\n if (shapes[i].containsPoint(x, y)) {\n selectedShape = shapes[i];\n break;\n }\n }\n\n shapes.forEach(shape => shape.selected = (shape === selectedShape));\n draw();\n });\n\n document.addEventListener('keydown', (e) => {\n if (!selectedShape) return;\n\n const step = 10;\n switch(e.key) {\n case 'ArrowLeft':\n selectedShape.x -= step;\n break;\n case 'ArrowRight':\n selectedShape.x += step;\n break;\n case 'ArrowUp':\n selectedShape.y -= step;\n break;\n case 'ArrowDown':\n selectedShape.y += step;\n break;\n case 'Delete':\n const index = shapes.indexOf(selectedShape);\n if (index > -1) {\n shapes.splice(index, 1);\n selectedShape = null;\n }\n break;\n }\n draw();\n });\n\n draw();\n});\n\n---end---\n\nThis website provides a canvas-based interface for creating and manipulating 2D shapes. Users can:\n1. Add rectangles, circles, and triangles\n2. Select colors and sizes\n3. Move shapes with arrow keys\n4. Select shapes by clicking\n5. Delete shapes with the Delete key\n\nThe design is clean and modern, with smooth animations and a responsive layout that works well on both desktop and mobile devices. The code follows best practices for accessibility and performance, using semantic HTML and proper ARIA labels where needed.\n\nThe interface is intuitive and user-friendly, with clear instructions and visual feedback for user interactions. The color scheme is professional and pleasing to the eye, with subtle shadows and transitions that add polish without being overwhelming."
    + }
    + ],
    + "stop_reason": "end_turn",
    + "stop_sequence": null,
    + "usage": {
    + "input_tokens": 299,
    + "cache_creation_input_tokens": 0,
    + "cache_read_input_tokens": 0,
    + "output_tokens": 2749
    + }
    + }
    readme.scroll
    Changed around line 1
    + # canvasplay.scroll.pub
    + Website generated by Claude from prompt: make a website where you can make and add an 2d objects and manuiplate it and using arrow keys you can move it around
    script.js
    Changed around line 1
    + class Shape {
    + constructor(type, x, y, size, color) {
    + this.type = type;
    + this.x = x;
    + this.y = y;
    + this.size = size;
    + this.color = color;
    + this.selected = false;
    + }
    +
    + draw(ctx) {
    + ctx.fillStyle = this.color;
    + ctx.strokeStyle = this.selected ? '#2ecc71' : this.color;
    + ctx.lineWidth = 3;
    +
    + switch(this.type) {
    + case 'rectangle':
    + ctx.fillRect(this.x, this.y, this.size, this.size);
    + if (this.selected) {
    + ctx.strokeRect(this.x, this.y, this.size, this.size);
    + }
    + break;
    + case 'circle':
    + ctx.beginPath();
    + ctx.arc(this.x + this.size/2, this.y + this.size/2, this.size/2, 0, Math.PI * 2);
    + ctx.fill();
    + if (this.selected) {
    + ctx.stroke();
    + }
    + break;
    + case 'triangle':
    + ctx.beginPath();
    + ctx.moveTo(this.x + this.size/2, this.y);
    + ctx.lineTo(this.x + this.size, this.y + this.size);
    + ctx.lineTo(this.x, this.y + this.size);
    + ctx.closePath();
    + ctx.fill();
    + if (this.selected) {
    + ctx.stroke();
    + }
    + break;
    + }
    + }
    +
    + containsPoint(x, y) {
    + if (this.type === 'rectangle') {
    + return x >= this.x && x <= this.x + this.size &&
    + y >= this.y && y <= this.y + this.size;
    + } else if (this.type === 'circle') {
    + const dx = x - (this.x + this.size/2);
    + const dy = y - (this.y + this.size/2);
    + return dx * dx + dy * dy <= (this.size/2) * (this.size/2);
    + } else if (this.type === 'triangle') {
    + // Simple bounding box check for triangle
    + return x >= this.x && x <= this.x + this.size &&
    + y >= this.y && y <= this.y + this.size;
    + }
    + return false;
    + }
    + }
    +
    + document.addEventListener('DOMContentLoaded', () => {
    + const canvas = document.getElementById('canvas');
    + const ctx = canvas.getContext('2d');
    + const shapes = [];
    + let selectedShape = null;
    +
    + // Set canvas size
    + function resizeCanvas() {
    + canvas.width = Math.min(800, window.innerWidth - 40);
    + canvas.height = Math.min(600, window.innerHeight - 200);
    + }
    + resizeCanvas();
    + window.addEventListener('resize', resizeCanvas);
    +
    + function draw() {
    + ctx.clearRect(0, 0, canvas.width, canvas.height);
    + shapes.forEach(shape => shape.draw(ctx));
    + }
    +
    + function addShape(type) {
    + const color = document.getElementById('colorPicker').value;
    + const size = parseInt(document.getElementById('sizeSlider').value);
    + const x = canvas.width/2 - size/2;
    + const y = canvas.height/2 - size/2;
    +
    + const shape = new Shape(type, x, y, size, color);
    + shapes.push(shape);
    + selectedShape = shape;
    + shapes.forEach(s => s.selected = (s === selectedShape));
    + draw();
    + }
    +
    + document.getElementById('addRectangle').addEventListener('click', () => addShape('rectangle'));
    + document.getElementById('addCircle').addEventListener('click', () => addShape('circle'));
    + document.getElementById('addTriangle').addEventListener('click', () => addShape('triangle'));
    +
    + canvas.addEventListener('click', (e) => {
    + const rect = canvas.getBoundingClientRect();
    + const x = e.clientX - rect.left;
    + const y = e.clientY - rect.top;
    +
    + selectedShape = null;
    + for (let i = shapes.length - 1; i >= 0; i--) {
    + if (shapes[i].containsPoint(x, y)) {
    + selectedShape = shapes[i];
    + break;
    + }
    + }
    +
    + shapes.forEach(shape => shape.selected = (shape === selectedShape));
    + draw();
    + });
    +
    + document.addEventListener('keydown', (e) => {
    + if (!selectedShape) return;
    +
    + const step = 10;
    + switch(e.key) {
    + case 'ArrowLeft':
    + selectedShape.x -= step;
    + break;
    + case 'ArrowRight':
    + selectedShape.x += step;
    + break;
    + case 'ArrowUp':
    + selectedShape.y -= step;
    + break;
    + case 'ArrowDown':
    + selectedShape.y += step;
    + break;
    + case 'Delete':
    + const index = shapes.indexOf(selectedShape);
    + if (index > -1) {
    + shapes.splice(index, 1);
    + selectedShape = null;
    + }
    + break;
    + }
    + draw();
    + });
    +
    + draw();
    + });
    style.css
    Changed around line 1
    + :root {
    + --primary-color: #2c3e50;
    + --accent-color: #3498db;
    + --bg-color: #ecf0f1;
    + --text-color: #2c3e50;
    + }
    +
    + * {
    + margin: 0;
    + padding: 0;
    + box-sizing: border-box;
    + }
    +
    + body {
    + font-family: 'Segoe UI', system-ui, sans-serif;
    + background: var(--bg-color);
    + color: var(--text-color);
    + line-height: 1.6;
    + min-height: 100vh;
    + display: flex;
    + flex-direction: column;
    + }
    +
    + .container {
    + max-width: 1200px;
    + margin: 0 auto;
    + padding: 2rem;
    + }
    +
    + header {
    + text-align: center;
    + margin-bottom: 2rem;
    + }
    +
    + h1 {
    + font-size: 2.5rem;
    + color: var(--primary-color);
    + margin-bottom: 0.5rem;
    + text-transform: uppercase;
    + letter-spacing: 2px;
    + }
    +
    + .controls {
    + display: flex;
    + gap: 2rem;
    + justify-content: center;
    + margin-bottom: 2rem;
    + flex-wrap: wrap;
    + }
    +
    + button {
    + padding: 0.8rem 1.5rem;
    + border: none;
    + border-radius: 8px;
    + background: var(--accent-color);
    + color: white;
    + cursor: pointer;
    + transition: transform 0.2s, background 0.2s;
    + }
    +
    + button:hover {
    + background: #2980b9;
    + transform: translateY(-2px);
    + }
    +
    + #canvas {
    + background: white;
    + border-radius: 12px;
    + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    + margin: 0 auto;
    + display: block;
    + max-width: 100%;
    + height: auto;
    + }
    +
    + .instructions {
    + margin-top: 2rem;
    + padding: 1.5rem;
    + background: white;
    + border-radius: 8px;
    + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    + }
    +
    + .instructions h2 {
    + margin-bottom: 1rem;
    + color: var(--primary-color);
    + }
    +
    + .instructions ul {
    + list-style-position: inside;
    + color: #666;
    + }
    +
    + footer {
    + margin-top: auto;
    + padding: 1rem;
    + text-align: center;
    + background: var(--primary-color);
    + color: white;
    + }
    +
    + @media (max-width: 768px) {
    + .container {
    + padding: 1rem;
    + }
    +
    + h1 {
    + font-size: 2rem;
    + }
    +
    + .controls {
    + flex-direction: column;
    + align-items: center;
    + }
    + }