【CSS】画像をwindow幅に合わせた大きさの正方形で表示する方法

おはようございます。
今日はブラウザに画像を表示する際、window幅に合わせた大きさの正方形で表示をする方法をCSSで書いていきたいと思います。
なお、このブログではRuby on Railsウェブアプリケーションを作る過程で私がつまったところや難しいと感じた部分について記事を書いています。そのため、記事中でのコードはRuby on Railsのコードがでてきます。しかし、今回の内容はHTMLとCSSですので、Rubyなんて知らねえよという方でも参考になると思いますので、よろしくお願いします。

実装後の姿

下の動画のように正方形を維持したままwindow幅に合わせて可変してくれる記述をCSSでしていきたいと思います。
https://gyazo.com/baf904a117b36b0222daae1901389175


前提

前提としては、画像をブラウザ上に表示できている状態とします。以下にHTML(HAML)を示します。

%ul.images__box
  - if event.images.any?
    - event.images.each do |image|
      %li.image_box
        = image_tag image.photograph.url 
  - else
    まだ写真が投稿されていません。



記載の流れ

① 写真が入れられる箱のスタイリング (images__box)
② 写真1枚が入れられる箱のスタイリング (image__box)
③ 写真のスタイリング (img)

という順番で書いていきます。箱と言われてもイメージがつかない人のために概略図を書いておきます。

f:id:shun_0211:20200725102008p:plain


① 写真が入れられる箱のスタイリング (images__box)

まずは一番大きい箱のスタイリングからやっていきます。

