Карта на Baidu с листовка за реакция

Ще говорим за:

1. Какво е react-leaflet?
2. Как да добавите плочка за карти на Baidu?
3. Как да създадете персонализиран CRS за карти на Baidu?
4. Демо връзката е в края

1. Какво е React-leaflet?

Leaflet е JavaScript библиотека с отворен код за удобни за мобилни устройства интерактивни карти, тя ще ви позволи да правите каквото искате, като добавяне на маркери, изскачащи прозорци, форми и т.н.

2. Как да добавите плочка с карти на Baidu

1-създайте ново приложение за реакция
2- Инсталирайте необходимите зависимости

$ npm i leaflet @types/leaflet react-leaflet proj4 @types/proj4 proj4leaflet @types/proj4leaflet

or 

$ yarn add leaflet @types/leaflet react-leaflet proj4 @types/proj4 proj4leaflet @types/proj4leaflet

3- отворете приложението си във vscode или каквото и да е удобно и стартирайте проекта
4- в App.tsx, импортирайте css файла на листовката и proj4leaflet (IMPORTATNT).

import "leaflet/dist/leaflet.css";
import "proj4leaflet";

5- импортирайте MapContainer, TileLayer от react-leaflet.
Вашият App.tsx трябва да е така.

import { MapContainer, TileLayer } from "react-leaflet";

// 🎀🎀🎀 don't forget those they are so important 🎀🎀🎀
import "leaflet/dist/leaflet.css";
import "proj4leaflet";

function App() {
  return (
    <div>
      <MapContainer
        style={{
          height: "100vh",
          width: "100%",
        }}
        center={[31.432026740690574, 120.8439179532812]}
        zoom={8}
      >
        <TileLayer
          // those two url are the same i just add both in case one of them get out of service
          url="https://maponline{s}.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl"
          //url="http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=1&p=1"
          subdomains={["0", "1", "2", "3"]}
          maxNativeZoom={18}
          minNativeZoom={3}
          tms
        />
      </MapContainer>
    </div>
  );
}

export default App;

6- картата няма да работи, защото трябва да предадете crs като проп към компонента MapContainer

3. Как да създадете персонализиран CRS за Baidu карти

1-създайте crs

import { bounds, Proj } from "leaflet";

// create offset incase you want to adjust the map
const offset = { x: 40, y: -210 };

// create custom CRS for Baidu maps
// 💥💥💥 important 💥💥💥 this CRS only work with Baidu map Tile
//  if you have multi Tiles they'll break
const baiduCRS = new Proj.CRS(
  "EPSG:3395",
  `+proj=merc +lon_0=0 +k=1 +x_0=${offset.x} +y_0=${offset.y} +datum=WGS84 +units=m +no_defs`,
  {
    resolutions: [
      262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, 1024, 512, 256,
      128, 64, 32, 16, 8, 4, 2, 1,
    ],
    origin: [0, 0],
    bounds: bounds([20037508.342789244, 0], [0, 20037508.342789244]),
  }
);

2- Предайте го на MapContainer като опора.
Целият код ще бъде така.

import { MapContainer, TileLayer } from "react-leaflet";
import { bounds, Proj } from "leaflet";

// 🎀🎀🎀 don't forget those they are so important 🎀🎀🎀
import "leaflet/dist/leaflet.css";
import "proj4leaflet";

// create offset incase you want to adjust the map
const offset = { x: 40, y: -210 };

// create costume CRS for Baidu maps
// 💥💥💥 important 💥💥💥 this CRS only work with Baidu map Tile
//  if you have multi Tiles they'll break
const baiduCRS = new Proj.CRS(
  "EPSG:3395",
  `+proj=merc +lon_0=0 +k=1 +x_0=${offset.x} +y_0=${offset.y} +datum=WGS84 +units=m +no_defs`,
  {
    resolutions: [
      262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, 1024, 512, 256,
      128, 64, 32, 16, 8, 4, 2, 1,
    ],
    origin: [0, 0],
    bounds: bounds([20037508.342789244, 0], [0, 20037508.342789244]),
  }
);

function App() {
  return (
    <div>
      <MapContainer
        style={{
          height: "100vh",
          width: "100%",
        }}
        // add the CRS here
        crs={baiduCRS}
        center={[31.432026740690574, 120.8439179532812]}
        zoom={8}
      >
        <TileLayer
          // those two url are the same i just add both in case one of them get out of service
          url="https://maponline{s}.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl"
          //url="http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=1&p=1"
          subdomains={["0", "1", "2", "3"]}
          maxNativeZoom={18}
          minNativeZoom={3}
          tms
        />
      </MapContainer>
    </div>
  );
}

export default App;

А сега поздравления, 🥳🥳 това е.

В приложението, върху което работя, използвам Baidu за Китай и google за други държави, като просто заменям плочката и премахвам crs prop от MapContainer. Обясних как да го направя в предишна статия.

Демо връзка 🔗

https://codesandbox.io/s/react-leaflet-baidu-maps-dyfi0j?file=/src/App.tsx

Друг китайски доставчик на карти 🔗

https://codesandbox.io/s/react-leaflet-chinese-providers-4c8fgx?file=/src/App.tsx