Baidu Map with react-leaflet
Tags: react, nextjs, typescript, javascript
Published: 2023-01-20 13:32:43

## - We'll Talk About:

1. What is react-leaflet ?
2. How to add Baidu maps tile ?
3. How to create custom CRS for Baidu maps ?
4. Demo Link is in the end 

## 1. What is react-leaflet ?
Leaflet is open-source JavaScript library for mobile-friendly interactive maps, it'll let you do what ever you want like adding markers, popups, shapes, etc...

## 2. How to add Baidu maps tile 

1-create new react app
2- Install the required dependencies
```
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- open your app in vscode or whatever is convenient and run the project 
4- in App.tsx, import leaflet css file and proj4leaflet (IMPORTATNT).

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

5- import MapContainer, TileLayer from react-leaflet.
Your App.tsx should be like this.

```typescript 
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- the map won't work because you need to pass crs as prop to the MapContainer component 

## 3. How to create custom CRS for Baidu maps
1-create the crs
```typescript
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- Pass it to MapContainer as a prop. 
The whole code will be like this.
```typescript
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;

```
And now congratulations, 🥳🥳 that's it.


In the application that I’m working on, I use Baidu for china and google for other countries by just replacing the tile and removing the crs prop from MapContainer. I explained how to do it in a previous article.


## Demo Link 🔗 

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

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


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v35jlwxe9ya56ea9j445.png)