.images__box{
  display: flex;


Flexboxを使って画像を横並びにします。ここはこれだけでOKです。

② 写真1枚が入れられる箱のスタイリング (image__box)

次に1枚ずつの箱に対してスタイリングをしていきます。

.image__box{
  width: 23%;
  position: relative;
}
.image__box::before{
  padding-top: 100%;
  content: "";
  display: block;
}


ここが一番理解しにくいところです。まずは、image__boxの横幅を指定します。そして、疑似要素を使用して正方形の箱を作ります。
beforeなどの擬似要素は、対象の要素に擬似的に要素を追加して装飾を適用するセレクタのことです。このbeforeに対してpadding-top: 100%を適用します。CSSでは、高さ方向にpaddingを%で指定した場合、基準値をwidth(100%)から取得する性質があります。つまり、image__boxの横幅と同じpaddingを取ってくれます。これにより、正方形の箱を用意することができるわけです。

また、写真の位置を指定するために position: relative を指定しておきます。


※ ハマるポイントとしては、必ず親要素に当たる要素にulタグをつけ、子に当たる要素にliタグをつける必要があります。そうしないと、原因不明の長方形ができるようになってしまうので注意してください。

③ 写真のスタイリング (img)

最後に写真のスタイリングをして完成です。

img{
  object-fit: cover;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}


position: absolute と top: 0; left: 0 により写真の位置を箱の中にしっかり収めます。当然、写真の縦と横の大きさは箱の大きさと同じにするため、height と weight は100%です。

object-fit: cover を指定することにより、画像をボックスサイズに合わせて縦横比を維持しながらリサイズし、トリミングしてはめ込みます。縦と横のうち、小さい方を基準にして大きい方をトリミングするので、画像は必ず正方形になってくれます。

まとめ

以上になりますが、いかがだったでしょうか。最初はなかなかとっつきにくい内容に見えるかもしれませんが、分解して見ていくと難しいことは何もしてないと思います。最後にCSS全体のコードを載せて終わりにします。ここまで読んでくださり、ありがとうございました。分かりにくいやアドバイス等ありましたらコメントくださると幸いです。では!

    .images__box{
      margin-bottom: 20px;
      text-align: center;
      &__view{
        display: flex;
        width: 100%;
        flex-wrap: wrap;
        .image__box{
          width: 23%;
          position: relative;
          margin-right: 2%;
          margin-bottom: 2%;
          img{
            object-fit: cover;
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
          }
        }
        .image__box::before{
          padding-bottom: 100%;
          content: "";
          display: block;
        }
      }
      .details{
        text-align: center;
        border: 1px solid;
        display: inline-block;
        font-size: 13px;
        padding: 4px 10px;
        border-radius: 10px;
        cursor: pointer;
        margin-top: 10px; 
      }
    }


【rails】f.file_fieldによる画像複数枚投稿の実装方法

こんばんわ。
今日はrailsでの複数枚画像投稿の実装方法の記事を書いていきたいと思います。

前提

画像の一枚ずつでの投稿は実装できているものとします。その際のコードを下に示します。
(今回は複数枚投稿の実装方法のため、変更を加えるviewとcontrollerしかコードを紹介していません。)

new.html.haml

.image__upload
  .image__upload__title
    写真
  .image__upload__field
    = icon('fas', 'camera')
  = f.file_field :photograph, class: "image__form"
.new__image__post
  = button_tag type: "submit", class: "new__image__post__button" do
    %i.fas.fa-arrow-circle-up
    UPLOAD

images_controller

class ImagesController < ApplicationController

  def new
    @events = Event.all
    @image = Image.new
  end

  def create
    @image = Image.new(image_params)
    @image.save
  end
  
  private
  def image_params
    params.require(:image).permit(:user_id, :event_id, :photograph).merge(user_id: current_user.id)
  end

end



実装の流れ

① Viewでfile_fieldメソッドに:multiple => trueのオプションをつけて複数枚投稿を可能にする。
② Controllerで配列の形で送られてくる画像を一枚ずつ取り出して保存処理を行う。

① Viewでfile_fieldメソッドに:multiple => trueのオプションをつけて複数枚投稿を可能にする。

= f.file_field :photograph, :multiple => true, class: "image__form"

変更前
f:id:shun_0211:20200724201945p:plain

変更後
f:id:shun_0211:20200724201810p:plain

変更前と変更後を比べると、name属性がimage[photograph]からimage[photograph][]となり、画像が配列の形で複数枚paramsに入れてコントローラー側に送れることが分かります。

② Controllerで配列の形で送られてくる画像を一枚ずつ取り出して保存処理を行う。

:multiple => trueとすることで、画像が配列の形で送られてくるので、それをeachメソッドを使って一枚ずつデータベースへ保存する記述をします。

def create
  params[:image][:photograph].each do |photograph|
    new_image = Image.new(event_id: params[:image][:event_id], photograph: photograph, user_id: current_user.id)
    new_image.save
  end
  redirect_to images_path
end


以上になります。:multiple => trueにすることでどのようにして複数枚投稿を可能にしているかが理解すれば簡単に実装できるかと思います。
ここまで読んでくださり、ありがとうございました。分かりにくいやアドバイス等ありましたらコメントくださると幸いです。では!

【rails】Carrier Waveを使った画像アップロードでハマった話

こんばんは。
今日は短いですが、無駄に時間をとられたので、備忘録として記録を残したいと思います。


carrier_waveで画像をアップロードする際、実際に値が入っているかbinding.pryを使って確認しましたが、画像をアップロードしても下図のようにカラムの中身がnilになり、データベースに画像を保存できずハマってしまいました。

※下図はアップロードに成功したときのparamsの中身です。


f:id:shun_0211:20200721212442p:plain


カラムの中が空であるのに、データベースの中身を確認するときちんと入っています。


f:id:shun_0211:20200722062411p:plain


画像のカラムの中身がnilで返されるのは仕様のようで、データベースに値が入らなかったのはNot Null制約をかけた他のカラムでバリデーションエラーになっていたからでした。エラーが出た際は必ずエラーメッセージを見るようにしたほうがいいことを学びました。(当たり前ですが・・・)


短いですが、今日はここまでになります。誰かの役に立てれば幸いです。

【rails】フォームでの選択ボックスの作り方(f.selectとf.collection_select)

おはようございます。
今日はform_forやform_withといっしょに使われるf.selectとf.collection_selectの使い方について簡単にまとめていこうと思います。
これらはフォームをクリックした際に選択して入力することができる選択ボックスが作れてすごく便利ですが、書き方を忘れていたため、備忘録として書いていきます。

f.select

データベースから情報を取得せずに選択ボックスを作成する際に使用します。

使い方

合計5つの引数をとります。

f.select (オブジェクト), プロパティ, 要素情報, オプション, 要素属性


第一引数であるオブジェクトはform_forの場合、先に書いているので省略します。
第二引数であるプロパティはデータベースに保存するモデルのカラム名を書きます。
第三引数である要素情報は選択したい情報を配列またはハッシュ形式で書きます。

# 配列
[[ 選択肢の表示名1, 実際に送信されるデータ1 ], [ 選択肢の表示名1, 実際に送信されるデータ2 ]]
# ハッシュ
{ "選択肢の表示名1" => "実際に送信されるデータ1", "選択肢の表示名1" => "実際に送信されるデータ2" }


第四引数と第五引数は省略可能で、必要に応じてオプションや要素属性を決めれます。


Ex.

f.select :name, [ [ "山田", 1 ], [ "佐々木", 2 ] ], { include_blank: "選択してください"}, class: "name"

f.collection_select

データベースから情報を取得して選択ボックスを作成する際に使用

使い方

合計7つの引数をとります。

f.collection_sellect (オブジェクト), プロパティ, オブジェクトの配列, value, text, オプション, 要素属性


第一引数と第二引数はf.selectと同様です。
第三引数では選択するオブジェクトの配列を記載します。
第四引数では実際にDBに送られる値を記載します。多くの場合、idが書かれます。
第五引数では選択ボックスに表示したい値のカラムを記載します。
第六、七引数は省略可能で、必要に応じてオプションや要素属性を決めれます。


Ex.

f.collection_select :image, @events, :id, :event_name, prompt: "イベントを選択してください"


以上になります。使い分けのポイントはデータベースから情報を引っ張るか否かというだけです。引数に何を入れたらいいかがわかれば簡単に使えると思います。
ここまで読んでくださり、ありがとうございました。分かりにくいやアドバイス等ありましたらコメントくださると幸いです。では!

カメラの超基礎知識

おはようございます。
今日はプログラミングの記事ではなく、SONYのミラーレス一眼レフα7ⅲを買ってカメラの勉強をしたのでカメラについて書いていこうと思います。カメラに関してドがつく素人ですので間違っていたり説明不足なことが多々あると思いますが、宜しくおねがいします。

カメラの基本設定

① 絞り
② シャッタースピード
③ ISO感度
④ 焦点距離
⑤ 露出

上記の順番で簡単にまとめていこうと思います。


① 絞り

写真を撮るときレンズから光を取り込む穴の大きさを表す数値のこと(F値
数字が小さいほど穴が大きく、より多くの光を取り込むことができる。(レンズごとにF値の最小値(絞り開放値)が決まっている)また、F値被写界深度(※)の値に大きく関わっておりこれを調整することで写真にボケ感を出すことができる。

できること
・明るさの調整
被写界深度の調整


被写界深度
物体面においてピントが合っている範囲のことを被写界深度という。

被写界深度計算式
f:id:shun_0211:20200712073744p:plain


Aモード(絞り優先モード)

F値を任意に設定できるモードで、適正な明るさになるよう自動で調整してくれる。


② シャッタースピード

カメラはシャッターボタンが押されたときだけ、奥にあるセンサーに光が当たり、その瞬間が写真として残る。写真を適切な明るさにするために、センサーに光を当てる時間を調整する仕組みになっている。この時間をシャッタースピードと呼ぶ。
例:1/500(1/500 sのこと)

f:id:shun_0211:20200712080524p:plain


Sモード(シャッタースピード優先モード)

シャッター速度を任意に設定できるモードで、適切な明るさになるようにF値ISO感度を調整してくれる。


③ ISO感度(International Organization Standard)

カメラは撮像素子(※)に当たった光を電気信号に変えて処理をする。その電気信号の増幅度合いを表す数値のこと(基本は100)

デメリット
光を電気的に増幅させるため、写真のノイズが増える。

※ 撮像素子
画像を電気信号に変換する素子


④ 焦点距離

焦点距離とはピントを合わせたときのレンズから撮像素子までの距離のこと

焦点距離の短いレンズ(画角が広い)
f:id:shun_0211:20200712081558p:plain

焦点距離の長いレンズ(画角が狭い)
f:id:shun_0211:20200712081655p:plain


画角 焦点距離 写る範囲 被写体の大きさ
広角レンズ 広い 短い 広い 小さい
望遠レンズ 狭い 長い 狭い 大きい


⑤ 露出

写真を撮るときに取り込まれる光の量のこと。絞りとシャッタースピードで決定される。


参考にしたサイト

https://www.nikon-image.com/enjoy/phototech/manual/19/01.html


ここまで読んでくださり、ありがとうございました。
今後はプログラミングについてに加えてこういった趣味の方もブログに挙げてこうと思っています。次はプログラミングについての記事を書く予定です。
よかったらいいねやコメントの方、宜しくおねがいします。では!

【Jquery】検索フォームのアニメーションの実装方法

おはようございます。
一年の半分が過ぎましたが、2020年いい年だったと思えるように全力でがんばっていきます!!
今回はボタンを押したら検索フォームがフワッと現れて、画面をクリックするとフワッと消える機能を実装していきたいと思います。イメージは下のような感じです。
https://gyazo.com/be1f61ffdf08372e7459ba517b8c6c28


前提

ページのコーディングが完了していること

実装の流れ

① 検索フォームにアニメーション用のクラスをつける
② CSSで初期設定を行う
③ JavaScriptで動きをつける

以上の3点になります。以前の記事を応用すればあっさり実装できます。

https://shun-0211.hatenablog.com/entry/2020/06/13/114332


① 検索フォームにアニメーション用のクラスをつける

動きをつけたい要素に対してクラスをつけます。(付けなくても実装できますが、分かりやすくするためつけてます。)

%form.header__main__search.fadeInDown     # クラス名を追記


② CSSで初期設定を行う

ページを読み込んだ際のスタイリングをします。

.fadeInDown{
  opacity : 0;    
  transform: translateY(-10px);
  transition: 1s;
}

opacityプロパティで不透明度を0にして、フォームを見えなくします。そしてtransformプロパティで要素をY方向へ10px移動しておきます。
また、transitionプロパティにて時間変化を指定します。
※ transitionプロパティ:transition効果(時間的変化)をまとめて指定する際に使用する。

これで終わりではありません。このままでは検索フォームは見えないだけで存在しているので、カーソルをあわせてクリックすると反応してしまいます。そこで、formにdisabled属性を追加して無効化します。

%input.header__main__search__form{name: "search", type: "text", placeholder: "SEARCH", disabled: 'disabled'}     # disabled属性追加


③ Javascriptで動きをつける

最後にJavascriptを書いていきます。ここでの動きは2種類に分けられます。
1 検索ボタンをクリックした際に検索フォームが現れる動き
https://gyazo.com/4ae4c0593b6a6404fbcb55828c79c68b

2 検索フォームが現れている状態で画面をクリックした際、検索フォームが消える動き
https://gyazo.com/8ee7bce42d5cf06df4d79c9fbea9b5c4

検索フォームの動きに加えてロゴやログインなどのボタンも透明度を変化させています。

function(){
# 1 検索ボタンをクリックした際に検索フォームが現れる動き
  $(".search__button").on('click', function(){
    $(".fadeInDown").css('opacity', '1');
    $(".fadeInDown").css('transform', 'translateY(0)');
    $(".header__main__button__nav").css('opacity', '0.1');     # ナビゲーションの透明度を上げる
    $(".header__main__logo").css('opacity', '0.1');     # ロゴの透明度を上げる
    $(".header__main__search__form").prop('disabled', false)     # disabled属性をfalseにし、フォームの無効化を解除
  })

# 2 検索フォームが現れている状態で画面をクリックした際、検索フォームが消える動き
  $(document).on('click', function(e){
    if($(e.target).is('.fa-search, .header__main__search__form')) {
    }else{
      $(".header__main__logo").css('opacity', '1');
      $(".header__main__button__nav").css('opacity', '1');
      $(".fadeInDown").css('opacity', '0');
      $(".fadeInDown").css('transform', 'translateY(-10px)');
      $(".header__main__search__form").prop('disabled', true);     # disabled属性をtrueにし、再度フォームを無効化
    }
  })
}


1は単純に検索ボタンをクリックしたときの処理を書いているのみになります。
2では画面がクリックされたときif以下の関数が走ります。中身としてはイベントが走った要素を取得し、それが検索フォームもしくは検索ボタンでなければ下の関数を実行します。これにより、画面をクリックした際のフォームの動きを実行できます。

(補足) function(e)

 function(e)のeはイベントオブジェクトのことで、イベントハンドラー及びイベントリスナーにおいて実行される関数の引数として受け取ることのできるオブジェクトです。そのイベントオブジェクトから発生したイベントに関する様々な情報(プロパティ)を知ることができ、またそのイベントを制御するメソッドを活用することができる。

参考
https://noumenon-th.net/programming/2017/06/24/eventobject/


以上になります。ここまで読んでくださり、ありがとうございました。分かりにくいやアドバイス等ありましたらコメントくださると幸いです。では!

【Rails】本番環境でのSNS認証ログインについて(Facebook, Twitter, Google)

おはようございます。
月に10回更新を目標にしているのですが、今日が6月の10投稿目になります。なんとか達成できそうで一安心\(^o^)/
気を引き締めて書いていきたいと思います。今回はSNS認証の本番環境での実装になります。

実装の流れ

① アプリのドメイン取得とSSL
② コールバックURLの編集

のみです!ただアプリのドメイン取得とSSL化が少し骨のいる作業になります。

① アプリのドメイン取得とSSL

まずは、アプリのドメインの取得とSSL化をしないといけません。詳しいやり方は省略しますが、アプリを本番環境で動かせているのなら、下の記事の通りにやれば問題なく実装できました。

https://qiita.com/Yuki_Nagaoka/items/1f0b814e52e603613556
https://qiita.com/Yuki_Nagaoka/items/3020f02d3fd74c8572a0
https://qiita.com/Yuki_Nagaoka/items/55ed1610cfc1f59398b1

ハマった点

一点だけハマった点があったので共有させてもらいます。
お名前.comで取得したドメインの詳細にてネームサーバーの情報を登録する操作があり、その後ターミナルでネームサーバーの確認をする作業があるのですが、待てど暮せど変更が反映されないということがありました。ネームサーバーの変更の反映には72時間ほどかかる場合があると補足がしてあったので3日くらい待っていたんですけど変更されず散々調べた結果、単純にURLの誤記が原因でした。再度ドメインを取得し直すところからやり直したところ、変更の反映30分もかからなかったです。なので、もしなかなか変更が反映されないということがあれば、簡単な誤記など疑ってみて下さい。

② コールバックURLの編集

ここまでこれれば後は簡単です。
それぞれのSNSAPIの設定で、本番環境のコールバックURLを設定するだけです。

Twitter
f:id:shun_0211:20200628083826p:plain



Facebook
f:id:shun_0211:20200628083818p:plain



google
f:id:shun_0211:20200628083934p:plain



これで無事、本番環境でSNS認証でログインすることができるようになっています。エラーが出る場合はコールバックURLがちゃんと合っているかの確認をまず行って下さい。
補足ですが、FacebookAPIではローカルのコールバックURLは設定しなくても自動で認識してくれるみたいです。めっちゃ優秀ですね。


以上で今回は終わります。ここまで読んでくださり、ありがとうございました。分かりにくいやアドバイス等ありましたらコメントくださると幸いです。では!