読者です 読者をやめる 読者になる 読者になる

firebaseホスティングサービスの登録からデプロイまで

その他技術 firebase

firebaseの記事を最近見るようになってきたので試しに触ってみる。

プロジェクトの作成

https://firebase.google.com/

「無料で開始」をクリック。

「新規プロジェクトを作成」をクリック。

「プロジェクト名」、「国 / 地域」を入力、選択して「プロジェクトを作成」をクリック。

CLIの導入

ローカルの開発用ディレクトリを作成する。今回は C:\dev\firebase に作成した。

作成した開発用ディレクトリに移動し、コンソール(ターミナル)を開く。

次のコマンドでnpmからCLIをインストールする。

npm i firebase-tools -g

ログイン。

firebase login

f:id:kosumoro:20161015140018j:plain

初期化。いくつか質問されるので答えていく。

firebase init

f:id:kosumoro:20161015140805j:plain

  • Are you ready to proceed? => Y
  • What Firebase CLI features do you want to setup for this folder? => Hosting

f:id:kosumoro:20161015141148j:plain

  • What Firebase project do you want to associate as default? => cosmolab(プロジェクトの作成で作成したプロジェクト名)
  • What file should be used for Database Rules? => database.rules.json(EnterクリックだけでOK)
  • What do you want to use as your public directory? => public(EnterクリックだけでOK)
  • Configure as a single-page app => y

初期化を行うとローカルに次のようなファイルが作成される。

+ public/
|   + index.html
|
+ .firebaserc
+ database.rules.json
+ firebase.json

デプロイ

firebase deploy

【JavaScript実験】 即時関数を利用したループ

JavaScript

即時関数に名前を与えると再帰処理が便利になる。

scripts/script.js

(function loop_(i) {
  console.log("loop_: ", i);
  
  if(i < 10) {
    loop_(i+1);
  }
})(0);

loop_(0);

名前空間の汚染も無い。

f:id:kosumoro:20161009234735j:plain

【JavaScript実践】 Google Map上に大阪市内の保育所を表示する

JavaScript

この記事では以下の画面を作成する。

f:id:kosumoro:20161009131344j:plain

https://cosmology233.github.io/sandbox/hatena/2016/10/08/

Google Maps APIを利用してページに大阪市内の保育所を表示する。

必要なデータは大阪市のオープンデータを利用する。

大阪市市政 マップナビおおさかオープンデータ一覧

csvファイルを直接参照できればよいが、httpsに対応していないようなのでデータをダウンロードして使用する。

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
  <title>Practice JavaScript</title>
  <link rel="stylesheet" href="./styles/style.css">
</head>
<body>
  <div id="gmap" class="gmap"></div>

  <script src="./scripts/script.js"></script>
  <script src="//maps.googleapis.com/maps/api/js?key=AIzaSyBAVKOgsqfbsINYt2qjoLMziacVp6N8zBY&callback=initMap"></script>
</body>
</html>

data/schools.csv

https://github.com/cosmology233/sandbox/blob/gh-pages/hatena/2016/10/08/data/schools.csv

Githubcsvファイルをアップロードすると自動的にテーブルで表示してくれるようだ。

styles/style.css

body {
  padding: 0; margin: 0;
}

.gmap {
  width: 100%; height: 100vh;
}

scripts/script.js

alert("データは大阪市(http://www.city.osaka.lg.jp/toshikeikaku/page/0000250227.html#mapnavi)のものです。");

