ANTON072
4/25/2015 - 8:25 AM

Vue.jsとgoogle mapでフィルタリング http://bl.ocks.org/ANTON072/7d40c96899c3b4d087d2

Vue.jsとgoogle mapでフィルタリング http://bl.ocks.org/ANTON072/7d40c96899c3b4d087d2

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/3.0.1/normalize.min.css">
  <style type="text/css">
    .wrap {
      padding: 30px;
    }
    .nav {
      margin-bottom: 20px;
    }
    .map {
      width: 600px;
      height: 400px;
      margin-bottom: 20px;
    }
    .debug {
      width: 600px;
    }
    .debug textarea {
      width: 100%;
      height: 450px;
      box-sizing: border-box;
    }
  </style>
</head>
<body>

  <div id="app" class="wrap">

    <div class="nav">
      <select v-model="data.area">
        <option value="all" selected>All</option>
        <option value="nakano">中野区</option>
        <option value="shinjuku">新宿区</option>
        <option value="suginami">杉並区</option>
      </select>
      <label><input type="radio" name="price" v-model="data.price" checked value="all"> All</label>
      <label><input type="radio" name="price" v-model="data.price" value="10"> 10万円</label>
      <label><input type="radio" name="price" v-model="data.price" value="20"> 20万円</label>
      <label><input type="radio" name="price" v-model="data.price" value="30"> 30万円</label>
    </div>

    <div class="map" id="map_canvas"></div>

    <div class="debug">
      <pre>{{debug}}</pre>
    </div>

  </div><!-- /app -->

  <script src="//maps.googleapis.com/maps/api/js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/0.11.5/vue.min.js"></script>
  <script>

  var areaData = {
    nakano: [
      { name: 'nakanoA', price: 10, latLng: [35.71, 139.665283] },
      { name: 'nakanoB', price: 20, latLng: [35.72, 139.665283] },
      { name: 'nakanoC', price: 20, latLng: [35.70, 139.666] }
    ],
    shinjuku: [
      { name: 'shinjukuA', price: 10, latLng: [35.691638, 139.704616] },
      { name: 'shinjukuB', price: 20, latLng: [35.70, 139.704616] },
      { name: 'shinjukuC', price: 30, latLng: [35.68, 139.704616] }
    ],
    suginami: [
      { name: 'suginamiA', price: 10, latLng: [35.705385, 139.649867] },
      { name: 'suginamiB', price: 20, latLng: [35.71, 139.649867] },
      { name: 'suginamiC', price: 30, latLng: [35.69, 139.649867] }
    ]
  };

  var $mapCanvas = document.querySelector('#map_canvas');
  var mapOptions = {
    center: {lat: 35.702941, lng:139.665283},
    zoom: 13,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  var map = new google.maps.Map($mapCanvas, mapOptions);

  var getFilteredData = function(aData) {
    return _(areaData)
      .chain()
      .map(function(arr, key){
        _(arr).each(function(o){
          o.area = key;
        });
        return arr;
      })
      .reduce(function(prev, current){
        return prev.concat(current);
      })
      .filter(function(o){
        // エリアのフィルタ
        return aData.area === 'all' ? o : o.area === aData.area;
      })
      .filter(function(o){
        // priceのフィルタ
        return aData.price === 'all' ? o : ( o.price + '' ) === ( aData.price + '' );
      })
      .value();
  };

  var markers = new google.maps.MVCArray();

  var createMarker = function(opts) {
    return new google.maps.Marker(opts);
  };

  var clearMarker = function() {
    if (!markers.length) return;
    markers.forEach(function(marker){
      marker.setMap(null);
    });
    markers = [];
  };

  var updateGmap = function(aData) {
    var filteredData = getFilteredData(aData);
    clearMarker();
    if (!filteredData.length) return;
    _(filteredData).each(function(aData){
      markers.push(createMarker({
        map: map,
        position: new google.maps.LatLng(aData.latLng[0], aData.latLng[1])
      }));
    });
  };

  var vm = new Vue({
    el: '#app',
    data: {
      data: {
        area: '',
        price: ''
      }
    },
    ready: function() {
      this.$watch('data', function(aData){
        updateGmap( aData );
      }, true, true);
    },
    computed: {
      debug: function() {
        return JSON.stringify(this.$data.data);
      }
    }
  });

  </script>

</body>
</html>