ドラッグ&ドロップでファイル選択をさせて、画像をプレビューする機能をJavascriptで実装する方法について記します。
jQueyやライブラリは使用せずに素のJavascriptで実現する事を目指します。
目次
ドラッグ&ドロップ&プレビュー機能
下記のようにドラッグ&ドロップしてファイル選択させ、画像をプレビューする機能の実装を目指します。
HTMLとCSSでドラッグ&ドロップエリアを作る
まずは、ドラッグ&ドロップエリアの見た目の作成から始めましょう。
<div class="drop-area">
<input type="file">
<div class="preview-area"></div>
</div>
.drop-area {
border: 1px dashed;
border-radius: 10px;
display: flex;
flex-direction: column;
align-items: center;
padding: 50px;
}
.drop-area input[type="file"] {
padding: 15px;
}
.drop-area input[type="file"]::file-selector-button {
background: gray;
color: white;
padding: 8px 10px;
border-radius: 4px;
width: 100%;
display: block;
border: none;
}
.drop-area::before {
content: "ここにファイルをドラッグ&ドロップ\Aまたは";
white-space: pre;
text-align: center;
font-size: 20px;
line-height: 1.6;
}
.drop-area .preview-area img {
width: 100%;
}
見た目が整いました。
※現時点では、まだドラッグ&ドロップでファイル選択はできません。
ドラッグ&ドロップでファイル選択できるようにする
ドラッグ&ドロップでファイル選択させるためのJavascriptは下記になります。
ドロップしてファイル選択させるだけならもう少し単純な記述で済むのですが、一つ問題が発生するため少し複雑になっています(コードの下で詳しく解説)。
document.querySelectorAll('.drop-area').forEach((el)=>{
const input = el.querySelector('input')
el.addEventListener('drop', (e)=>{ // ドロップされた時
if(e.dataTransfer.files.length == 1 || input.hasAttribute('multiple')){ // ファイルが一つ、またはmultiple属性がついていたら
input.files = e.dataTransfer.files // ファイルを取得して埋め込む
input.dispatchEvent(new Event('change')) // 変更イベントを強制発火
}else{
alert('ファイルを一つ選択してください')
}
e.preventDefault() // ドロップ時に別タブで開くのを防止
})
el.addEventListener('dragover', (e)=>e.preventDefault()) // ドロップ時に別タブで開くのを防止
})
『ドラッグ&ドロップでは複数ファイル選択ができるのに通常のファイル選択では一つしか選択できない』という状態を避けるために4行目のif文でmultiple属性がついてる時のみ複数ファイルをドロップできるようにしています。
ドラッグ&ドロップでファイル選択できるようになったと思うので試してみてください。
※プレビューはまだ表示されません
画像をプレビューする
次に画像をプレビューする機能を実装します。
選択されたファイルからimgタグを生成して、プレビューエリアに埋め込むというシンプルな処理です。
document.querySelectorAll('.drop-area').forEach((el)=>{
const input = el.querySelector('input')
/************* ↓ 追加 ↓ **************/
input.addEventListener('change', (e)=>{ // ファイルが選択されたとき
const imgs = Array.from(e.target.files).map((file,i)=> // 選択されたファイルをマップ処理
`<img src="${URL.createObjectURL(file)}">` // ファイルからimgタグを生成
)
el.querySelector('.preview-area').innerHTML = imgs.join('') // 画像をプレビューエリアに表示
})
/************* ↑ 追加 ↑ **************/
el.addEventListener('drop', (e)=>{
if(e.dataTransfer.files.length == 1 || input.hasAttribute('multiple')){
input.files = e.dataTransfer.files
input.dispatchEvent(new Event('change'))
}else{
alert('ファイルを一つ選択してください')
}
e.preventDefault()
})
el.addEventListener('dragover', (e)=>e.preventDefault())
})
基本的なドラッグ&ドロップ&プレビュー機能が完成しました。
ファイル選択、またはドラッグ&ドロップで画像がプレビューされると思うので試してみてください。
ファイルを複数選択させたい場合
input[type=”file”]にmultiple属性を付与することで、ユーザーはファイルを複数選択する事ができるようになります。
<div class="drop-area">
<input type="file" multiple> <!-- 変更 -->
<div class="preview-area"></div>
</div>
下記CSSを追加しておくと、multiple属性が付与された時のみ画像が横並びでプレビュー表示されるので親切かもしれません。
※こちらの場合は4列で表示します。
.drop-area input[multiple] + .preview-area {
gap: 10px;
display: grid;
grid-template-columns: repeat(4, 1fr);
}
ソースコード全文
ソースコードを全文載せておきます。
<style>
.drop-area {
border: 1px dashed;
border-radius: 10px;
display: flex;
flex-direction: column;
align-items: center;
padding: 40px;
}
.drop-area input[type="file"] {
padding: 15px;
}
.drop-area input[type="file"]::file-selector-button {
background: gray;
color: white;
padding: 8px 10px;
border-radius: 4px;
width: 100%;
display: block;
border: none;
}
.drop-area::before {
content: "ここにファイルをドラッグ&ドロップ\Aまたは";
white-space: pre;
text-align: center;
font-size: 20px;
line-height: 1.6;
}
.drop-area input[multiple] + .preview-area {
gap: 10px;
display: grid;
grid-template-columns: repeat(4, 1fr);
}
.drop-area .preview-area img {
width: 100%;
}
</style>
<div class="drop-area">
<input type="file" multiple> <!-- ファイルを一つだけ選択させたい場合は『multiple』をトル -->
<div class="preview-area"></div>
</div>
<script>
document.querySelectorAll('.drop-area').forEach((el)=>{
const input = el.querySelector('input')
input.addEventListener('change', (e)=>{ // ファイルが選択されたとき
const imgs = Array.from(e.target.files).map((file,i)=> // 選択されたファイルをマップ処理
`<img src="${URL.createObjectURL(file)}">` // ファイルからimgタグを生成
)
el.querySelector('.preview-area').innerHTML = imgs.join('') // 画像をプレビューエリアに表示
})
el.addEventListener('drop', (e)=>{ // ドロップされた時
if(e.dataTransfer.files.length == 1 || input.hasAttribute('multiple')){ // ファイルが一つ、またはmultiple属性がついていたら
input.files = e.dataTransfer.files // ファイルを取得して埋め込む
input.dispatchEvent(new Event('change')) // 変更イベントを強制発火
}else{
alert('ファイルを一つ選択してください')
}
e.preventDefault() // ドロップ時に別タブで開くのを防止
})
el.addEventListener('dragover', (e)=>e.preventDefault()) // ドロップ時に別タブで開くのを防止
})
</script>
以上、ドラッグ&ドロップ&プレビュー機能を作る方法でした!
プレビュー機能が必要ない場合は、HTMLとCSSのみでドラッグ&ドロップ機能を作ることができます。
HTMLとCSSのみでファイルのドラッグ&ドロップ機能を作る