karlkoder-playground/js/sprite-editor.js

73 lines
2.3 KiB
JavaScript

export class SpriteEditor {
constructor(rootEl, sprites) {
this.list = rootEl.querySelector("#sprite-editor-sprite-list");
this.preview = {};
this.preview.title = rootEl.querySelector("#sprite-editor-preview-title");
this.preview.image = rootEl.querySelector("#sprite-editor-preview-image");
this.sprites = sprites;
rootEl.querySelector("#sprite-editor-upload-button").addEventListener("click", () => {
this.promptUpload();
});
this.renderList();
}
promptUpload() {
const input = document.createElement("input");
input.type = "file";
input.accept = "image/*";
input.multiple = true;
input.style = "display: none;";
input.addEventListener("cancel", () => {
input.remove();
});
input.addEventListener("change", async () => {
for (const file of input.files) {
this.addSprite({
name: file.name,
mime: file.type,
bytes: await fetch(URL.createObjectURL(file)).then((x) => x.bytes()),
});
}
input.remove();
});
document.body.append(input);
input.click();
}
addSprite({ name, bytes, mime }) {
const id = Math.round(Math.random() * 1e6);
this.sprites.push({ id, bytes, name, mime });
this.renderList();
}
deleteSprite(id) {
this.sprites = this.sprites.filter((x) => x.id !== id);
this.renderList();
}
setPreview(id) {
const sprite = this.sprites.find((x) => x.id === id);
this.preview.title.textContent = sprite.name;
this.preview.image.src = `data:${sprite.mime};base64,${sprite.bytes.toBase64()}`;
}
renderList() {
const children = this.sprites
.map((sprite) => {
const listItem = document.createElement("li");
listItem.classList.add("sprite-editor-list-item");
const name = document.createElement("span");
name.textContent = sprite.name;
name.addEventListener("click", () => {
this.setPreview(sprite.id);
});
listItem.append(name);
return listItem;
});
this.list.replaceChildren(...children);
}
}