Skip to content

Instantly share code, notes, and snippets.

@isabellachen
Last active January 31, 2020 13:03
Show Gist options
  • Save isabellachen/c39562e9e5ef8a0c6bfc5f5da653f2b2 to your computer and use it in GitHub Desktop.
Save isabellachen/c39562e9e5ef8a0c6bfc5f5da653f2b2 to your computer and use it in GitHub Desktop.
React simple maps with react tooltip on a marker
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
  ComposableMap,
  Geographies,
  Geography,
  Marker,
  ZoomableGroup,
} from 'react-simple-maps';
import ReactTooltip from 'react-tooltip';
import numberConvertAndRound from '~/core/constants/NumberConversion';
import { DatacenterLocation } from '~/model/dashboard/datacenterLocation';
import { MeasureTypeIdStringEnum } from '~/model/measure';
import './map.scss';

const assets = require('./world-50m.json');

type DataCenterLocationProps = {
  dataCenterLocationsItems: DatacenterLocation[];
};

export function Map(props: DataCenterLocationProps) {
  const { dataCenterLocationsItems } = props;
  const [tooltipContent, setTooltipContent] = useState('');
  const [t] = useTranslation();

  //Make sure tooltip don't persist when scroll
  useEffect(() => {
    window.addEventListener('scroll', handleScroll, true);
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  //Must rebuild tooltip when items loaded from mobx store
  useEffect(() => {
    ReactTooltip.rebuild();
  }, [dataCenterLocationsItems]);

  const handleScroll = () => {
    setTooltipContent('');
  };

  return (
    <div className="map-wrapper">
      <ComposableMap
        projectionConfig={{
          scale: 135,
        }}
        width={610}
        height={411}
        viewBox={'0 0 610 411'}
        style={{
          width: '100%',
          height: '100%',
        }}
      >
        <ZoomableGroup center={[0, 0]}>
          <Geographies geography={assets}>
            {({ geographies }) =>
              geographies.map(geography => (
                <Geography key={geography.rsmKey} geography={geography} />
              ))
            }
          </Geographies>
          {dataCenterLocationsItems &&
            dataCenterLocationsItems.map((dataCenter, i) => {
              const dataCenterSize = numberConvertAndRound(
                dataCenter.size!,
                MeasureTypeIdStringEnum.Bytes,
              );
              return (
                <Marker
                  key={i}
                  data-tip=""
                  coordinates={[8.5, 47.3]}
                  onMouseEnter={() => {
                    setTooltipContent(`
                  <span class='tooltip-content'>
                    <div class='tooltip-content__single'>
                      <b>${t('dashboard.map.tooltip.datacenter')}</b>
                      ${dataCenter.dataCenter}
                    </div>
                    <div class='tooltip-content__single'>
                      <b>${t('dashboard.map.tooltip.location')}</b>
                      ${dataCenter.location}
                    </div>
                    <div class='tooltip-content__single'>
                      <b>${t('dashboard.map.tooltip.name')}</b>
                      ${dataCenter.name}
                    </div> 
                    <div class='tooltip-content__single'>
                      <b>${t('dashboard.map.tooltip.size')}</b>
                      ${dataCenterSize.value}${dataCenterSize.unit}
                    </div>
                  </span>`);
                  }}
                  onMouseLeave={() => {
                    setTooltipContent('');
                  }}
                >
                  <circle
                    cx={2}
                    cy={2}
                    r={3}
                    style={{
                      stroke: '#FF5722',
                      strokeWidth: 3,
                      opacity: 0.9,
                    }}
                  />
                </Marker>
              );
            })}
        </ZoomableGroup>
      </ComposableMap>
      <ReactTooltip className="tooltip-wrapper" effect="solid" html={true}>
        {tooltipContent}
      </ReactTooltip>
    </div>
  );
}
@isabellachen
Copy link
Author

The tooltip should not move.

sidra-map-move-error (1)

@isabellachen
Copy link
Author

With code above, tooltip does not move and scroll removes the tooltip.
sidra-map-move-fixed (1)
sidra-map-move-fix-scroll (1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment