ãã¡ã¤ã«ã®ãã©ãã° & ãããã
ã©ã³ãã£ã³ã°ãã¼ã¸ã§è¿°ã¹ãããã«ããã©ãã°ï¼ãããã API ã¯ããã¼ã¸å
ã§ã®è¦ç´ ã®ãã©ãã°ããã¼ã¸ããã®ãã¼ã¿ã®ãã©ãã°ããã¼ã¸ã¸ã®ãã¼ã¿ã®ãã©ãã°ã® 3 ã¤ã®ç¨éãåæã«ã¢ãã«åãã¾ãããã®ãã¥ã¼ããªã¢ã«ã§ã¯ã 3 ã¤ç®ã®ç¨éã§ããããã¼ã¸ã¸ã®ãã¼ã¿ã®ãã©ãã°ãã宿¼ãã¾ããã¦ã¼ã¶ã¼ããªãã¬ã¼ãã£ã³ã°ã·ã¹ãã ã®ãã¡ã¤ã«ã¨ã¯ã¹ããã¼ã©ã¼ããç»åãã¡ã¤ã«ããããããããã¼ã¸ä¸ã«è¡¨ç¤ºã§ããåºæ¬çãªããããã¾ã¼ã³ãå®è£
ãã¾ãããã©ãã°ï¼ãããããå©ç¨ã§ããªããã¾ãã¯å©ç¨ããããªãã¦ã¼ã¶ã¼åãã«ã<input> è¦ç´ ã«ãããã¡ã¤ã«é¸æã®ä»£æ¿æ©è½ãæä¾ãã¾ãã
åºæ¬çãªãã¼ã¸ã¬ã¤ã¢ã¦ã
é常㮠<input> ã«ãããã¡ã¤ã«é¸æã許å¯ãããã®ã§ãããããã¾ã¼ã³ã¯ <input> è¦ç´ ã§å®è£
ããã®ãåççã§ããããã«ããããã©ãã°ã§ã®æå
¥ã¨ã¯ãªãã¯æä½ãåæã«è¡ããã¨ãã§ãã¾ããä¸è¬çãªææ³ã¨ãã¦ã<input> ãé表示ã«ãã代ããã«ã¹ã¿ã¤ã«è¨å®ã容æãª <label> è¦ç´ ã¨é£åããã¾ããã¾ãããããããããç»åã®ãã¬ãã¥ã¼è¡¨ç¤ºç¨è¦ç´ ã追å ãã¾ãã
<label id="drop-zone">
ããã«ç»åããããããã¾ãã¯ã¯ãªãã¯ãã¦ã¢ãããã¼ããã¦ãã ããã
<input type="file" id="file-input" multiple accept="image/*" />
</label>
<ul id="preview"></ul>
<button id="clear-btn">ã¯ãªã¢</button>
ã©ãã«è¦ç´ ãã¹ã¿ã¤ã«è¨å®ããè¦è¦çã«ããããã¾ã¼ã³ã§ãããã¨ã示ãããã¡ã¤ã«å ¥åã¯é表示ã«ãã¾ãã
body {
font-family: "Arial", sans-serif;
}
#drop-zone {
display: flex;
align-items: center;
justify-content: center;
width: 500px;
max-width: 100%;
height: 200px;
padding: 1em;
border: 1px solid #cccccc;
border-radius: 4px;
color: slategray;
cursor: pointer;
}
#file-input {
display: none;
}
#preview {
width: 500px;
max-width: 100%;
display: flex;
flex-direction: column;
gap: 0.5em;
list-style: none;
padding: 0;
}
#preview li {
display: flex;
align-items: center;
gap: 0.5em;
margin: 0;
width: 100%;
height: 100px;
}
#preview img {
width: 100px;
height: 100px;
object-fit: cover;
}
<label> è¦ç´ 㨠<input> è¦ç´ ã使ç¨ãããã¨ã§ããã¡ã¤ã«é¸æ UX ã®å®è£
ã«è¿½å ã® JavaScript ã¯ä¸è¦ã«ãªãã¾ããæ¬¡ã«ããã¡ã¤ã«ã®ããããæä½ã¨ãããããããããã¡ã¤ã«ã®ãã®å¾ã®å¦çã«ç¦ç¹ãå½ã¦ã¾ãã
ããããã¿ã¼ã²ããã®å®£è¨
ããããã¿ã¼ã²ãã㯠<label> è¦ç´ ã§ããã¿ã¼ã²ããè¦ç´ ã¨ãã¦ã drop ã¤ãã³ããç£è¦ããããããããããã¡ã¤ã«ãå¦çãã¾ãã
const dropZone = document.getElementById("drop-zone");
dropZone.addEventListener("drop", dropHandler);
ãã¡ã¤ã«ããããã®å ´åããã¡ã¤ã«ãæå¹ãªããããå
ã¸ãããããããªãã¦ãããã©ã¦ã¶ã¼ãããã©ã«ãã§å¦çï¼ãã¡ã¤ã«ã®éã/ãã¦ã³ãã¼ããªã©ï¼ãè¡ããã¨ãããã¾ãããã®åä½ãé²ããããwindow ã® drop ã¤ãã³ããç£è¦ãããã£ã³ã»ã«ããå¿
è¦ãããã¾ãããã¡ã¤ã«ããã©ãã°ããã¦ããå ´åã®ã¿ã¤ãã³ããå¦çããããã«æ³¨æãã¾ãããªã³ã¯ãªã©ä»ã®è¦ç´ ã®å ´åã¯ãããã©ã«ãã®åä½ããã®ã¾ã¾ä½¿ç¨ãã¾ãããã©ãã°ãããã¢ã¤ãã ãç»å以å¤ã®ãã¡ã¤ã«ã®å ´åãã¤ãã³ãã¯å¦çãã¾ããã許å¯ããã¦ããªããã¨ãã¦ã¼ã¶ã¼ã«ãã£ã¼ãããã¯ãã¾ãã
window.addEventListener("drop", (e) => {
if ([...e.dataTransfer.items].some((item) => item.kind === "file")) {
e.preventDefault();
}
});
drop ã¤ãã³ããçºçãããã«ã¯ãè¦ç´ ã dragover ã¤ãã³ãããã£ã³ã»ã«ããå¿
è¦ãããã¾ããwindow ä¸ã§ drop ãç£è¦ãã¦ãããããwindow å
¨ä½ã«å¯¾ãã dragover ã¤ãã³ãããã£ã³ã»ã«ããå¿
è¦ãããã¾ããã¾ãããã¡ã¤ã«ãç»åã§ãªãå ´åãæ£ããå ´æã«ãã©ãã°ããã¦ããªãå ´åã DataTransfer.dropEffect ã none ã«è¨å®ãã¾ãã
dropZone.addEventListener("dragover", (e) => {
const fileItems = [...e.dataTransfer.items].filter(
(item) => item.kind === "file",
);
if (fileItems.length > 0) {
e.preventDefault();
if (fileItems.some((item) => item.type.startsWith("image/"))) {
e.dataTransfer.dropEffect = "copy";
} else {
e.dataTransfer.dropEffect = "none";
}
}
});
window.addEventListener("dragover", (e) => {
const fileItems = [...e.dataTransfer.items].filter(
(item) => item.kind === "file",
);
if (fileItems.length > 0) {
e.preventDefault();
if (!dropZone.contains(e.target)) {
e.dataTransfer.dropEffect = "none";
}
}
});
ã¡ã¢:
dragstart ããã³ dragend ã¤ãã³ãã¯ãOS ãããã©ã¦ã¶ã¼ã¸ãã¡ã¤ã«ããã©ãã°ããéã«çºçãã¾ãããOS ã®ãã¡ã¤ã«ããã©ã¦ã¶ã¼ã«ãã©ãã°ããããã¨ãæ¤åºããã«ã¯ã dragenter ããã³ dragleave ã使ç¨ãã¦ãã ããã
ã¤ã¾ããOS ãããã¡ã¤ã«ããã©ãã°ããéã«ã¯ãsetDragImage() ã使ç¨ãã¦ã«ã¹ã¿ã ã®ãã©ãã°ç»åãã«ã¼ã½ã«ãªã¼ãã¼ã¬ã¤ãé©ç¨ãããã¨ã¯ã§ãã¾ãããããã¯ããã©ãã°ãã¼ã¿ã¹ãã¢ã dragstart ã¤ãã³ãå
ã§ã®ã¿å¤æ´å¯è½ã§ããããã§ãããã®å¶é㯠setData() ã«ãé©ç¨ããã¾ãã
ããããã®å¦ç
次ã«ãåãã¡ã¤ã«ã«ã¢ã¯ã»ã¹ããããã« getAsFile() ã¡ã½ããã使ç¨ã㦠dropHandler ãå®è£
ãã¾ãããã®å¾ãã¢ããªã±ã¼ã·ã§ã³ã¯ãã¡ã¤ã« API ã使ç¨ãã¦ãã®ãã¡ã¤ã«ãã©ã®ããã«å¦çããããæ±ºå®ã§ãã¾ããããã§ã¯åã«ãã¼ã¸ä¸ã«è¡¨ç¤ºãã¦ãã¾ãããå®éã«ã¯æçµçã«ãµã¼ãã¼ã¸ã¢ãããã¼ããããã¨ãå¿
è¦ã«ãªãã§ãããã
const preview = document.getElementById("preview");
function displayImages(files) {
for (const file of files) {
if (file.type.startsWith("image/")) {
const li = document.createElement("li");
const img = document.createElement("img");
img.src = URL.createObjectURL(file);
img.alt = file.name;
li.appendChild(img);
li.appendChild(document.createTextNode(file.name));
preview.appendChild(li);
}
}
}
function dropHandler(ev) {
ev.preventDefault();
const files = [...ev.dataTransfer.items]
.map((item) => item.getAsFile())
.filter((file) => file);
displayImages(files);
}
input ã«åãåä½ã追å
ä¸è¨ããã©ãã°ï¼ããããã®å
¨ãã¼ã¿ããã¼ã§ããæ¬¡ã«ãdisplayImages() 颿°ããã¡ã¤ã«å
¥åæ¬ã«ãæ¥ç¶ããå¿
è¦ãããã¾ãã
const fileInput = document.getElementById("file-input");
fileInput.addEventListener("change", (e) => {
displayImages(e.target.files);
});
ã¯ãªã¢ãã¿ã³
æå¾ã«ãã¬ãã¥ã¼é åãã¯ãªã¢ããæ¹æ³ã追å ãã¾ãã URL.revokeObjectURL() ã使ç¨ãã¦ç»åãªãã¸ã§ã¯ãã使ç¨ãã¦ããã¡ã¢ãªãè§£æ¾ãã¾ãã
const clearBtn = document.getElementById("clear-btn");
clearBtn.addEventListener("click", () => {
for (const img of preview.querySelectorAll("img")) {
URL.revokeObjectURL(img.src);
}
preview.textContent = "";
});