function initMap() {
  var container = document.getElementById("gmap");
  var map = new google.maps.Map(container);
  
  map.setOptions({
    "zoom": 13,
    "center": {
      "lat": 34.702,
      "lng": 135.495
    }
  });
  
  getSchoolsData("./data/schools.csv", function(data) {
    data.forEach(function(datum) {
      var marker = new google.maps.Marker();
      var infoWindow = new google.maps.InfoWindow();
      
      if(datum.category != "保育所") {
        return false;
      }
      
      marker.setOptions({
        "map": map,
        "position": datum.coords
      });
      
      infoWindow.setOptions({
        "content": "" + 
            "<p>" +
              "<strong>" +
                "<a href=\"" + datum.url + "\">" + datum.name + "</a>" +
              "</strong>" +
              "<br>" +
              "<small>" +
                datum.address +
              "</small>" +
            "</p>"
      });

      marker.addListener("click", () => {
        infoWindow.open(map, marker);
      });
    });
  });
  
  function getSchoolsData(path, callback) {
    var xhr = new XMLHttpRequest();
    var schoolsData = [];
    
    xhr.open("GET", path);
    xhr.addEventListener("load", function(ev) {
      var csvData = ev.target.response.split("\n").map(function(datum) {
        return datum.split(",");
      });
      
      csvData.forEach(function(datum, i) {
        if(i == 0) {
          return false;
        }
        
        schoolsData.push({
          "name": datum[2],
          "category": datum[16],
          "address": datum[5],
          "url": datum[11],
          "coords": {
            "lat": Number(datum[1]),
            "lng": Number(datum[0])
          }
        });
      });
      
      callback(schoolsData);
    });
    xhr.send();
  }
}

【JavaScript実践】 Google Map上に阿倍野区域のポリゴンを表示する

JavaScript

この記事では以下の画面を作成する。

f:id:kosumoro:20161009122003j:plain

https://cosmology233.github.io/sandbox/hatena/2016/10/09/

Google Maps APIを利用してページに阿倍野区域のポリゴンを表示する。

座標データは大阪市のオープンデータを利用する。

大阪市市政 マップナビおおさかオープンデータ一覧

KMZファイルは7zipを使用してKMLファイルに変換しておく。今回は変換後、 osaka.kml にリネームした。

圧縮・解凍ソフト 7-Zip

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
  <title>Practice JavaScript</title>
  <link rel="stylesheet" href="./styles/style.css">
</head>
<body>
  <div id="gmap" class="gmap"></div>

  <script src="./scripts/script.js"></script>
  <script src="//maps.googleapis.com/maps/api/js?key=AIzaSyBAVKOgsqfbsINYt2qjoLMziacVp6N8zBY&callback=initMap"></script>
</body>
</html>

data/osaka.kml

省略。

https://github.com/cosmology233/sandbox/blob/gh-pages/hatena/2016/10/09/data/osaka.kml

styles/style.css

body {
  padding: 0; margin: 0;
}

.gmap {
  width: 100%; height: 100vh;
}

scripts/script.js

alert("座標データは大阪市(http://www.city.osaka.lg.jp/toshikeikaku/page/0000250227.html#kuiki)のものです。");

function initMap() {
  var container = document.getElementById("gmap");
  var map = new google.maps.Map(container);
  
  map.setOptions({
    "zoom": 14,
    "center": {
      "lat": 34.634827,
      "lng": 135.514045
    }
  });
  
  getGeometryData("./data/osaka.kml", function(data) {
    data.forEach(function(datum) {
      var polygon = new google.maps.Polygon({
        "paths": datum.coords,
        "strokeColor": "#F33",
        "strokeOpacity": "0.6",
        "strokeWeight": 1,
        "fillColor": "#F33",
        "fillOpacity": "0.3"
      });
      
      polygon.setMap(map);
    });
  });
  
  function getGeometryData(path, callback) {
    var xhr = new XMLHttpRequest();
    var result = [];
    
    xhr.open("GET", path);
    xhr.addEventListener("load", function(ev) {
      var places = ev.target.responseXML.getElementsByTagName("Placemark");
      
      [].forEach.call(places, function(place) {
        var placeName = place.getElementsByTagName("name")[0].textContent;
        var coordsStr = place.querySelector("outerBoundaryIs coordinates").textContent.trim();
        var coords = [];
        
        if(placeName != "阿倍野区") {
          return false;
        }
        
        coords = coordsStr.split(" ").map(function(coordStr) {
          return {
            "lat": Number(coordStr.split(",")[1]),
            "lng": Number(coordStr.split(",")[0])
          };
        });
        
        result.push({
          "name": placeName,
          "coords": coords
        });
      });
        
      callback(result);
    });
    xhr.send();
  }
}

