Pure CSS で書く地図用マーカー(MapboxGL JS版)

[前回の記事で書いた](https://qiita.com/hal_sk/items/13f407c052ca01972176)ように、A4サイズでいい感じに印刷できる地図サービスを運用中です。

[印刷できる台風災害支援情報マップ（千葉県）](https://codeforjapan.github.io/mapprint/map.html)

![スクリーンショット 2019-09-21 13.02.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1399/8cd607b0-89b0-3fd6-d446-e2557bca2893.png)

上のサイトの構築には `MapboxGL.js` を使っています。
サイトのマーカー部分はCSSと `Font Awesome` にて実現していますが、CSS のみでマーカーを作る部分は結構ニーズありそうなので、記事に残しておこうと思いました。

もちろん Mapbox Studio でもアイコンを選ぶことができるのですが、種類はあまり多くありません。オリジナルのSVGファイルをアップすることもできるのですが、ちょっと手間ですよね。

MapboxGL.js は、マーカーの中にHTMLエレメントを入れることができるので、そちらでマーカーを配置することにします。

まずは、基本のマーカーから。
以下のような Geojson データを表示するとします。その際、class に marker 要素を持たせた div エレメントを持ったマーカーを作成します。

```javascript:javascript
mapboxgl.accessToken = 'アクセストークン';
var map = new mapboxgl.Map({
container: 'map',
center: [139.646,35.626],
zoom: 12,
style: 'mapbox://styles/georepublic/cjvw34h830hx01cpgws5f0mpt'
});
// Add pure css marker
var geojson = {
  type: 'FeatureCollection',
  features: [{
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [139.640,35.626]
    },
    properties: {
      title: 'Point1',
      number: 1
    }
  },{
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [139.653,35.626]
    },
    properties: {
      title: 'Point2',
      number: 10
    }
  }]
}
// make a marker for each feature and add to the map
geojson.features.forEach(function(marker) {
    // create a HTML element for each feature
    var el = document.createElement('div');
    el.append(document.createElement('span'))
    el.className = 'marker';
    new mapboxgl.Marker(el)
    .setLngLat(marker.geometry.coordinates)
    .addTo(map);
});
```

次に、marker クラスのスタイルを作成します。

```css:css
.marker {width:0; height:0;}

.marker  span {
  display:flex;
  justify-content:center;
  align-items:center;
  box-sizing:border-box;
  width: 30px;
  height: 30px;
  color:#fff;
  background: #693;
  border:solid 2px;
  border-radius: 0 70% 70%;
  box-shadow:0 0 2px #000;
  cursor: pointer;
  transform-origin:0 0;
  transform: rotateZ(-135deg);
}
```

このスタイルを適用すると、以下のようなマーカーが表示できます。

![スクリーンショット 2019-09-21 22.40.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1399/2f9b1e3b-ec4c-e417-fbe7-a81c79b38773.png)


## 数字入りアイコン

さらに、以下のように、アイコンの中に数字を入れることもできます。

```javascript:javascript
var geojson = {
  type: 'FeatureCollection',
  features: [{
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [139.75037,35.67087]
    },
    properties: {
      title: 'Georepublic Japan',
      number: 1
    }
  },{
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [139.75237,35.67087]
    },
    properties: {
      title: 'Point2',
      number: 10
    }
  }]
}
geojson.features.forEach(function(marker) {
    // create a HTML element for each feature
    var el = document.createElement('div');
    el.innerHTML = '<span><b class="number">' + marker.properties.number + "</b></span>";
    el.className = 'marker';
    // make a marker for each feature and add to the map
    new mapboxgl.Marker(el)
    .setLngLat(marker.geometry.coordinates)
    .addTo(map);
});
```

```css:cssに以下を追加
.marker b {transform: rotateZ(135deg)}
```

![スクリーンショット 2019-09-21 22.42.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1399/693c5c59-754e-a4d5-356e-abbb496a1031.png)

## Font Awesome をアイコンに利用

以下のように [Font Awesome](https://fontawesome.com/start) をアイコンに使うことも可能です

```javascript:javascript

// Add pure css marker
var geojson = {
  type: 'FeatureCollection',
  features: [{
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [139.75037,35.67087]
    },
    properties: {
      title: 'Georepublic Japan',
      type: 'company'
    }
  },{
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [139.75237,35.67087]
    },
    properties: {
      title: 'Ramen shop',
      type: 'restaurant'
    }
  }]
}
geojson.features.forEach(function(marker) {
    // create a HTML element for each feature
    var el = document.createElement('div');
    if (marker.properties.type == 'company'){
        el.innerHTML = '<span><i class="fas fa-building"></i></span>';
    }else if(marker.properties.type = 'restaurant'){
        el.innerHTML = '<span><i class="fas fa-utensils"></i></span>';
    }
    el.className = 'marker';
    // make a marker for each feature and add to the map
    new mapboxgl.Marker(el)
    .setLngLat(marker.geometry.coordinates)
    .addTo(map);
});
```

```css:css
.marker i {transform: rotateZ(135deg)}
```
![スクリーンショット 2019-09-21 23.03.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1399/49ff7420-06b9-f585-9a4d-097112252940.png)

いかがでしたでしょうか。CSSなので色を変えるのも容易ですし、SVGを用意するよりも手軽に使うことができます。

冒頭の私たちのサイトも、少々複雑ですがCSSとFont Awesome で作られております。

実際に動くサンプルコードは、[こちらの GitHub リポジトリ](https://github.com/Georepublic/Mapbox-tutorials/blob/master/INSTRUCTION.md) から見ることができます。