Обновите всплывающую подсказку на Geo Json с помощью ответной листовки при смене языка с i18n - PullRequest
0 голосов
/ 29 апреля 2020

В настоящее время я показываю Карту, благодаря букве реагирования, с компонентом Geo JSON. Я также отображаю всплывающие подсказки для некоторых стран (например, при наведении курсора на Францию ​​отображается всплывающая подсказка «Франция»). Я также использую i18n для интернационализации. Проблема в том, что когда я переключаю языки, он отлично работает для всей страницы, но не для этих подсказок.

Я думаю, что проблема в функции onEachFeature, которая вызывается только один раз, когда JSX Element Geo JSON создан, поэтому он не обновляется, когда мы переключаем языки. Я так думаю, потому что подсказки на правильном языке, когда они появляются (если язык изначально установлен на французский, подсказки на французском, если язык установлен на engli sh, они установлены на engli sh ). Но они просто не обновляются, когда мы меняем язык после инициализации компонента Geo JSON.

Надеюсь, я дал понять,

Вот мои интерфейсы:

interface position {
  latlng: LatLngLiteral,
  tooltip: string
}

interface state {
  markers: position[],
  zoom: number,
  display: position[] | any,
  geoJson: any,
  countries: { [key: string]: position }
}

Вот то, что находится в начале моего компонента:

// t is the translation function, that should translate in the selected language. It is dynamic, it means that when we switch languages, it automatically update the translated string
const { t }: { t: TFunction } = useTranslation();

const countryToString = (countries: string[]): string => countries.join(", ");
  // List of position and label of tooltip for the GeoJson object, for each country
const countries: { [key: string]: position } = {
    DEU: {
      latlng: {
        lat: 51.0834196,
        lng: 10.4234469,
      },
      tooltip: countryToString([
        t("travel.germany.munich"),
        t("travel.germany.berlin"),
        t("travel.germany.hamburg"),
        t("travel.germany.munster"),
        t("travel.germany.country"),
      ])
    },
    CZE: {
      latlng: {
        lat: 49.667628,
        lng: 15.326962,
      },
      tooltip: countryToString([
        t("travel.tchequie.prague"),
        t("travel.tchequie.country"),
      ])
    },
...
}

// List of position and tooltip for the cities Markers
const cities: position[] = [
    {
      latlng: {
        lat: 48.13825988769531,
        lng: 11.584508895874023,
      },
      tooltip: t("travel.germany.munich"),
    },
    {
      latlng: {
        lat: 52.51763153076172,
        lng: 13.40965747833252,
      },
      tooltip: t("travel.germany.berlin"),
    },
...

У меня есть список стран, который я отображаю благодаря компоненту Geo JSON и список городов, который я отображаю благодаря списку маркеров.

А затем функциональная часть:


  // Contains the json containing the polygons of the countries
  const data: geojson.FeatureCollection = geoJsonData as geojson.FeatureCollection;
  let geoJson: any = <GeoJSON
    key='my-geojson'
    data={data}
    style={() => ({
      color: '#4a83ec',
      weight: 1,
      fillColor: "#1a1d62",
      fillOpacity: 0.25,
    })}

    // PROBLEM : does not update the tooltips when we switch languages
    // FIX ME
    onEachFeature={(feature: geojson.Feature<geojson.GeometryObject>, layer: Layer) => {
      layer.on({
        'mouseover': (e: LeafletMouseEvent) => {
          const country = state.countries[e.target.feature.properties.adm0_a3];
          layer.bindTooltip(country.tooltip);
          layer.openTooltip(country.latlng);
        },
        'mouseout': () => {
          layer.unbindTooltip();
          layer.closeTooltip();
        },
      });
    }}
  />


  const [state, setState] = useState<state>({
    markers: cities,
    zoom: 3,
    geoJson: geoJson,
    display: geoJson,
    countries: countries
  });

  // Update on zoom change
  function onZoom(e: LeafletMouseEvent): void {
    const zoom = e.target._zoom;
    const newDisplay = updateDisplay(zoom);
    setState({
      ...state,
      zoom,
      display: newDisplay,
    });
  }

  // Called on every zoom change, in order to display either the GeoJson, or the cities Marker
  function updateDisplay(zoom: number): Marker[] | any {
    if (zoom >= 4) {
      return (state.markers.map(
        (
          c: position,
          i: number
        ) => {
          return (
            <Marker key={c.latlng.lat + c.latlng.lng} position={c.latlng}>
              <Tooltip>{c.tooltip}</Tooltip>
            </Marker>
          );
        }
      ));
    } else {
      return state.geoJson;
    }
  }

  return (
    <Map
      style={{ height: "500px" }}
      center={[54.370138916189596, -29.918133437500003]}
      zoom={state.zoom}
      onZoomend={onZoom}
    >
      <TileLayer url="https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw" />
      {state.display}
    </Map>
  );

Если вы хотите увидеть весь код, вы можете увидеть его там: https://github.com/TheTisiboth/WebCV/blob/WIP/src/components/customMap.tsx

1 Ответ

1 голос
/ 29 апреля 2020

Очевидно, что плагин не может обрабатывать несколько соединенных строк в виде "travel.italy.roma, travel.italy.naples, travel.italy.pompei, travel.italy.country конкатенированных и, более того, кажется, что вам нужно поместить вызов функции в разметку (не уверен на 100%, почему я не знаком с этим плагин - может быть, есть альтернатива этому).

 <Map
  style={{ height: "500px" }}
  center={[54.370138916189596, -29.918133437500003]}
  zoom={state.zoom}
  onZoomend={onZoom}
>
  <TileLayer url='https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw' />
  {state.markers.map(
    (c: position, i: number): ReactElement => {
      if (state.zoom >= 5) {
        return (
          <Marker key={i} position={[c.lat, c.lon]}>
            <Tooltip>{t(c.tooltip)}</Tooltip>
          </Marker>
        );
      } else {
        return (
          <CircleMarker
            key={i}
            center={[c.lat, c.lon]}
            color='red'
            radius={state.radius}
          >
            <Tooltip>{t(c.tooltip)}</Tooltip>
          </CircleMarker>
        );
      }
    }
  )}
</Map>

, потому что если вы зарегистрируете переменную countries, вы увидите, что нет ссылки на функцию, а только напечатанные строки. Таким образом, строка будет загружена только в первый раз и не будет изменена, потому что нет функции для вызова.

Так что более идеальным способом обработки ссылок на перевод будет иметь такую ​​форму:

Engli sh:

"travel": {
    "germany": "Munich, Berlin, Hamburg, Münster, Germany",
    "munich": "Munich",
    "tchequie": "Czech Republic, Prague",

    ...
}

Французский:

"travel": {
       "germany": "Munich, Berlin, Hambourg, Münster, Allemagne",
       "munich": "Munchen",

       "tchequie": "Tchéquie, Prague",

     ...
}

и на пользовательской карте:

  let countries: position[] = [
    {
      // germany
      lat: 51.0834196,
      lon: 10.4234469,
      tooltip: "travel.germany",
    },
    {
      // tchequie
      lat: 49.667628,
      lon: 15.326962,
      tooltip: "travel.tchequie",
    },
   ...
   ]

Обновление: Ваши города должно быть так:

 let cities: position[] = [
    {
      lat: 48.13825988769531,
      lon: 11.584508895874023,
      tooltip: "travel.munich",
    },
    ...
  ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...