Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/** @jsxImportSource https://esm.sh/react */
import React, { useState, useRef, useEffect } from "https://esm.sh/react";
import { createRoot } from "https://esm.sh/react-dom/client";
function PotteryPlate({ radius, color, wobbliness, wobbleFrequency, wobbleIrregularity, rotation }) {
const points = [];
const centerX = 250;
const centerY = 250;
const numPoints = 180;
const irregularities = Array.from({ length: wobbleFrequency }, () => Math.random() * 2 * Math.PI);
for (let i = 0; i < numPoints; i++) {
const angle = (i / numPoints) * 2 * Math.PI;
let noise = 0;
for (let j = 0; j < wobbleFrequency; j++) {
const irregularAngle = (angle + irregularities[j] * wobbleIrregularity) % (2 * Math.PI);
noise += Math.sin(irregularAngle * wobbleFrequency) * (wobbliness / wobbleFrequency);
}
const r = radius + noise;
const x = r * Math.cos(angle);
const y = r * Math.sin(angle);
points.push(`${x},${y}`);
}
return (
<g transform={`translate(${centerX}, ${centerY}) rotate(${rotation})`}>
<path
d={`M ${points.join(" L ")} Z`}
fill={color}
stroke={color}
strokeWidth="2"
/>
</g>
);
}
function App() {
const [plate, setPlate] = useState(null);
const [svgString, setSvgString] = useState('');
const svgRef = useRef(null);
const textAreaRef = useRef(null);
const addPlate = () => {
const newPlate = {
radius: 140 + Math.random() * 20,
color: `hsl(${Math.random() * 360}, 70%, 75%)`,
wobbliness: Math.random() * 15,
wobbleFrequency: Math.floor(Math.random() * 8) + 2,
wobbleIrregularity: Math.random(),
rotation: Math.floor(Math.random() * 360),
};
setPlate(newPlate);
};
useEffect(() => {
if (svgRef.current && plate) {
const svgString = new XMLSerializer().serializeToString(svgRef.current);
setSvgString(svgString);
}
}, [plate]);
const copySVG = () => {
if (!textAreaRef.current) return;
textAreaRef.current.select();
try {
document.execCommand('copy');
// alert('SVG code copied to clipboard! You can now paste it elsewhere.');
} catch (err) {
// alert('Failed to copy SVG code. Please manually select and copy the text in the textarea.');
}
};
const updatePlate = (key, value) => {
if (plate) {
setPlate({...plate, [key]: value});
}
};
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100 p-4">
<div className="bg-white rounded-lg shadow-md p-8 max-w-2xl w-full">
<h1 className="text-3xl font-bold mb-4 text-center">Wobble Shape Generator</h1>
<div className="flex justify-center space-x-4 mb-4">
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" onClick={addPlate}>New Plate</button>
<button className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded" onClick={copySVG}>Copy SVG</button>
</div>
{plate && (
<div className="space-y-4">
<div className="flex items-center">
<label htmlFor="color" className="w-32 text-right mr-2">Color: </label>
<input
type="color"
id="color"
value={plate.color}
onChange={(e) => updatePlate('color', e.target.value)}
className="w-16 h-8"
/>
</div>
{['wobbliness', 'wobbleFrequency', 'wobbleIrregularity', 'rotation'].map((prop) => (
yawnxyz-wobbleshapes.web.val.run
September 16, 2024