LoginSignup
0
1

More than 3 years have passed since last update.

Geolocation APIで現在地を取得している間にローディングアニメーションが起動されるようにしてみた。

Posted at

実装のきっかけ

現在個人開発を行なっており、その際にGeolocation APIで現在地の緯度経度を取得する処理を実装していました。
現在地の取得まで最大で5秒ほどかかることがあり、従来だと以下のように何のアニメーションも表示されないので、ユーザーに不安感を抱かせてしまうと思いました。
そこで、「現在地の取得」をクリックした際にローディングアニメーションが実行されるようにすればユーザーの不安感を軽減できるのではないかと思い、実装することにしました。
現在地の取得.gif

この記事の対象となる方

  • Geolocation APIで現在地を取得する機能を実装している方
  • その上でローディングアニメーションを実装したい方

開発環境

  • Ruby 2.6.6
  • Rails 6.1.0

コード

app/views/layout/application.html.erb
  <body class="font-mono text-base sm:text-xl">
    <div class="loading_zone">
      <div class="spinner"></div>
    </div>
    <%= render  "layouts/header" %>
    <div>
      <p class="notice"><%= notice %></p>
      <p class="alert"><%= alert %></p>
      <%= yield %>
    </div>
    <%= render  "layouts/footer" %> 
  </body>
app/assets/stylesheets/application.scss
  // ローディング画面のcss

.loading_zone {
  position: fixed;
  top: 0;
  left: 0;
  opacity: 0;
  color: #f5f5f5;
}
.spinner {
  margin: 300px auto;
  width: 200px;
  height: 200px;
  background-color: #fff;
  border-radius: 100%;
  animation: sk-scaleout 1.0s infinite ease-in-out;
  @media(max-width: 500px){
    margin: 200px auto;
  }
}
/* ローディングアニメーション */
@keyframes sk-scaleout {
  0% {
    transform: scale(0);
  } 100% {
    transform: scale(1.0);
    opacity: 0;
  }
}

.loading {
  width: 100vw;
  height: 100vh;
  transition: all 1s;
  background-color:gray;
  opacity: 0.9;
  z-index: 9999;
  position: fixed;
}
app/javascript/packs/getcurrentlocation.js
  function geoFindMe() {
  const spinner = document.getElementsByClassName('loading_zone')[0];
  spinner.classList.add('loading')
  function success(position) {
    const latitude  = position.coords.latitude;
    const longitude = position.coords.longitude;
    document.getElementById('location').value = `${latitude},${longitude}`;
    spinner.classList.remove('loading'); 
  }

  function error() {
    alert('エラーが発生しました。')
  }

  if(!navigator.geolocation) {
     alert('Geolocation is not supported by your browser');
  } else {
    navigator.geolocation.getCurrentPosition(success, error);
  }
}

document.querySelector('#get_current_spot').addEventListener('click', geoFindMe);

何をやっているのか?

では一個づつ解説していきます。

app/views/layout/application.html.erb
  <body class="font-mono text-base sm:text-xl">
    <div class="loading_zone">
      <div class="spinner"></div>
    </div>
    <%= render  "layouts/header" %>
    <div>
      <p class="notice"><%= notice %></p>
      <p class="alert"><%= alert %></p>
      <%= yield %>
    </div>
    <%= render  "layouts/footer" %> 
  </body>

application.html.erbの中にローディングアニメーション用のdivを用意しています。

app/assets/stylesheets/application.scss
  // ローディング画面のcss

.loading_zone {
  position: fixed;
  top: 0;
  left: 0;
  opacity: 0;
  color: #f5f5f5;
}
.spinner {
  margin: 300px auto;
  width: 200px;
  height: 200px;
  background-color: #fff;
  border-radius: 100%;
  animation: sk-scaleout 1.0s infinite ease-in-out;
  @media(max-width: 500px){
    margin: 200px auto;
  }
}
/* ローディングアニメーション */
@keyframes sk-scaleout {
  0% {
    transform: scale(0);
  } 100% {
    transform: scale(1.0);
    opacity: 0;
  }
}

.loading {
  width: 100vw;
  height: 100vh;
  transition: all 1s;
  background-color: gray;
  opacity: 0.9;
  z-index: 9999;
  position: fixed;
}

ここで見慣れない@keyframesというコードが出てきたと思います。
@keyframesはアニメーション開始から終了するまでどのようなアニメーションをするのか指定できるCSSの文法です。
0%を開始直後、100%を終了時としています。

@keyframesについて詳しく知りたい場合はこちらを参照ください!

  .spinner {
  margin: 300px auto;
  width: 200px;
  height: 200px;
  background-color: #fff;
  border-radius: 100%;
  animation: sk-scaleout 1.0s infinite ease-in-out;
  @media(max-width: 500px){
    margin: 200px auto;
  }
}
/* ローディングアニメーション */
@keyframes sk-scaleout {
  0% {
    transform: scale(0);
  } 100% {
    transform: scale(1.0);
    opacity: 0;
  }
}

つまり、上のコードは

1.アニメーション開始時
→何も表示されない
2.アニメーション開始〜終了直前まで
→円を表示する(最大サイズは直径200px)
3.アニメーション終了時
→opacityがゼロなので、消える。

以降1~3を繰り返す。
というアニメーションになっています。

最後にJavaScriptで、クリックしたときにアニメーションが表示されるように処理を書きます。

app/javascript/packs/getcurrentlocation.js
  function geoFindMe() {
  const spinner = document.getElementsByClassName('loading_zone')[0];
  spinner.classList.add('loading')
  function success(position) {
    const latitude  = position.coords.latitude;
    const longitude = position.coords.longitude;
    document.getElementById('location').value = `${latitude},${longitude}`;
    spinner.classList.remove('loading'); 
  }

  function error() {
    alert('エラーが発生しました。')
    spinner.classList.remove('loading'); 
  }

  if(!navigator.geolocation) {
     alert('Geolocation is not supported by your browser');
  } else {
    navigator.geolocation.getCurrentPosition(success, error);
  }
}

document.querySelector('#get_current_spot').addEventListener('click', geoFindMe);

clickした後に走るgeoFindMeという関数の中に詳しい設定を書きます。
loading_zoneクラスを持つdivに対して、処理が走っている間はloadingクラスを付与、処理が終わった後はloadingクラスを削除するようにコードを書きました。

最後に

以上で、ローディングアイコンの実装が完了しました!
最後まで読んでいただき、誠にありがとうございます。

少しでも参考になったと思ったらLGTMを頂けますと幸いです!

0
1
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
0
1