【JavaScript実験】 カメラの映像を取得する

JavaScript

スマートフォンのカメラから映像を取得して <video> タグで描画するサンプルを作成した。

フロントカメラ、リアカメラの指定もできるようだが、どう頑張ってもフロントカメラの映像しか取得できなかった。

https://cosmology233.github.io/sandbox/hatena/2016/10/03/

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
  <link rel="stylesheet" href="./styles/style.css">
  <title>Practice JavaScript</title>
</head>
<body>
  <video id="video" width="256" height="256" autoplay></video>
  
  <script src="./scripts/script.js"></script>
</body>
</html>

scripts/script.js

(function() {
  navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
  
  var video = document.getElementById("video");
  
  navigator.getUserMedia({
    "video": {
      "facingMode": {
        "exact": "environment"
      }
    }
  },
  function(stream) {
    video.src = URL.createObjectURL(stream);
    video.play();
  },
  function(error) {
    alert("ERROR: ", error);
  });
})();

【JavaScript実践】 言語処理100本ノック

JavaScript

「第1章: 準備運動」の途中まで。

www.cl.ecei.tohoku.ac.jp

(function() {
  console.log(q03());
  
  function q00() {
    // 文字列"stressed"の文字を逆に(末尾から先頭に向かって)並べた文字列を得よ.
    
    var str = "stressed";
    var result = "";
    
    for(var i = str.length; i > 0; i--) {
      result += str[i - 1];
    }
    
    return result;
  }
  
  function q01() {
    // 「パタトクカシーー」という文字列の1,3,5,7文字目を取り出して連結した文字列を得よ.
    
    var str = "パタトクカシーー";
    
    return str[0] + str[2] + str[4] + str[6];
  }
  
  function q02() {
    // 「パトカー」+「タクシー」の文字を先頭から交互に連結して文字列「パタトクカシーー」を得よ.
    
    var strArr = "パトカー".split("");
    var str2Arr = "タクシー".split("");
    var result = "";
    
    while(strArr.length > 0 && str2Arr.length > 0) {
      result += strArr.length > 0? strArr.shift(): "";
      result += str2Arr.length > 0? str2Arr.shift(): "";
    }
    
    return result;
  }
  
  function q03() {
    // "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."という文を単語に分解し,
    // 各単語の(アルファベットの)文字数を先頭から出現順に並べたリストを作成せよ.
    
    var str = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.";
    var wordsArr = str.match(/[a-zA-Z]+/g);
    var result = wordsArr.map(function(word) {
      return word.length;
    });
    
    return result;
  }
  
  function q04() {
    // "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."という文を単語に分解し,
    // 1, 5, 6, 7, 8, 9, 15, 16, 19番目の単語は先頭の1文字,それ以外の単語は先頭に2文字を取り出し,
    // 取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ.
    
    var str = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.";
    var wordsArr = str.match(/[a-zA-Z]+/g);
    var result = wordsArr.map(function(word, i) {
      var r = {};
      
      switch(i + 1) {
        case 1:
        case 5:
        case 6:
        case 7:
        case 8:
        case 9:
        case 15:
        case 16:
        case 19:
          r[word.substr(0, 1)] = i + 1;
          break;
        default:
          r[word.substr(0, 2)] = i + 1;
      }
      
      return r;
    });
    
    return result;
  }
  
  function q05() {
    // 与えられたシーケンス(文字列やリストなど)からn-gramを作る関数を作成せよ.
    // この関数を用い,"I am an NLPer"という文から単語bi-gram,文字bi-gramを得よ.
    
    var str = "I am an NPLer";
    
    console.log(getNGram(str.match(/[a-zA-Z]+/g), 2));
    
    return {
      "words": getNGram(str.match(/[a-zA-Z]+/g), 2),
      "chars": getNGram(str.split(""), 2)
    };
    
    function getNGram(arr, n) {
      var nGram = [];
      var i = 0, j = 0;
      
      for(i = 0; i < n; i++) {
        nGram[j] = (function() {
          var charsArr = nGram[j] || [];
          
          charsArr.push(arr.shift() || "");
          
          return charsArr;
        })();
      }
      
      while(arr.length > 0) {
        nGram.push((function() {
          var charsArr = [].concat(nGram[j]);
          
          charsArr.push(arr.shift());          
          charsArr.shift();
          
          return charsArr;
        }()));
        
        j = j + 1;
      }
      
      return nGram;
    }
  }
  
  function q06() {
    // "paraparaparadise"と"paragraph"に含まれる文字bi-gramの集合を,それぞれ, XとYとして求め,XとYの和集合,積集合,差集合を求めよ.
    // さらに,'se'というbi-gramがXおよびYに含まれるかどうかを調べよ.
  }
  
  function q07() {
    // 引数x, y, zを受け取り「x時のyはz」という文字列を返す関数を実装せよ.
    // さらに,x=12, y="気温", z=22.4として,実行結果を確認せよ.
  }
  
  function q08() {
    // 与えられた文字列の各文字を,以下の仕様で変換する関数cipherを実装せよ.
    //   * 英小文字ならば(219 - 文字コード)の文字に置換
    //   * その他の文字はそのまま出力
    // この関数を用い,英語のメッセージを暗号化・復号化せよ.
  }
  
  function q09() {
    // スペースで区切られた単語列に対して,各単語の先頭と末尾の文字は残し,それ以外の文字の順序をランダムに並び替えるプログラムを作成せよ.
    // ただし,長さが4以下の単語は並び替えないこととする.
    // 適当な英語の文(例えば"I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind .")を与え,
    // その実行結果を確認せよ.
  }
})();

