[MaaStep]CDNを利用しないLeaflet[React/Leaflet/OSM]
2019-07-10
azblob://2022/11/11/eyecatch/2019-07-10-maastep-no-cdn-leaflet-000.jpg

はじめに

以前の記事ではLeafletを用いてOpenStreetMapの地図を表示し、その上に地上絵を描きました。
その際にマーカーのアイコンはCDNから取得していたのですが、以下のようなエラーがでることがあります。

“Mixed Content: The page at 'https://<your-blog>.blogspot.com/' was loaded over HTTPS, but requested an insecure script 'http://<some-url>/script.js'. This request has been blocked; the content must be served over HTTPS.”

そのため、マーカーのアイコンをCDNから取得するのを辞めます。
このページを参考にMapComponents.jsを以下のように置き換えます。

import React, { Component } from "react";
import Leaflet from "leaflet";
import { Map, TileLayer, Polyline, Marker, Popup } from "react-leaflet";

Leaflet.Icon.Default.imagePath =
'../node_modules/leaflet'

delete Leaflet.Icon.Default.prototype._getIconUrl;

Leaflet.Icon.Default.mergeOptions({
    iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
    iconUrl: require('leaflet/dist/images/marker-icon.png'),
    shadowUrl: require('leaflet/dist/images/marker-shadow.png')
});

export default class MapSheet extends Component {
  constructor(props) {
    super(props);
    this.state = {
      lat: 34.96841,
      lng: 136.62732,
      zoom: 13,
      faceLine: [
        [35.007904, 136.597519],
        [35.02664, 136.622259],
        [34.982158, 136.631795],
        [34.965716, 136.614922],
        [34.970725, 136.555688],
        [34.99368, 136.542041],
        [35.032062, 136.562559],
        [35.009322, 136.577461],
        [35.007904, 136.597519]
      ],
      eyeLine1: [[34.997932, 136.600816], [34.991654, 136.599221]],
      eyeLine2: [[34.999107, 136.572963], [34.991705, 136.569218]],
      currentLocation: {
        coords: {
          lat: 34.96841,
          lng: 136.62732
        }
      },
      markers: [
        {
          title: "marker1",
          coordinates: {
            lat: 35.02664,
            lng: 136.622259
          }
        },
        {
          title: "marker2",
          coordinates: {
            lat: 35.032062,
            lng: 136.562559
          }
        }
      ],
      popup: {
        title: "",
        coordinates: {
          lat: 34.983396,
          lng: 136.587074
        }
      }
    };
  }

  render() {
    const osmAttribution =
      '&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors';
    const osmDefaultUrl = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";

    const position = [this.state.lat, this.state.lng];

    return (
      <Map center={position} zoom={this.state.zoom}>
        <TileLayer attribution={osmAttribution} url={osmDefaultUrl} />
        <Polyline positions={this.state.faceLine} />
        <Polyline positions={this.state.eyeLine1} />
        <Polyline positions={this.state.eyeLine2} />
        <Popup
          position={this.state.popup.coordinates}
          autoClose={false}
          closeButton={false}
        >
          {this.state.popup.title}
        </Popup>
        {this.state.markers.map((marker, index) => (
          <Marker key={index} position={marker.coordinates} />
        ))}
      </Map>
    );
  }
}

これによって、Mixed Contentのエラーが消えるはずです。

おわりに

CDNから取得していたマーカーのアイコンをモジュールから取得する方法を紹介しました。
いくつかのサイトではLeaflet.Icon.Default.imagePathを書き換えるだけでうまくいっているのですが、私の環境ではうまくいかなくて解決に時間がかかりました。