画像登録前のプレビューのやり方 画像比率

どうも〜
画像を登録する必要のある、もしくはできるアプリであれば、登録する画像のプレビューが付き物ですよね。

1作前の個人アプリでもプレビュー機能は作ったのですが、画像によってプレビュー時に縦に伸びたり、横に伸びたりとなってしまってました。
今回解決方法が見つかったので、備忘録ついでにブログに載せて起きます。

その前にまず、プレビューのやり方です。
HTML

  = form_with(model: [@image], local: true,class:"image_form") do |f| -# ①
    .image_field-new
      = f.label :'Icon(Not essential)',class:'new_labelname'
      %br/
      = image_tag asset_path('初期画像'),class:'icon_image',size:"120x120"
      = f.file_field :iconimage, autocomplete: "iconimage",class:'icon_image-form' -# ②
      .icon_imagebtn File -# ③

※今回作成しているアプリのやり方をほぼコピーして載せてるので、下記に注意点を載せて起きます。
①withでもforでも大丈夫です。
②display: none;で隠してます。
③②を隠したので、これを加工してJsから②を押すように処理
丸っとコピーだとCSSの記述が足りないのでご注意を!

JavaScript(jQuery)

$(function(){
  // 新規登録の画像を選択するファイルボタンを擬似的に押せるように
  const realBtn = $('.icon_image-form');
  const fakeBtn = $('.icon_imagebtn');

  $(fakeBtn).on('mousedown',function(){
    $(realBtn).click();
  });

  //ここから画像のプレビュー
  $('.icon_image-form').change(function(e){
    //ファイルオブジェクトを取得する
    let file = e.target.files[0];
    let reader = new FileReader();
 
    //画像でない場合は処理終了
    if(file.type.indexOf("image") < 0){
      alert("画像ファイルを指定してください。");
      return false;
    }
 
    //アップロードした画像を設定する
    reader.onload = (function(file){
      return function(e){
        $(".icon_image").attr("src", e.target.result);
        $(".icon_image").attr("title", file.name);
      };
    })(file);
    reader.readAsDataURL(file);
  });
});

という感じでここまで実装できれば画像は表示されます。
が!
画像の比率によって縦横に画像が伸びちゃいます。
実際carrierwaveでmini_magickとか使って設定すれば保存される画像は比率をコントロールできます。
ちなみにこんな感じになります。(設定が個人アプリ用なのはすいません…)

f:id:zare926:20200711004402p:plain
CSS設定無し
順序逆ですが、デフォルトはこんな感じです。

f:id:zare926:20200711004553p:plain
デフォルト

さて本題の比率のコントロールですが、2種類紹介したいと思います。
先に画像から

f:id:zare926:20200711004714p:plain
object-fit: cover;
CSS

.icon_image{
    width: 120px;
    height: 120px;
    object-fit: cover;
  }

しっかり元の画像通りの比率で必要範囲だけ表示されてます。

f:id:zare926:20200711005008p:plain
object-fit: contain;
CSS

.icon_image{
    width: 120px;
    height: 120px;
    object-fit: contain;
  }

こちらは横幅に合わせて表示してくれてます。
みんながみんな正四角形の画像を登録するとは限らないので、個人的にはcoverがいいかなと思いますが、もっと他の方法はあると思います。

プレビュー表示の実装に少しでも手助けになれば幸いです!