[Mapbox]MUIのアイコンをマーカー(Marker)として地図に表示する

react-map-glのMarkerを使って、地図上にMUIのアイコンを表示します。

ここでは、mapMarkersオブジェクトが持つtopic_category_keyによって、表示するアイコンを変更するように実装しています。

目次

MarkerIconコンポーネントを作成

Mapboxの地図上に表示したいMUIのアイコンを定義します。

先頭でMUIのアイコンをインポートします。
コードは、Material Iconsのサイトからコピーしてきます。

Propsでtopic_category_keyを受け取り、その値に応じて返すIconを指定してreturnします。
MUIの書き方でsxプロパティを使うと、任意のCSSが追加できます。
MUIのIconはsvgなので、svgで使用できるstrokeプロパティなどを使っています。

import HolidayVillageIcon from '@mui/icons-material/HolidayVillage'
import StorefrontIcon from '@mui/icons-material/Storefront'
import LocationOnIcon from '@mui/icons-material/LocationOn'
import styled from 'styled-components'
import React from 'react'

interface Props {
  topic_category_key: number
}

export default React.memo(function MarkerIcon(props: Props) {
  switch (props.topic_category_key) {
    case 1:
      return (
        <MarkerIconWrapper>
          <HolidayVillageIcon
            sx={{ color: '#386E7C', fontSize: 40, strokeWidth: '4px', stroke: '#fff', paintOrder: 'stroke' }}
          />
        </MarkerIconWrapper>
      )
    case 2:
      return (
        <MarkerIconWrapper>
          <StorefrontIcon
            sx={{ color: '#EDA83D', fontSize: 40, strokeWidth: '6px', stroke: '#fff', paintOrder: 'stroke' }}
          />
        </MarkerIconWrapper>
      )
    default:
      return (
        <MarkerIconWrapper>
          <LocationOnIcon
            sx={{ color: '#CEDBD0', fontSize: 40, strokeWidth: '4px', stroke: '#fff', paintOrder: 'stroke' }}
          />
        </MarkerIconWrapper>
      )
  }
})

const MarkerIconWrapper = styled.div`
  svg {
    transition: 0.3s all;
  }
`

styled-componentsでMarkerIconWrapperを作成したのは、Iconをhoverした時にtransitionしてほしかったためです。
本記事では関連するコンポーネントは書きません。

mapMarkersオブジェクトを定義

mapMarkersオブジェクトを定義します。
緯度経度とMarkerIconコンポーネントで表示したいtopic_category_keyをセットします。

実際はAPIから取得して動的にセットすることになると思います。

const mapMarkers = [
  {
    "id": "marker1",
    "lng": -0.1257,
    "lat": 51.508,
    "topic_category_key": 1
  },
  {
    "id": "marker2",
    "lng": -0.1275,
    "lat": 51.507,
    "topic_category_key": 2
  },
  {
    "id": "marker3",
    "lng": -0.1425,
    "lat": 51.500,
    "topic_category_key": 3
  },
]

MapにIconを描画する

react-map-glのMapコンポーネントのchildrenに渡してMarkerを描画します。

mapMarkersオブジェクトをmapで回し、MapMarkerコンポーネントを生成します。
MapMarkerの中でMarkerIconを呼び出し、MUIのIconを表示します。

<Map
      id='map'
      initialViewState={{
        zoom: 17
      }}
      reuseMaps
      mapStyle={'mapbox://styles/mapbox/streets-v11'}
      mapboxAccessToken={process.env.NEXT_PUBLIC_MAP_BOX_TOKEN}
    >
      <NavigationControl />
      {mapMarkers.map(m => {
        return (
          <MapMarker
            key={m.id}
            longitude={m.lng}
            latitude={m.lat}
            anchor='center'
            style={{ cursor: 'pointer' }}
          >
            <MarkerIcon topic_category_key={m.topic_category_key} />
          </MapMarker>
        )
      })}
    </Map>

こんな感じに表示されます。

Summary

MapboxのAPIは分かりやすく、呼び出しやすいです。

任意のsvgファイルを読み込むこともできますが、作成する時間がなければMUIのIconで代用するのもありですね。

よかったらシェアしてね!
目次