I'm working on a map visualization using D3.js and GeoJSON data for Russian federal districts. The goal is to display each district as a filled polygon fill to highlight certain areas.
I followed the advice from this Stack Overflow answer to invert the polygons, applying this transformation globally to each district:
[
[0, 90], [180, 90], [180, -90], [0, -90], [-180, -90], [-180, 0], [-180, 90], [0, 90]
]
This approach worked well for all districts except showing a weird line for the Siberian Federal District on the top left 
I tried to play with the transformation array (flipping, changing order, scaling) but haven't succeed to fix it.
Would appreciate any help!
Component code:
function Map({
statistics,
style = {},
colorsForScale = ["#F4F3EE", "#969AFF", "#000"]
}) {
useEffect(() => {}, [statistics]);
// Map
const [regionDescription, setRegionDescription] = useState("");
const [regionValue, setRegionValue] = useState("");
const { language } = useLanguage();
const [translations, setTranslations] = useState([]);
useEffect(() => {
getTranslations()
.then((data) => {
setTranslations(data);
})
.catch((err) => {})
.finally(() => {});
}, []);
const projection = d3geo
.geoConicConformal()
.scale(300)
.center([54, 44])
.rotate([-110, 0]);
console.log('projection',projection)
const path = d3geo.geoPath().projection(projection);
console.log('path',path)
const values = statistics.map((item) => item.value);
const min = Math.min(0);
const max = Math.max(100);
const getScale = () => {
return [min, (min + max) / 2, max];
};
var colorScale = d3.scaleLinear(getScale(), colorsForScale);
const mapElements = useMemo(() => {
if (statistics.length > 0) {
console.log('geoData.features',geoData.features)
return geoData.features.map((d, index) => {
const pathD = path(d);
if (!pathD) return null; // Skip if path is not defined
const relevantStatistics = statistics.filter(
(item) => item.name === d.properties.name
)[0];
const color = relevantStatistics
? colorScale(relevantStatistics?.value)
: "lightgrey";
return (
<path
key={"map-element-" + d.properties.name}
name={d.properties.name}
d={path(d)}
fill= {color}
stroke="#0e1724"
strokeWidth="0.5"
strokeOpacity="0.5"
opacity="0.9"
onMouseEnter={(e) => {
d3.select(e.target).attr("opacity", 1);
if (language === "ru") {
setRegionDescription(relevantStatistics.name);
} else {
const translation = translations.find(
(t) => t.name_ru === relevantStatistics.name
);
setRegionDescription(
translation ? translation.name_en : relevantStatistics.name
);
}
setRegionValue(Math.round(relevantStatistics.value));
}}
onMouseOut={(e) => {
d3.select(e.target).attr("opacity", 0.9);
setRegionDescription("");
setRegionValue("");
}}
/>
);
});
} else {
return (
<>
<p>No map data.</p>
</>
);
}
}, [geoData, statistics]);
// Legend
const mapTooltip = useRef(null);
useEffect(() => {
if (!mapTooltip.current) return;
}, [mapTooltip]);
const setTooltipPosition = (x, y) => {
if (!mapTooltip.current) return;
let newX = x - mapTooltip.current.offsetWidth / 2;
newX = Math.max(newX, 0);
mapTooltip.current.style.transform = `translate(${newX}px, ${y + 12}px)`;
};
if (statistics) {
return (
<div
onPointerMove={(ev) => {
setTooltipPosition(ev.clientX, ev.clientY);
}}
style={{ position: "relative", display: "inline-block", ...style }}
>
<svg className="map">
<g className="map">{mapElements}</g>
</svg>
<div
className={`map-tooltip ${!regionDescription && "hidden"}`}
ref={mapTooltip}
>
{/* <div className="tip"></div> */}
{regionDescription && (
<>
<h3>{regionDescription}</h3>
<h1>{regionValue}%</h1>
</>
)}
</div>
</div>
);
}
return <></>;
}
export default Map;