本記事投稿のいきさつ
アプリの中で画像投稿機能を実装したとき、ただフォームを作成するだけでは画像を選択しても表示がされず何を選んだのか確認をすることが出来ません。
そこで、画像を選択した時点でプレビュー表示することができればいいなと思い、実際に機プレビュー機能を作成したため、記録として残したいと思います。
今回はユーザーのプロフィール画像の編集画面を想定します。
そのため、既に登録されている画像は最初からプレビューさせた状態で表示をさせます。
前提
- 変種画面はprofile_edit.html.haml
- 画像の保存先は Usersテーブル: imageカラム
- file_field本体は隠し、画像が選択されていない時はiconを、
選択されている時はプレビュー画像をクリックすることで画像選択できるようにします。 - jQueryを使用しますが、必要なGemのインストール等は既に出来ているとします。
- ユーザー機能はDeviseを使用しています。
- cssは今回の内容に含まれません。
フォーム作成
まず、今回はhamlでビューのフォームを作成します。
profile_edit.html.haml
= form_for current_user, url: {action: 'profile_update'} do |f|
.form-group
.image_form
.image_form__contents
-# ラベルでfile_fieldとicon、プレビュー画像を紐付けます
= f.label :image, class: 'image_label' do
.prev-contents
-# 既に登録されている画像があれば表示をさせます
- if current_user.image.present?
.prev-content
= image_tag current_user.image.url, alt: "preview", class: "prev-image"
-# 既に登録されている画像がなければiconを表示させます
- else
= icon('fas', 'image', class: 'photo-icon')
-# file_fieldはdisplay: none;で隠します
= f.file_field :image, class: 'image_form__contents__field hidden_file'
FileReader
今回はFileReaderを使用します。
FileReaderとはHTML5世代の機能でユーザーのPC内にあるファイルやバッファ上の生データに対して、読み取りアクセスを行えるオブジェクトです。
jsファイルの編集
今回はimage_preview.jsを作成して、そこに記述していきます。
image_preview.js
$(document).on('turbolinks:load', function () {
$(function () {
// 画像をプレビュー表示させる.prev-contentを作成
function buildHTML(image) {
var html =
`
<div class="prev-content">
<img src="${image}", alt="preview" class="prev-image">
</div>
`
return html;
}
// 画像が選択された時に発火します
$(document).on('change', '.hidden_file', function () {
// .file_filedからデータを取得して変数fileに代入します
var file = this.files[0];
// FileReaderオブジェクトを作成します
var reader = new FileReader();
// DataURIScheme文字列を取得します
reader.readAsDataURL(file);
// 読み込みが完了したら処理が実行されます
reader.onload = function () {
// 読み込んだファイルの内容を取得して変数imageに代入します
var image = this.result;
// プレビュー画像がなければ処理を実行します
if ($('.prev-content').length == 0) {
// 読み込んだ画像ファイルをbuildHTMLに渡します
var html = buildHTML(image)
// 作成した.prev-contentをiconの代わりに表示させます
$('.prev-contents').prepend(html);
// 画像が表示されるのでiconを隠します
$('.photo-icon').hide();
} else {
// もし既に画像がプレビューされていれば画像データのみを入れ替えます
$('.prev-content .prev-image').attr({ src: image });
}
}
});
});
});
上記で出てくるDataURISchemeとは、
簡単にいうと、画像やらJavascriptやらそういったHTMLのコンテンツを文字列として定義出来るものです。
以上で、画像が表示されます。
終わり
最後まで見ていただきありがとうございました。