init idk
This commit is contained in:
68
src/App.css
Normal file
68
src/App.css
Normal file
@@ -0,0 +1,68 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 4rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.canvas {
|
||||
height: 256px;
|
||||
width: 296px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.vertical {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 256px;
|
||||
}
|
||||
|
||||
.horizontal {
|
||||
width: 296px;
|
||||
margin-left: -30px;
|
||||
|
||||
}
|
||||
|
||||
.settings {
|
||||
color: white;
|
||||
font-family: "YurukaStd";
|
||||
margin: 1.5rem 0 1.5rem 0;
|
||||
}
|
||||
|
||||
.settings > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.picker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 2rem;
|
||||
font-family: "YurukaStd";
|
||||
}
|
||||
|
||||
.footer > a {
|
||||
color: rgb(199, 199, 199);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer > a:hover {
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
151
src/App.jsx
Normal file
151
src/App.jsx
Normal file
@@ -0,0 +1,151 @@
|
||||
import "./App.css";
|
||||
import Canvas from "./components/Canvas";
|
||||
import { useState, useEffect } from "react";
|
||||
import characters from "./characters.json";
|
||||
import Slider from "@mui/material/Slider";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import Button from "@mui/material/Button";
|
||||
import Picker from "./components/Picker";
|
||||
|
||||
function App() {
|
||||
const [character, setCharacter] = useState(49);
|
||||
const [text, setText] = useState(characters[character].defaultText.text);
|
||||
const [position, setPosition] = useState({
|
||||
x: characters[character].defaultText.x,
|
||||
y: characters[character].defaultText.y,
|
||||
});
|
||||
const [fontSize, setFontSize] = useState(characters[character].defaultText.s);
|
||||
const [rotate, setRotate] = useState(characters[character].defaultText.r);
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
const img = new Image();
|
||||
|
||||
useEffect(() => {
|
||||
setText(characters[character].defaultText.text);
|
||||
setPosition({
|
||||
x: characters[character].defaultText.x,
|
||||
y: characters[character].defaultText.y,
|
||||
});
|
||||
setRotate(characters[character].defaultText.r);
|
||||
setFontSize(characters[character].defaultText.s);
|
||||
setLoaded(false);
|
||||
}, [character]);
|
||||
|
||||
img.src = "/img/" + characters[character].img;
|
||||
|
||||
img.onload = () => {
|
||||
setLoaded(true);
|
||||
};
|
||||
|
||||
const draw = (ctx) => {
|
||||
ctx.canvas.width = 296;
|
||||
ctx.canvas.height = 256;
|
||||
|
||||
if (loaded && document.fonts.check("12px YurukaStd")) {
|
||||
ctx.drawImage(img, 0, 0, 296, 256);
|
||||
ctx.font = `${fontSize}px YurukaStd`;
|
||||
ctx.lineWidth = 9;
|
||||
ctx.save();
|
||||
|
||||
ctx.translate(position.x, position.y);
|
||||
ctx.rotate(rotate / 10);
|
||||
ctx.textAlign = "center";
|
||||
ctx.strokeStyle = "white";
|
||||
ctx.strokeText(text, 0, 0);
|
||||
ctx.fillStyle = characters[character].color;
|
||||
ctx.fillText(text, 0, 0);
|
||||
ctx.restore();
|
||||
}
|
||||
};
|
||||
|
||||
const download = () => {
|
||||
const canvas = document.getElementsByTagName("canvas")[0];
|
||||
const link = document.createElement("a");
|
||||
link.download = `${characters[character].name}_st.ayaka.one.png`;
|
||||
link.href = canvas.toDataURL();
|
||||
link.click();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<div className="container">
|
||||
<div className="vertical">
|
||||
<div className="canvas">
|
||||
<Canvas draw={draw} />
|
||||
</div>
|
||||
<Slider
|
||||
value={256 - position.y}
|
||||
onChange={(e, v) => setPosition({ ...position, y: 256 - v })}
|
||||
min={0}
|
||||
max={256}
|
||||
step={1}
|
||||
orientation="vertical"
|
||||
track={false}
|
||||
color="secondary"
|
||||
/>
|
||||
</div>
|
||||
<div className="horizontal">
|
||||
<Slider
|
||||
value={position.x}
|
||||
onChange={(e, v) => setPosition({ ...position, x: v })}
|
||||
min={0}
|
||||
max={296}
|
||||
step={1}
|
||||
track={false}
|
||||
color="secondary"
|
||||
/>
|
||||
<div className="settings">
|
||||
<div>
|
||||
<label>Rotate: </label>
|
||||
<Slider
|
||||
value={rotate}
|
||||
onChange={(e, v) => setRotate(v)}
|
||||
min={-10}
|
||||
max={10}
|
||||
step={1}
|
||||
track={false}
|
||||
color="secondary"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label>
|
||||
<nobr>Font size: </nobr>
|
||||
</label>
|
||||
<Slider
|
||||
value={fontSize}
|
||||
onChange={(e, v) => setFontSize(v)}
|
||||
min={10}
|
||||
max={100}
|
||||
step={1}
|
||||
track={false}
|
||||
color="secondary"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text">
|
||||
<TextField
|
||||
label="Text"
|
||||
size="small"
|
||||
color="secondary"
|
||||
value={text}
|
||||
fullWidth
|
||||
onChange={(e) => setText(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="picker">
|
||||
<Picker setCharacter={setCharacter} />
|
||||
<Button color="secondary" onClick={download}>
|
||||
download
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer">
|
||||
<a href="https://github.com/theoriginalayaka/sekai-stickers">
|
||||
GitHub
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
913
src/characters.json
Normal file
913
src/characters.json
Normal file
@@ -0,0 +1,913 @@
|
||||
[
|
||||
{
|
||||
"id": "3",
|
||||
"name": "Airi 01",
|
||||
"character": "airi",
|
||||
"img": "airi/Airi_01.png",
|
||||
"color": "#FB8AAC",
|
||||
"defaultText": {
|
||||
"text": "keep up",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"name": "Airi 02",
|
||||
"character": "airi",
|
||||
"img": "airi/Airi_02.png",
|
||||
"color": "#FB8AAC",
|
||||
"defaultText": {
|
||||
"text": "nice to meet ya",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": 0,
|
||||
"s": 28
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"name": "Airi 03",
|
||||
"character": "airi",
|
||||
"img": "airi/Airi_03.png",
|
||||
"color": "#FB8AAC",
|
||||
"defaultText": {
|
||||
"text": "keep at it!",
|
||||
"x": 140,
|
||||
"y": 79,
|
||||
"r": 2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"name": "Airi 04",
|
||||
"character": "airi",
|
||||
"img": "airi/Airi_04.png",
|
||||
"color": "#FB8AAC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "8",
|
||||
"name": "Airi 06",
|
||||
"character": "airi",
|
||||
"img": "airi/Airi_06.png",
|
||||
"color": "#FB8AAC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "9",
|
||||
"name": "Airi 07",
|
||||
"character": "airi",
|
||||
"img": "airi/Airi_07.png",
|
||||
"color": "#FB8AAC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "10",
|
||||
"name": "Airi 08",
|
||||
"character": "airi",
|
||||
"img": "airi/Airi_08.png",
|
||||
"color": "#FB8AAC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "11",
|
||||
"name": "Airi 09",
|
||||
"character": "airi",
|
||||
"img": "airi/Airi_09.png",
|
||||
"color": "#FB8AAC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "13",
|
||||
"name": "Airi 11",
|
||||
"character": "airi",
|
||||
"img": "airi/Airi_11.png",
|
||||
"color": "#FB8AAC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "14",
|
||||
"name": "Airi 12",
|
||||
"character": "airi",
|
||||
"img": "airi/Airi_12.png",
|
||||
"color": "#FB8AAC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "15",
|
||||
"name": "Airi 13",
|
||||
"character": "airi",
|
||||
"img": "airi/Airi_13.png",
|
||||
"color": "#FB8AAC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "16",
|
||||
"name": "Airi 14",
|
||||
"character": "airi",
|
||||
"img": "airi/Airi_14.png",
|
||||
"color": "#FB8AAC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "18",
|
||||
"name": "Airi 16",
|
||||
"character": "airi",
|
||||
"img": "airi/Airi_16.png",
|
||||
"color": "#FB8AAC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "19",
|
||||
"name": "Akito 01",
|
||||
"character": "akito",
|
||||
"img": "akito/Akito_01.png",
|
||||
"color": "#FF7722",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "20",
|
||||
"name": "Akito 02",
|
||||
"character": "akito",
|
||||
"img": "akito/Akito_02.png",
|
||||
"color": "#FF7722",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "21",
|
||||
"name": "Akito 03",
|
||||
"character": "akito",
|
||||
"img": "akito/Akito_03.png",
|
||||
"color": "#FF7722",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "22",
|
||||
"name": "Akito 04",
|
||||
"character": "akito",
|
||||
"img": "akito/Akito_04.png",
|
||||
"color": "#FF7722",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "24",
|
||||
"name": "Akito 06",
|
||||
"character": "akito",
|
||||
"img": "akito/Akito_06.png",
|
||||
"color": "#FF7722",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "25",
|
||||
"name": "Akito 07",
|
||||
"character": "akito",
|
||||
"img": "akito/Akito_07.png",
|
||||
"color": "#FF7722",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "26",
|
||||
"name": "Akito 08",
|
||||
"character": "akito",
|
||||
"img": "akito/Akito_08.png",
|
||||
"color": "#FF7722",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "27",
|
||||
"name": "Akito 09",
|
||||
"character": "akito",
|
||||
"img": "akito/Akito_09.png",
|
||||
"color": "#FF7722",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "29",
|
||||
"name": "Akito 11",
|
||||
"character": "akito",
|
||||
"img": "akito/Akito_11.png",
|
||||
"color": "#FF7722",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "30",
|
||||
"name": "Akito 12",
|
||||
"character": "akito",
|
||||
"img": "akito/Akito_12.png",
|
||||
"color": "#FF7722",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "31",
|
||||
"name": "Akito 13",
|
||||
"character": "akito",
|
||||
"img": "akito/Akito_13.png",
|
||||
"color": "#FF7722",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "32",
|
||||
"name": "Akito 14",
|
||||
"character": "akito",
|
||||
"img": "akito/Akito_14.png",
|
||||
"color": "#FF7722",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "33",
|
||||
"name": "Akito 16",
|
||||
"character": "akito",
|
||||
"img": "akito/Akito_16.png",
|
||||
"color": "#FF7722",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "34",
|
||||
"name": "An 01",
|
||||
"character": "an",
|
||||
"img": "an/An_01.png",
|
||||
"color": "#00BADC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "35",
|
||||
"name": "An 02",
|
||||
"character": "an",
|
||||
"img": "an/An_02.png",
|
||||
"color": "#00BADC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "36",
|
||||
"name": "An 03",
|
||||
"character": "an",
|
||||
"img": "an/An_03.png",
|
||||
"color": "#00BADC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "37",
|
||||
"name": "An 04",
|
||||
"character": "an",
|
||||
"img": "an/An_04.png",
|
||||
"color": "#00BADC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "39",
|
||||
"name": "An 06",
|
||||
"character": "an",
|
||||
"img": "an/An_06.png",
|
||||
"color": "#00BADC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "40",
|
||||
"name": "An 07",
|
||||
"character": "an",
|
||||
"img": "an/An_07.png",
|
||||
"color": "#00BADC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "41",
|
||||
"name": "An 08",
|
||||
"character": "an",
|
||||
"img": "an/An_08.png",
|
||||
"color": "#00BADC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "42",
|
||||
"name": "An 09",
|
||||
"character": "an",
|
||||
"img": "an/An_09.png",
|
||||
"color": "#00BADC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "44",
|
||||
"name": "An 11",
|
||||
"character": "an",
|
||||
"img": "an/An_11.png",
|
||||
"color": "#00BADC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "45",
|
||||
"name": "An 12",
|
||||
"character": "an",
|
||||
"img": "an/An_12.png",
|
||||
"color": "#00BADC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "46",
|
||||
"name": "An 13",
|
||||
"character": "an",
|
||||
"img": "an/An_13.png",
|
||||
"color": "#00BADC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "47",
|
||||
"name": "An 14",
|
||||
"character": "an",
|
||||
"img": "an/An_14.png",
|
||||
"color": "#00BADC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "49",
|
||||
"name": "An 16",
|
||||
"character": "an",
|
||||
"img": "an/An_16.png",
|
||||
"color": "#00BADC",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "50",
|
||||
"name": "Emu 01",
|
||||
"character": "emu",
|
||||
"img": "emu/Emu_01.png",
|
||||
"color": "#FF66BB",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "51",
|
||||
"name": "Emu 02",
|
||||
"character": "emu",
|
||||
"img": "emu/Emu_02.png",
|
||||
"color": "#FF66BB",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "52",
|
||||
"name": "Emu 03",
|
||||
"character": "emu",
|
||||
"img": "emu/Emu_03.png",
|
||||
"color": "#FF66BB",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "53",
|
||||
"name": "Emu 04",
|
||||
"character": "emu",
|
||||
"img": "emu/Emu_04.png",
|
||||
"color": "#FF66BB",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "55",
|
||||
"name": "Emu 06",
|
||||
"character": "emu",
|
||||
"img": "emu/Emu_06.png",
|
||||
"color": "#FF66BB",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "56",
|
||||
"name": "Emu 07",
|
||||
"character": "emu",
|
||||
"img": "emu/Emu_07.png",
|
||||
"color": "#FF66BB",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "57",
|
||||
"name": "Emu 08",
|
||||
"character": "emu",
|
||||
"img": "emu/Emu_08.png",
|
||||
"color": "#FF66BB",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "58",
|
||||
"name": "Emu 09",
|
||||
"character": "emu",
|
||||
"img": "emu/Emu_09.png",
|
||||
"color": "#FF66BB",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "60",
|
||||
"name": "Emu 11",
|
||||
"character": "emu",
|
||||
"img": "emu/Emu_11.png",
|
||||
"color": "#FF66BB",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "61",
|
||||
"name": "Emu 12",
|
||||
"character": "emu",
|
||||
"img": "emu/Emu_12.png",
|
||||
"color": "#FF66BB",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "62",
|
||||
"name": "Emu 13",
|
||||
"character": "emu",
|
||||
"img": "emu/Emu_13.png",
|
||||
"color": "#FF66BB",
|
||||
"defaultText": {
|
||||
"text": "Wonderhoy!",
|
||||
"x": 148,
|
||||
"y": 70,
|
||||
"r": -2,
|
||||
"s": 38
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "63",
|
||||
"name": "Emu 14",
|
||||
"character": "emu",
|
||||
"img": "emu/Emu_14.png",
|
||||
"color": "#FF66BB",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "65",
|
||||
"name": "Emu 16",
|
||||
"character": "emu",
|
||||
"img": "emu/Emu_16.png",
|
||||
"color": "#FF66BB",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "66",
|
||||
"name": "Ena 01",
|
||||
"character": "ena",
|
||||
"img": "ena/Ena_01.png",
|
||||
"color": "#B18F6C",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "67",
|
||||
"name": "Ena 02",
|
||||
"character": "ena",
|
||||
"img": "ena/Ena_02.png",
|
||||
"color": "#B18F6C",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "68",
|
||||
"name": "Ena 03",
|
||||
"character": "ena",
|
||||
"img": "ena/Ena_03.png",
|
||||
"color": "#B18F6C",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "69",
|
||||
"name": "Ena 04",
|
||||
"character": "ena",
|
||||
"img": "ena/Ena_04.png",
|
||||
"color": "#B18F6C",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "71",
|
||||
"name": "Ena 06",
|
||||
"character": "ena",
|
||||
"img": "ena/Ena_06.png",
|
||||
"color": "#B18F6C",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "72",
|
||||
"name": "Ena 07",
|
||||
"character": "ena",
|
||||
"img": "ena/Ena_07.png",
|
||||
"color": "#B18F6C",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "73",
|
||||
"name": "Ena 08",
|
||||
"character": "ena",
|
||||
"img": "ena/Ena_08.png",
|
||||
"color": "#B18F6C",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "74",
|
||||
"name": "Ena 09",
|
||||
"character": "ena",
|
||||
"img": "ena/Ena_09.png",
|
||||
"color": "#B18F6C",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "76",
|
||||
"name": "Ena 11",
|
||||
"character": "ena",
|
||||
"img": "ena/Ena_11.png",
|
||||
"color": "#B18F6C",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "77",
|
||||
"name": "Ena 12",
|
||||
"character": "ena",
|
||||
"img": "ena/Ena_12.png",
|
||||
"color": "#B18F6C",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "78",
|
||||
"name": "Ena 13",
|
||||
"character": "ena",
|
||||
"img": "ena/Ena_13.png",
|
||||
"color": "#B18F6C",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "79",
|
||||
"name": "Ena 14",
|
||||
"character": "ena",
|
||||
"img": "ena/Ena_14.png",
|
||||
"color": "#B18F6C",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "81",
|
||||
"name": "Ena 16",
|
||||
"character": "ena",
|
||||
"img": "ena/Ena_16.png",
|
||||
"color": "#B18F6C",
|
||||
"defaultText": {
|
||||
"text": "something",
|
||||
"x": 148,
|
||||
"y": 58,
|
||||
"r": -2,
|
||||
"s": 47
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
21
src/components/Canvas.jsx
Normal file
21
src/components/Canvas.jsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { useRef, useEffect } from 'react'
|
||||
import "../index.css"
|
||||
|
||||
const Canvas = props => {
|
||||
|
||||
const { draw, ...rest } = props
|
||||
const canvasRef = useRef(null)
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
const canvas = canvasRef.current
|
||||
const context = canvas.getContext('2d')
|
||||
|
||||
draw(context)
|
||||
|
||||
}, [draw])
|
||||
|
||||
return <canvas ref={canvasRef} {...rest}/>
|
||||
}
|
||||
|
||||
export default Canvas
|
||||
72
src/components/Picker.jsx
Normal file
72
src/components/Picker.jsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import ImageList from "@mui/material/ImageList";
|
||||
import ImageListItem from "@mui/material/ImageListItem";
|
||||
import Popover from "@mui/material/Popover";
|
||||
import Button from "@mui/material/Button";
|
||||
import { useState } from "react";
|
||||
import characters from "../characters.json";
|
||||
|
||||
export default function Picker({ setCharacter }) {
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
|
||||
const handleClick = (event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const open = Boolean(anchorEl);
|
||||
const id = open ? "picker" : undefined;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
aria-describedby={id}
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
onClick={handleClick}
|
||||
>
|
||||
Pick character
|
||||
</Button>
|
||||
<Popover
|
||||
id={id}
|
||||
open={open}
|
||||
anchorEl={anchorEl}
|
||||
onClose={handleClose}
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "left",
|
||||
}}
|
||||
>
|
||||
<ImageList sx={{ width: 500, height: 450 }} cols={4} rowHeight={120}>
|
||||
{characters.map((c, index) => (
|
||||
<ImageListItem
|
||||
key={index}
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
setCharacter(index);
|
||||
}}
|
||||
sx={{
|
||||
cursor: "pointer",
|
||||
"&:hover": {
|
||||
opacity: 0.5,
|
||||
},
|
||||
"&:active": {
|
||||
opacity: 0.8,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={`/img/${c.img}`}
|
||||
srcSet={`/img/${c.img}`}
|
||||
alt={c.name}
|
||||
loading="lazy"
|
||||
/>
|
||||
</ImageListItem>
|
||||
))}
|
||||
</ImageList>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
BIN
src/fonts/YurukaStd.woff2
Normal file
BIN
src/fonts/YurukaStd.woff2
Normal file
Binary file not shown.
10
src/index.css
Normal file
10
src/index.css
Normal file
@@ -0,0 +1,10 @@
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: rgb(87, 73, 91);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'YurukaStd';
|
||||
src: local('YurukaStd'), url(./fonts/YurukaStd.woff2) format('woff2');
|
||||
}
|
||||
22
src/index.jsx
Normal file
22
src/index.jsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import "./index.css";
|
||||
import App from "./App";
|
||||
import { ThemeProvider, createTheme } from "@mui/material/styles";
|
||||
import CssBaseline from "@mui/material/CssBaseline";
|
||||
|
||||
const darkTheme = createTheme({
|
||||
palette: {
|
||||
mode: "dark",
|
||||
},
|
||||
});
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById("root"));
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<ThemeProvider theme={darkTheme}>
|
||||
<CssBaseline />
|
||||
<App />
|
||||
</ThemeProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
Reference in New Issue
Block a user