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
/**
* This app allows users to drop an image onto the canvas, add text to it, move the text around,
* edit the text directly on the canvas, and save the result to their local disk.
* We'll use the HTML5 Canvas API for image manipulation and the File System Access API for saving files.
*/
/** @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 App() {
const [image, setImage] = useState(null);
const [text, setText] = useState("Enter text here");
const [textPosition, setTextPosition] = useState({ x: 250, y: 250 });
const [isDragging, setIsDragging] = useState(false);
const [canvasSize, setCanvasSize] = useState({ width: window.innerWidth, height: window.innerHeight });
const [textColor, setTextColor] = useState("#ffffff");
const [fontSize, setFontSize] = useState(30);
const [fontFamily, setFontFamily] = useState("Caveat");
const canvasRef = useRef(null);
useEffect(() => {
drawCanvas();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [image, text, textPosition, canvasSize, textColor, fontSize, fontFamily]);
const handleResize = () => {
if (!image) {
setCanvasSize({ width: window.innerWidth, height: window.innerHeight });
}
};
const drawCanvas = () => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (image) {
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
} else {
ctx.fillStyle = "#f0f0f0";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#999";
ctx.font = "20px Caveat";
ctx.textAlign = "center";
ctx.fillText("Drop an image here", canvas.width / 2, canvas.height / 2);
}
ctx.font = `${fontSize}px ${fontFamily}`;
ctx.fillStyle = textColor;
ctx.textAlign = "center";
ctx.fillText(text, textPosition.x, textPosition.y);
};
const handleCanvasMouseDown = (e) => {
const canvas = canvasRef.current;
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const textWidth = canvasRef.current.getContext("2d").measureText(text).width;
if (Math.abs(x - textPosition.x) < textWidth / 2 && Math.abs(y - textPosition.y) < fontSize / 2) {
setIsDragging(true);
} else {
setTextPosition({ x, y });
}
};
const handleCanvasMouseMove = (e) => {
if (isDragging) {
const canvas = canvasRef.current;
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
setTextPosition({ x, y });
}
};
const handleCanvasMouseUp = () => {
setIsDragging(false);
};
const handleKeyPress = (e) => {
e.preventDefault();
if (e.key === 'Backspace') {
setText(text.slice(0, -1));
} else if (e.key.length === 1) {
setText(text + e.key);
}
};
const handleDrop = (e) => {
e.preventDefault();
const file = e.dataTransfer.files[0];
if (file && file.type.startsWith('image/')) {
const reader = new FileReader();
reader.onload = (event) => {
const img = new Image();
img.onload = () => {
hasparus-czarkowyedytordat.web.val.run
August 24, 2024