初めに
この記事では、画像選択時にその場で選択した画像を表示させる方法をご紹介します!
実装
今回は以下のように実装してみました。
CSSはTailwindCSSを使用してます。
・add.blade.php(画像選択のビュー)
<div class="flex justify-center md:px-20 xl:px-20">
<label class="block px-12 py-2 rounded-md bg-gray-300">
<p class="text-center">画像を選択</p>
<input id="img_upload" type="file" accept="image/*" name="image" value="{{old('image')}}" class="hidden -ml-12" onchange=" previewImage(this)">
@error('image')
<p class="w-44 text-red-500 text-sm">{{$message}}</p>
@enderror
</label>
</div>
<div class="flex justify-center">
<label class="block w-44">
<img id="preview" class="h-48 w-full" src="https://zaikokanri.s3.ap-northeast-1.amazonaws.com/SQBzGcvgGvOftMYGWG85i2DBuXaONl6FbiW9uwoA.jpg">
</label>
<script>
function previewImage(obj) {
var fileReader = new FileReader();
fileReader.onload = (function() {
document.getElementById('preview').src = fileReader.result;
});
fileReader.readAsDataURL(obj.files[0]);
}
</script>
</div>
・app.blade.php
add.blade.phpは親元であるapp.blade.phpを継承している構成になっていますが、一様app.blade.phpの
ここに関しては今回のjQuery導入に合わせて何か読み込んだりといったことは特にしていないです。
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>@yield('title')</title>
<!-- Fonts -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap">
<!-- Styles -->
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
@livewireStyles
<!-- Scripts -->
<script src="{{ mix('js/app.js') }}" defer></script>
</head>
jQuery部分の説明
<script>
function previewImage(obj) {
var fileReader = new FileReader();
fileReader.onload = (function() {
document.getElementById('preview').src = fileReader.result;
});
fileReader.readAsDataURL(obj.files[0]);
}
$(function() {
$(document).on('change', '#receipt', function() {
$('#preview').addClass('img-thumbnail');
});
});
</script>
・var fileReader = new FileReader();
FileReaderオブジェクトでユーザーのコンピュータに保存されているファイルの内容を非同期に読み取る。
それをvarで定義したfileReader変数に格納。
・document.getElementById('preview').src = fileReader.result;
・document.getElementById('preview').src
画像選択ボタン部分で指定したid=preview
かつ画像要素を特定
。
・fileReader.result;
読み込んだファイルの内容を返す。また、こちらはデータの読み取り操作が完了した後でしかファイルの内容を返しません。読み取りができてない場合はnullとなります。
・fileReader.readAsDataURL(obj.files[0]);
ファイルのデータを表すbase64
エンコーディングされたdata:URL
の文字列を格納。
・readAsDataURLメソッド
指定されたfile型の内容を読み込む。
読み込み操作が終了するとreadyStateがDONEとなりloadendが発生
。このとき、result属性にはファイルのデータを表すbase64エンコーディングされたdata:URLの文字列
が格納される。
・readState
XMLHttpRequestのプロパティで、通信状態を表す数値を返す。
・DONE
成功・失敗に関わらず通信を終了した状態。
・load
loadendイベントは、リクエストが正常に完了した場合afterload
または失敗した場合afterabort
またはerror
が発生。
・base64
64進数を意味する言葉で、すべてのデータをアルファベットa〜z, A〜Z
と数字0〜9
、一部の記号+,/
の64文字で表すエンコード方式。
データ長を揃えるためにパディング(データを一定の長さに整形するため前後に挿入される無意味なデータ)として末尾に記号の=
を使用。
おまけ
下記のようにしてあげると画像周りに角丸の枠線を付け加えることができます!
$(function() {
$(document).on('change', '#receipt', function() {
$('#preview').addClass('img-thumbnail');
});
});
・$(document).on('change', '#img_upload', function(){}
changeイベントが発生したとき、function{}に書いた処理を実行する。
・change
フォーム(input要素)や選択メニュー(select要素)、テキストエリア(textarea要素)にてユーザーの操作によって値が変更されたときに発生するイベント。
・$('#preview').addClass('img-thumbnail');
#previewに対して``img-thumbnailクラス属性を追加
。
・img-thumbnailクラス
bootstrapのクラスで、画像の周りに角丸の枠線が追加される。