【JavaScript実践】 Google Map上に2点間の経路を表示する

JavaScript

この記事では以下の画面を作成する。

f:id:kosumoro:20161002221813j:plain

2点の座標を指定し、座標間の移動経路を描画する。

https://cosmology233.github.io/sandbox/hatena/2016/09/30/

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
  <link rel="stylesheet" href="./styles/style.css">
  <title>Practice JavaScript</title>
</head>
<body>
  <div id="gmap" class="gmap"></div>
  
  <script src="./scripts/script.js"></script>
  <script src="//maps.googleapis.com/maps/api/js?key=AIzaSyBAVKOgsqfbsINYt2qjoLMziacVp6N8zBY&callback=initMap"></script>
</body>
</html>

styles/style.css

body {
  margin: 0; padding: 0;
}

.gmap {
  margin: 0; padding: 0;
  width: 100%; height: 100vh;
}

scripts/script.js

function initMap() {
  var container = document.getElementById("gmap");
  var map = new google.maps.Map(container);
  var directionsService = new google.maps.DirectionsService();
  var directionsDisplay = new google.maps.DirectionsRenderer();
  
  map.setOptions({
    "zoom": 13,
    "center": {
      "lat": 34.647,
      "lng": 35.513
    }
  });
  
  directionsDisplay.setMap(map);
  
  directionsService.route({
    "travelMode": google.maps.TravelMode.DRIVING,
    "origin": {
      "lat": 34.647,
      "lng": 135.513
    },
    "destination": {
      "lat": 34.693,
      "lng": 135.502
    }
  }, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      directionsDisplay.setDirections(response);
    }
    else {
      window.alert("Failed: " + status);
    }
  });
}