1
2

More than 3 years have passed since last update.

画像のプレビュー機能実装

Posted at

はじめに

Railsでオリジナルアプリを制作しています。このアプリに画像投稿機能を実装しました。画像をアップロードした後(データベースに保存する前)の状態でプレビューを表示しましたので、書き記します。
※コードひとつひとつに解説を挟むので、最後に完成コードを載せています。

目次

1.事前準備
2.プレビュー機能の実装

1.事前準備

JavaScriptを使用しますので、jsファイルを準備します。ページが読み込まれたときに動作するように定義します。

app/javascript/packs/preview.js
document.addEventListener('DOMContentLoaded', function(){
  const ImageList = document.getElementById('image-list');
});

なお、getElementByIdで取得するimage-listは、html上のdivタグのid名です。このdivタグにプレビューを表示します。そのため、htmlに追記します(今回は送信ボタンの下に配置しました)。

○○.html.erb
<%= f.file_field :image %>
<%= f.submit '送信' %>
<div id="image-list"></div>

また、作成したjsファイルが読み込まれるようにapplication.jsも編集します。コメントアウトしたturbolinksは画面遷移を高速化するGemです。ページ内の情報を全て読み込まず、HTMLだけを読み取るそうです。だからJavaScriptで設定したイベントが発火しない場合があります。

app/javascript/packs/application.js
// require("turbolinks").start()  // コメントアウトする
require("@rails/activestorage").start()
require("channels")
require('./preview')  // 追記する

2.プレビュー機能の実装

全部で3ステップ。
**2-1.画像情報の取得
はじめに画像情報を取得し、URLを生成します。画像情報の取得はinput要素の値に変更があった場合に行います。

app/javascript/packs/preview.js
document.addEventListener('DOMContentLoaded', function(){
  const ImageList = document.getElementById('image-list');

  document.getElementById('desk_image').addEventListener('change', function(e){
  //↑desk_imageは画像選択ボタンのid//
    const file = e.target.files[0];
    const blob = window.URL.createObjectURL(file);
  });
});

選択した画像は、発火したイベントe、targetの中のfilesという配列に格納されています。それをfile変数に定義し、window.URL.createObjectURLでURLを生成します。

2-2.取得画像の表示
createElementで取得画像を入れ込むdiv要素とimg要素生成します。その後生成した要素をブラウザに表示します。

app/javascript/packs/preview.js
document.addEventListener('DOMContentLoaded', function(){
  const ImageList = document.getElementById('image-list');

  document.getElementById('desk_image').addEventListener('change', function(e){
    const file = e.target.files[0];
    const blob = window.URL.createObjectURL(file);

  // 画像を表示するためのdiv要素を生成
    const imageElement = document.createElement('div');

  // 表示する画像要素を生成し、画像を入れ込む
    const blobImage = document.createElement('img');
    blobImage.setAttribute('src', blob);

  // 生成したHTMLの要素をブラウザに表示させる
    imageElement.appendChild(blobImage);
    ImageList.appendChild(imageElement);
  });
});

appendChildで指定した親要素の中に要素を追加する(使い方:親要素.appendChild(子要素))。

2-3.エラー回避と編集可能にする
2-2までで画像は表示されるようになりました。しかし、画像投稿ページ以外ではコンソール上でエラーが表示されます。これを回避するため条件分を追加します。URLにnew及びeditがある場合(画像の新規投稿、編集時)に適用するように記述します。

app/javascript/packs/preview.js
if (document.URL.match( /new/ ) || document.URL.match( /edit/ )) {
  document.addEventListener('DOMContentLoaded', function(){
    const ImageList = document.getElementById('image-list');

 ーーーーーーーーーーーーーーー中略ーーーーーーーーーーーーーーーーーー 
    // 生成したHTMLの要素をブラウザに表示させる
      imageElement.appendChild(blobImage);
      ImageList.appendChild(imageElement);
    });
  });
}

画像を編集するときは、既存のプレビューを削除した後に新しい画像のプレビューを表示するようにする。

app/javascript/packs/preview.js
if (document.URL.match( /new/ ) || document.URL.match( /edit/ )) {
  document.addEventListener('DOMContentLoaded', function(){
    const ImageList = document.getElementById('image-list');

    document.getElementById('message_image').addEventListener('change', function(e){
      // 画像が表示されている場合のみ、すでに存在している画像を削除する
      const imageContent = document.querySelector('img');
      if (imageContent){
        imageContent.remove();
      }
      const file = e.target.files[0];
      const blob = window.URL.createObjectURL(file);
      const imageElement = document.createElement('div');
      const blobImage = document.createElement('img');
      blobImage.setAttribute('src', blob);
      imageElement.appendChild(blobImage);
      ImageList.appendChild(imageElement);
    });
  });
}

以上

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2