はじめに
画像投稿の際に1つ1つ画像を選んで投稿...とても面倒ですよね
そこでドラッグ&ドロップができればめちゃくちゃ簡単に投稿できかな?と思い調べてみました。
結果JavaScriptを使えば可能なのはわかったけれど、初学者としてはもっとシンプルに、簡単に実装したい!
もっと楽したい!!
そんな時に閃いた力技をご紹介します。
実は最初からドラッグ&ドロップできる!
実はfile_fierdを使用すると、何もしなくてもドラッグ&ドロップできます。
「...?」ですよね、実際に確認してみましょう
ちゃんとできてますよね?
ちなみに今のViewはこれだけです。
= form_with model: @article de |f|
.new_article
= f.file_field :image
= f.submit
file_fieldを使用した際に作られる「ファイルを選択」ボタンの上であれば、ドラッグ&ドロップは可能な状態にあります!
ね、簡単でしょう?
viewを整える
これを利用すれば、使いやすいドラッグ&ドロップ機能が実装できます!
そこで、これからやることは以下の3つ
- ファイル選択ボタンを広げる
- ドラッグ&ドロップエリアを作成する。
- "1"のファイル選択ボタンと"2"のドラッグ&ドロップエリアを重ねる。
それでは、順を追ってご紹介します。
1.ファイル選択ボタンを広げる
file_fieldで作成したボタンにクラスをつけて、CSSで広げる。
= form_with model: @article de |f|
.new_article
= f.file_field :image, id: "post"
= f.submit
# post{
height: 300px;
width: 300px;
cursor: pointer;
background-color: aqua;
}
※ 今回はわかりやすいようにJSでプレビュー表示させています。
2. ドラッグ&ドロップエリアを作成する
ファイルを選択ボタンが邪魔なので、ドラッグ&ドロップできるエリアを作ります。
= form_with model: @article do |f|
= f.file_field :image, id:"post"
.choice_box ドラック&ドロップまたはクリック
.submit
= f.submit
# post{
height: 300px;
width: 300px;
cursor: pointer;
background-color: aqua;
}
.choice_box{
height: 300px;
width: 300px;
background-color: rgb(186, 186, 186);
pointer-events: none;
line-height: 300px;
text-align: center;
border: 2px dashed black;
}
3. "1"のファイル選択ボタンと"2"のドラッグ&ドロップエリアを重ねる

完成
以上でドラッグ&ドロップが完成です!(もちろん、ファイルクリックでも選択できます。)
簡単でしたよね?
もちろん、データはちゃんと入っています。

以上が実装方法です。
終わりに
プログラミング始めたばっかでJSはまだ難しい...と言う人は、このやり方を参考にしてみてください!
最初は難しいやり方を勉強するのではなく、自分ができそうなやり方で経験を積んで、プログラミングを楽しむことをお勧めします。
最後にコードを残しておきますので、色々触ってみてください。
= form_with model: @article do |f|
= f.file_field :image, id:"post"
.choice_box
ドラック&ドロップまたはクリック
#show
.submit
= f.submit
# 以下、画像プレビューです。file_field (#post) が選択されたら プレビュー (#show)に画像を表示させます。
%script{:src => "https://code.jquery.com/jquery-3.0.0.min.js"}
:javascript
$(function(){
$('#post').change(function(){
$('img').remove();
var file = $(this).prop('files')[0];
if(!file.type.match('image.*')){
return;
}
var fileReader = new FileReader();
fileReader.onloadend = function() {
$('#show').html('<img src="' + fileReader.result + '"/>');
}
fileReader.readAsDataURL(file);
});
});
@mixin imageBox{
height: 300px;
width: 300px;
cursor: pointer;
position: absolute;
top: 0;
left: 0;
}
# post{
@include imageBox;
background-color: aqua;
z-index: 1;
}
.choice_box{
@include imageBox;
background-color: rgb(186, 186, 186);
z-index: 2;
pointer-events: none;
line-height: 300px;
text-align: center;
border: 2px dashed black;
}
# show{
height: 300px;
width: 300px;
border: 2px solid #333;
position: absolute;
top: 0;
left: 300px;
img{
height: 296px;
width: 296px;
object-fit: cover;
}
}
.submit{
position: absolute;
top: 300px;
left: 0;
}